aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target/i386/cpu.c41
-rw-r--r--target/i386/cpu.h1
-rw-r--r--target/i386/kvm.c12
3 files changed, 54 insertions, 0 deletions
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index b9d6f32945..296ef6c918 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -4416,6 +4416,42 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
assert(!(*eax & ~0x1f));
*ebx &= 0xffff; /* The count doesn't need to be reliable. */
break;
+ case 0x1F:
+ /* V2 Extended Topology Enumeration Leaf */
+ if (env->nr_dies < 2) {
+ *eax = *ebx = *ecx = *edx = 0;
+ break;
+ }
+
+ *ecx = count & 0xff;
+ *edx = cpu->apic_id;
+ switch (count) {
+ case 0:
+ *eax = apicid_core_offset(env->nr_dies, cs->nr_cores,
+ cs->nr_threads);
+ *ebx = cs->nr_threads;
+ *ecx |= CPUID_TOPOLOGY_LEVEL_SMT;
+ break;
+ case 1:
+ *eax = apicid_die_offset(env->nr_dies, cs->nr_cores,
+ cs->nr_threads);
+ *ebx = cs->nr_cores * cs->nr_threads;
+ *ecx |= CPUID_TOPOLOGY_LEVEL_CORE;
+ break;
+ case 2:
+ *eax = apicid_pkg_offset(env->nr_dies, cs->nr_cores,
+ cs->nr_threads);
+ *ebx = env->nr_dies * cs->nr_cores * cs->nr_threads;
+ *ecx |= CPUID_TOPOLOGY_LEVEL_DIE;
+ break;
+ default:
+ *eax = 0;
+ *ebx = 0;
+ *ecx |= CPUID_TOPOLOGY_LEVEL_INVALID;
+ }
+ assert(!(*eax & ~0x1f));
+ *ebx &= 0xffff; /* The count doesn't need to be reliable. */
+ break;
case 0xD: {
/* Processor Extended State */
*eax = 0;
@@ -5094,6 +5130,11 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
x86_cpu_adjust_level(cpu, &cpu->env.cpuid_min_level, 0x14);
}
+ /* CPU topology with multi-dies support requires CPUID[0x1F] */
+ if (env->nr_dies > 1) {
+ x86_cpu_adjust_level(cpu, &env->cpuid_min_level, 0x1F);
+ }
+
/* SVM requires CPUID[0x8000000A] */
if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000000A);
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 85319f4ae1..0a96c78669 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -736,6 +736,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
#define CPUID_TOPOLOGY_LEVEL_INVALID (0U << 8)
#define CPUID_TOPOLOGY_LEVEL_SMT (1U << 8)
#define CPUID_TOPOLOGY_LEVEL_CORE (2U << 8)
+#define CPUID_TOPOLOGY_LEVEL_DIE (5U << 8)
/* MSR Feature Bits */
#define MSR_ARCH_CAP_RDCL_NO (1U << 0)
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index e4b4f5756a..473a17e9a5 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -1451,6 +1451,10 @@ int kvm_arch_init_vcpu(CPUState *cs)
}
break;
}
+ case 0x1f:
+ if (env->nr_dies < 2) {
+ break;
+ }
case 4:
case 0xb:
case 0xd:
@@ -1458,6 +1462,11 @@ int kvm_arch_init_vcpu(CPUState *cs)
if (i == 0xd && j == 64) {
break;
}
+
+ if (i == 0x1f && j == 64) {
+ break;
+ }
+
c->function = i;
c->flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
c->index = j;
@@ -1469,6 +1478,9 @@ int kvm_arch_init_vcpu(CPUState *cs)
if (i == 0xb && !(c->ecx & 0xff00)) {
break;
}
+ if (i == 0x1f && !(c->ecx & 0xff00)) {
+ break;
+ }
if (i == 0xd && c->eax == 0) {
continue;
}