diff options
| author | Stefan Hajnoczi <stefanha@redhat.com> | 2025-01-17 10:12:52 -0500 |
|---|---|---|
| committer | Stefan Hajnoczi <stefanha@redhat.com> | 2025-01-17 10:12:52 -0500 |
| commit | 09360a048bd7a133e47cb8dea617d44540bdebbd (patch) | |
| tree | 2b4868526830031398f0f8077c8bfc86854cf5c5 /target/i386/cpu.c | |
| parent | 4d5d933bbc7cc52f6cc6b9021f91fa06266222d5 (diff) | |
| parent | 99a637a86f55c8486b06c698656befdf012eec4d (diff) | |
| download | focaccia-qemu-09360a048bd7a133e47cb8dea617d44540bdebbd.tar.gz focaccia-qemu-09360a048bd7a133e47cb8dea617d44540bdebbd.zip | |
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging
* rust: miscellaneous changes * target/i386: small code generation improvements * target/i386: various cleanups and fixes * cpu: remove env->nr_cores # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmeBoIgUHHBib256aW5p # QHJlZGhhdC5jb20ACgkQv/vSX3jHroOD2gf+NK7U1EhNIrsbBsbtu2i7+tnbRKIB # MTu+Mxb2wz4C7//pxq+vva4bgT3iOuL9RF19PRe/63CMD65xMiwyyNrEWX2HbRIJ # 5dytLLLdef3yMhHh2x1uZfm54g12Ppvn9kulMCbPawrlqWgg1sZbkUBrRtFzS45c # NeYjGWWSpBDe7LtsrgSRYLPnz6wWEiy3tDpu2VoDtjrE86UVDXwyzpbtBk9Y8jPi # CKdvLyQeO9xDE5OoXMjJMlJeQq3D9iwYEprXUqy+RUZtpW7YmqMCf2JQ4dAjVCad # 07v/kITF4brGCVnzDcDA6W7LqHpBu1w+Hn23yLw3HEDDBt11o9JjQCl9qA== # =xIQ4 # -----END PGP SIGNATURE----- # gpg: Signature made Fri 10 Jan 2025 17:34:48 EST # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: (38 commits) i386/cpu: Set and track CPUID_EXT3_CMP_LEG in env->features[FEAT_8000_0001_ECX] i386/cpu: Set up CPUID_HT in x86_cpu_expand_features() instead of cpu_x86_cpuid() cpu: Remove nr_cores from struct CPUState i386/cpu: Hoist check of CPUID_EXT3_TOPOEXT against threads_per_core i386/cpu: Track a X86CPUTopoInfo directly in CPUX86State i386/topology: Introduce helpers for various topology info of different level i386/topology: Update the comment of x86_apicid_from_topo_ids() i386/cpu: Drop cores_per_pkg in cpu_x86_cpuid() i386/cpu: Drop the variable smp_cores and smp_threads in x86_cpu_pre_plug() i386/cpu: Extract a common fucntion to setup value of MSR_CORE_THREAD_COUNT target/i386/kvm: Replace ARRAY_SIZE(msr_handlers) with KVM_MSR_FILTER_MAX_RANGES target/i386/kvm: Clean up error handling in kvm_arch_init() target/i386/kvm: Return -1 when kvm_msr_energy_thread_init() fails target/i386/kvm: Clean up return values of MSR filter related functions target/i386/confidential-guest: Fix comment of x86_confidential_guest_kvm_type() target/i386/kvm: Drop workaround for KVM_X86_DISABLE_EXITS_HTL typo target/i386/kvm: Only save/load kvmclock MSRs when kvmclock enabled target/i386/kvm: Remove local MSR_KVM_WALL_CLOCK and MSR_KVM_SYSTEM_TIME definitions target/i386/kvm: Add feature bit definitions for KVM CPUID i386/cpu: Mark avx10_version filtered when prefix is NULL ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'target/i386/cpu.c')
| -rw-r--r-- | target/i386/cpu.c | 119 |
1 files changed, 54 insertions, 65 deletions
diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 0b639848cd..1b9c11022c 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -312,13 +312,11 @@ static uint32_t num_threads_by_topo_level(X86CPUTopoInfo *topo_info, case CPU_TOPOLOGY_LEVEL_CORE: return topo_info->threads_per_core; case CPU_TOPOLOGY_LEVEL_MODULE: - return topo_info->threads_per_core * topo_info->cores_per_module; + return x86_threads_per_module(topo_info); case CPU_TOPOLOGY_LEVEL_DIE: - return topo_info->threads_per_core * topo_info->cores_per_module * - topo_info->modules_per_die; + return x86_threads_per_die(topo_info); case CPU_TOPOLOGY_LEVEL_SOCKET: - return topo_info->threads_per_core * topo_info->cores_per_module * - topo_info->modules_per_die * topo_info->dies_per_pkg; + return x86_threads_per_pkg(topo_info); default: g_assert_not_reached(); } @@ -6498,18 +6496,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, CPUState *cs = env_cpu(env); uint32_t limit; uint32_t signature[3]; - X86CPUTopoInfo topo_info; - uint32_t cores_per_pkg; + X86CPUTopoInfo *topo_info = &env->topo_info; uint32_t threads_per_pkg; - topo_info.dies_per_pkg = env->nr_dies; - topo_info.modules_per_die = env->nr_modules; - topo_info.cores_per_module = cs->nr_cores / env->nr_dies / env->nr_modules; - topo_info.threads_per_core = cs->nr_threads; - - cores_per_pkg = topo_info.cores_per_module * topo_info.modules_per_die * - topo_info.dies_per_pkg; - threads_per_pkg = cores_per_pkg * topo_info.threads_per_core; + threads_per_pkg = x86_threads_per_pkg(topo_info); /* Calculate & apply limits for different index ranges */ if (index >= 0xC0000000) { @@ -6548,7 +6538,6 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *edx = env->features[FEAT_1_EDX]; if (threads_per_pkg > 1) { *ebx |= threads_per_pkg << 16; - *edx |= CPUID_HT; } if (!cpu->enable_pmu) { *ecx &= ~CPUID_EXT_PDCM; @@ -6586,12 +6575,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, int host_vcpus_per_cache = 1 + ((*eax & 0x3FFC000) >> 14); *eax &= ~0xFC000000; - *eax |= max_core_ids_in_package(&topo_info) << 26; + *eax |= max_core_ids_in_package(topo_info) << 26; if (host_vcpus_per_cache > threads_per_pkg) { *eax &= ~0x3FFC000; /* Share the cache at package level. */ - *eax |= max_thread_ids_for_cache(&topo_info, + *eax |= max_thread_ids_for_cache(topo_info, CPU_TOPOLOGY_LEVEL_SOCKET) << 14; } } @@ -6603,7 +6592,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, switch (count) { case 0: /* L1 dcache info */ encode_cache_cpuid4(env->cache_info_cpuid4.l1d_cache, - &topo_info, + topo_info, eax, ebx, ecx, edx); if (!cpu->l1_cache_per_core) { *eax &= ~MAKE_64BIT_MASK(14, 12); @@ -6611,7 +6600,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; case 1: /* L1 icache info */ encode_cache_cpuid4(env->cache_info_cpuid4.l1i_cache, - &topo_info, + topo_info, eax, ebx, ecx, edx); if (!cpu->l1_cache_per_core) { *eax &= ~MAKE_64BIT_MASK(14, 12); @@ -6619,13 +6608,13 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; case 2: /* L2 cache info */ encode_cache_cpuid4(env->cache_info_cpuid4.l2_cache, - &topo_info, + topo_info, eax, ebx, ecx, edx); break; case 3: /* L3 cache info */ if (cpu->enable_l3_cache) { encode_cache_cpuid4(env->cache_info_cpuid4.l3_cache, - &topo_info, + topo_info, eax, ebx, ecx, edx); break; } @@ -6708,12 +6697,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, switch (count) { case 0: - *eax = apicid_core_offset(&topo_info); - *ebx = topo_info.threads_per_core; + *eax = apicid_core_offset(topo_info); + *ebx = topo_info->threads_per_core; *ecx |= CPUID_B_ECX_TOPO_LEVEL_SMT << 8; break; case 1: - *eax = apicid_pkg_offset(&topo_info); + *eax = apicid_pkg_offset(topo_info); *ebx = threads_per_pkg; *ecx |= CPUID_B_ECX_TOPO_LEVEL_CORE << 8; break; @@ -6739,7 +6728,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; } - encode_topo_cpuid1f(env, count, &topo_info, eax, ebx, ecx, edx); + encode_topo_cpuid1f(env, count, topo_info, eax, ebx, ecx, edx); break; case 0xD: { /* Processor Extended State */ @@ -6964,17 +6953,6 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *ecx = env->features[FEAT_8000_0001_ECX]; *edx = env->features[FEAT_8000_0001_EDX]; - /* The Linux kernel checks for the CMPLegacy bit and - * discards multiple thread information if it is set. - * So don't set it here for Intel to make Linux guests happy. - */ - if (threads_per_pkg > 1) { - if (env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1 || - env->cpuid_vendor2 != CPUID_VENDOR_INTEL_2 || - env->cpuid_vendor3 != CPUID_VENDOR_INTEL_3) { - *ecx |= 1 << 1; /* CmpLegacy bit */ - } - } if (tcg_enabled() && env->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && !(env->hflags & HF_LMA_MASK)) { *edx &= ~CPUID_EXT2_SYSCALL; @@ -7042,7 +7020,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, * thread ID within a package". * Bits 7:0 is "The number of threads in the package is NC+1" */ - *ecx = (apicid_pkg_offset(&topo_info) << 12) | + *ecx = (apicid_pkg_offset(topo_info) << 12) | (threads_per_pkg - 1); } else { *ecx = 0; @@ -7071,19 +7049,19 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, switch (count) { case 0: /* L1 dcache info */ encode_cache_cpuid8000001d(env->cache_info_amd.l1d_cache, - &topo_info, eax, ebx, ecx, edx); + topo_info, eax, ebx, ecx, edx); break; case 1: /* L1 icache info */ encode_cache_cpuid8000001d(env->cache_info_amd.l1i_cache, - &topo_info, eax, ebx, ecx, edx); + topo_info, eax, ebx, ecx, edx); break; case 2: /* L2 cache info */ encode_cache_cpuid8000001d(env->cache_info_amd.l2_cache, - &topo_info, eax, ebx, ecx, edx); + topo_info, eax, ebx, ecx, edx); break; case 3: /* L3 cache info */ encode_cache_cpuid8000001d(env->cache_info_amd.l3_cache, - &topo_info, eax, ebx, ecx, edx); + topo_info, eax, ebx, ecx, edx); break; default: /* end of info */ *eax = *ebx = *ecx = *edx = 0; @@ -7095,7 +7073,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; case 0x8000001E: if (cpu->core_id <= 255) { - encode_topo_cpuid8000001e(cpu, &topo_info, eax, ebx, ecx, edx); + encode_topo_cpuid8000001e(cpu, topo_info, eax, ebx, ecx, edx); } else { *eax = 0; *ebx = 0; @@ -7539,6 +7517,19 @@ void x86_cpu_expand_features(X86CPU *cpu, Error **errp) } } + if (x86_threads_per_pkg(&env->topo_info) > 1) { + env->features[FEAT_1_EDX] |= CPUID_HT; + + /* + * The Linux kernel checks for the CMPLegacy bit and + * discards multiple thread information if it is set. + * So don't set it here for Intel to make Linux guests happy. + */ + if (!IS_INTEL_CPU(env)) { + env->features[FEAT_8000_0001_ECX] |= CPUID_EXT3_CMP_LEG; + } + } + for (i = 0; i < ARRAY_SIZE(feature_dependencies); i++) { FeatureDep *d = &feature_dependencies[i]; if (!(env->features[d->from.index] & d->from.mask)) { @@ -7719,8 +7710,10 @@ static bool x86_cpu_filter_features(X86CPU *cpu, bool verbose) env->avx10_version = version; have_filtered_features = true; } - } else if (env->avx10_version && prefix) { - warn_report("%s: avx10.%d.", prefix, env->avx10_version); + } else if (env->avx10_version) { + if (prefix) { + warn_report("%s: avx10.%d.", prefix, env->avx10_version); + } have_filtered_features = true; } @@ -7891,6 +7884,21 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) */ cpu->mwait.ecx |= CPUID_MWAIT_EMX | CPUID_MWAIT_IBE; + /* + * Most Intel and certain AMD CPUs support hyperthreading. Even though QEMU + * fixes this issue by adjusting CPUID_0000_0001_EBX and CPUID_8000_0008_ECX + * based on inputs (sockets,cores,threads), it is still better to give + * users a warning. + */ + if (IS_AMD_CPU(env) && + !(env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_TOPOEXT) && + env->topo_info.threads_per_core > 1) { + warn_report_once("This family of AMD CPU doesn't support " + "hyperthreading(%d). Please configure -smp " + "options properly or try enabling topoext " + "feature.", env->topo_info.threads_per_core); + } + /* For 64bit systems think about the number of physical bits to present. * ideally this should be the same as the host; anything other than matching * the host can cause incorrect guest behaviour. @@ -7995,24 +8003,6 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) x86_cpu_gdb_init(cs); qemu_init_vcpu(cs); - /* - * Most Intel and certain AMD CPUs support hyperthreading. Even though QEMU - * fixes this issue by adjusting CPUID_0000_0001_EBX and CPUID_8000_0008_ECX - * based on inputs (sockets,cores,threads), it is still better to give - * users a warning. - * - * NOTE: the following code has to follow qemu_init_vcpu(). Otherwise - * cs->nr_threads hasn't be populated yet and the checking is incorrect. - */ - if (IS_AMD_CPU(env) && - !(env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_TOPOEXT) && - cs->nr_threads > 1) { - warn_report_once("This family of AMD CPU doesn't support " - "hyperthreading(%d). Please configure -smp " - "options properly or try enabling topoext " - "feature.", cs->nr_threads); - } - #ifndef CONFIG_USER_ONLY x86_cpu_apic_realize(cpu, &local_err); if (local_err != NULL) { @@ -8171,8 +8161,7 @@ static void x86_cpu_init_default_topo(X86CPU *cpu) { CPUX86State *env = &cpu->env; - env->nr_modules = 1; - env->nr_dies = 1; + env->topo_info = (X86CPUTopoInfo) {1, 1, 1, 1}; /* thread, core and socket levels are set by default. */ set_bit(CPU_TOPOLOGY_LEVEL_THREAD, env->avail_cpu_topo); |