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.

Backports commit a94e1428991f741e2c6636e7c8df7f8d1905d983 from qemu
This commit is contained in:
Like Xu 2019-08-08 18:24:42 -04:00 committed by Lioncash
parent d2410074d8
commit 2c424e691c
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
2 changed files with 44 additions and 0 deletions

View file

@ -3943,6 +3943,43 @@ 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;
@ -4554,6 +4591,12 @@ static void x86_cpu_expand_features(struct uc_struct *uc, X86CPU *cpu, Error **e
x86_cpu_adjust_feat_level(cpu, FEAT_C000_0001_EDX);
x86_cpu_adjust_feat_level(cpu, FEAT_SVM);
x86_cpu_adjust_feat_level(cpu, FEAT_XSAVE);
/* 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);

View file

@ -711,6 +711,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)