diff --git a/hw/i386/x86-common.c b/hw/i386/x86-common.c index 67b03c913a..7d4f9b20f2 100644 --- a/hw/i386/x86-common.c +++ b/hw/i386/x86-common.c @@ -271,7 +271,10 @@ void x86_cpu_pre_plug(HotplugHandler *hotplug_dev, init_topo_info(&topo_info, x86ms); - env->nr_dies = ms->smp.dies; + if (ms->smp.dies > 1) { + env->nr_dies = ms->smp.dies; + set_bit(CPU_TOPO_LEVEL_DIE, env->avail_cpu_topo); + } /* * If APIC ID is not set, diff --git a/include/hw/i386/topology.h b/include/hw/i386/topology.h index d4eeb7ab82..befeb92b0b 100644 --- a/include/hw/i386/topology.h +++ b/include/hw/i386/topology.h @@ -60,6 +60,21 @@ typedef struct X86CPUTopoInfo { unsigned threads_per_core; } X86CPUTopoInfo; +/* + * CPUTopoLevel is the general i386 topology hierarchical representation, + * ordered by increasing hierarchical relationship. + * Its enumeration value is not bound to the type value of Intel (CPUID[0x1F]) + * or AMD (CPUID[0x80000026]). + */ +enum CPUTopoLevel { + CPU_TOPO_LEVEL_INVALID, + CPU_TOPO_LEVEL_SMT, + CPU_TOPO_LEVEL_CORE, + CPU_TOPO_LEVEL_DIE, + CPU_TOPO_LEVEL_PACKAGE, + CPU_TOPO_LEVEL_MAX, +}; + /* Return the bit width needed for 'count' IDs */ static unsigned apicid_bitwidth_for_count(unsigned count) { @@ -168,4 +183,12 @@ static inline apic_id_t x86_apicid_from_cpu_idx(X86CPUTopoInfo *topo_info, return x86_apicid_from_topo_ids(topo_info, &topo_ids); } +/* + * Check whether there's extended topology level (die)? + */ +static inline bool x86_has_extended_topo(unsigned long *topo_bitmap) +{ + return test_bit(CPU_TOPO_LEVEL_DIE, topo_bitmap); +} + #endif /* HW_I386_TOPOLOGY_H */ diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 363f5ee4be..8419055006 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -6442,7 +6442,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; case 0x1F: /* V2 Extended Topology Enumeration Leaf */ - if (topo_info.dies_per_pkg < 2) { + if (!x86_has_extended_topo(env->avail_cpu_topo)) { *eax = *ebx = *ecx = *edx = 0; break; } @@ -7275,7 +7275,7 @@ void x86_cpu_expand_features(X86CPU *cpu, Error **errp) * cpu->vendor_cpuid_only has been unset for compatibility with older * machine types. */ - if ((env->nr_dies > 1) && + if (x86_has_extended_topo(env->avail_cpu_topo) && (IS_INTEL_CPU(env) || !cpu->vendor_cpuid_only)) { x86_cpu_adjust_level(cpu, &env->cpuid_min_level, 0x1F); } @@ -7798,13 +7798,25 @@ static void x86_cpu_post_initfn(Object *obj) accel_cpu_instance_init(CPU(obj)); } +static void x86_cpu_init_default_topo(X86CPU *cpu) +{ + CPUX86State *env = &cpu->env; + + env->nr_dies = 1; + + /* SMT, core and package levels are set by default. */ + set_bit(CPU_TOPO_LEVEL_SMT, env->avail_cpu_topo); + set_bit(CPU_TOPO_LEVEL_CORE, env->avail_cpu_topo); + set_bit(CPU_TOPO_LEVEL_PACKAGE, env->avail_cpu_topo); +} + static void x86_cpu_initfn(Object *obj) { X86CPU *cpu = X86_CPU(obj); X86CPUClass *xcc = X86_CPU_GET_CLASS(obj); CPUX86State *env = &cpu->env; - env->nr_dies = 1; + x86_cpu_init_default_topo(cpu); object_property_add(obj, "feature-words", "X86CPUFeatureWordInfo", x86_cpu_get_feature_words, diff --git a/target/i386/cpu.h b/target/i386/cpu.h index ccf6811794..9e7b9e918e 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -24,6 +24,7 @@ #include "cpu-qom.h" #include "kvm/hyperv-proto.h" #include "exec/cpu-defs.h" +#include "hw/i386/topology.h" #include "qapi/qapi-types-common.h" #include "qemu/cpu-float.h" #include "qemu/timer.h" @@ -1891,6 +1892,9 @@ typedef struct CPUArchState { /* Number of dies within this CPU package. */ unsigned nr_dies; + + /* Bitmap of available CPU topology levels for this CPU. */ + DECLARE_BITMAP(avail_cpu_topo, CPU_TOPO_LEVEL_MAX); } CPUX86State; struct kvm_msrs; diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index c5943605ee..6c864e4611 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -51,6 +51,7 @@ #include "hw/i386/apic_internal.h" #include "hw/i386/apic-msidef.h" #include "hw/i386/intel_iommu.h" +#include "hw/i386/topology.h" #include "hw/i386/x86-iommu.h" #include "hw/i386/e820_memory_layout.h" @@ -1791,7 +1792,7 @@ static uint32_t kvm_x86_build_cpuid(CPUX86State *env, break; } case 0x1f: - if (env->nr_dies < 2) { + if (!x86_has_extended_topo(env->avail_cpu_topo)) { cpuid_i--; break; }