AMD CPU doesn't support hyperthreading. Even though QEMU fixes this issue by setting CPUID_0000_0001_EBX and CPUID_8000_0008_ECX via conversion, it is better to stop end-users in the first place with a warning message.
Signed-off-by: Wei Huang <w...@redhat.com> --- target-i386/cpu.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index e7bf9de..c377cd2 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2696,6 +2696,10 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp) } #endif +#define IS_AMD_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && \ + (env)->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && \ + (env)->cpuid_vendor3 == CPUID_VENDOR_AMD_3) + static void x86_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); @@ -2711,9 +2715,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on * CPUID[1].EDX. */ - if (env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && - env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && - env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) { + if (IS_AMD_CPU(env)) { env->features[FEAT_8000_0001_EDX] &= ~CPUID_EXT2_AMD_ALIASES; env->features[FEAT_8000_0001_EDX] |= (env->features[FEAT_1_EDX] & CPUID_EXT2_AMD_ALIASES); @@ -2742,6 +2744,21 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) mce_init(cpu); qemu_init_vcpu(cs); + /* AMD CPU doesn't support hyperthreading. Even though QEMU does fix + * this issue by setting CPUID_0000_0001_EBX and CPUID_8000_0008_ECX + * correctly, it is still better to stop end-users in the first place + * by giving out a warning message. + * + * NOTE: cs->nr_threads is initialized in qemu_init_vcpu(). So the + * following code has to follow qemu_init_vcpu(). + */ + if (IS_AMD_CPU(env) && (cs->nr_threads > 1)) { + error_setg(&local_err, + "AMD CPU doesn't support hyperthreading. Please configure " + "-smp options correctly."); + goto out; + } + x86_cpu_apic_realize(cpu, &local_err); if (local_err != NULL) { goto out; -- 1.8.3.1