aboutsummaryrefslogtreecommitdiff
path: root/target/i386/cpu.c
diff options
context:
space:
mode:
authorLike Xu <like.xu@linux.intel.com>2019-06-20 13:45:23 +0800
committerEduardo Habkost <ehabkost@redhat.com>2019-07-05 17:08:04 -0300
commita94e1428991f741e2c6636e7c8df7f8d1905d983 (patch)
treef09158d8e90fc8ee9c5dcf9aad90902fc57e6fa4 /target/i386/cpu.c
parent1c809535e3083d4299899e9843a3f4e44b191a9c (diff)
target/i386: Add CPUID.1F generation support for multi-dies PCMachine
The CPUID.1F as Intel V2 Extended Topology Enumeration Leaf would be exposed if guests want to emulate multiple software-visible die within each package. Per Intel's SDM, the 0x1f is a superset of 0xb, thus they can be generated by almost same code as 0xb except die_offset setting. If the number of dies per package is greater than 1, the cpuid_min_level would be adjusted to 0x1f regardless of whether the host supports CPUID.1F. Likewise, the CPUID.1F wouldn't be exposed if env->nr_dies < 2. Suggested-by: Eduardo Habkost <ehabkost@redhat.com> Signed-off-by: Like Xu <like.xu@linux.intel.com> Message-Id: <20190620054525.37188-2-like.xu@linux.intel.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Diffstat (limited to 'target/i386/cpu.c')
-rw-r--r--target/i386/cpu.c41
1 files changed, 41 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);