mirror of
https://github.com/qemu/qemu.git
synced 2024-11-24 19:33:39 +08:00
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>
This commit is contained in:
parent
1c809535e3
commit
a94e142899
@ -4413,6 +4413,42 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||||
*ecx |= CPUID_TOPOLOGY_LEVEL_INVALID;
|
||||
}
|
||||
|
||||
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;
|
||||
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user