From 3eaa433ca1cbee753698893b7732819ba2e31302 Mon Sep 17 00:00:00 2001 From: Jian Wang Date: Thu, 10 Feb 2022 19:43:55 +0800 Subject: [PATCH 1/2] i386: cache passthrough: Update Intel CPUID4.EAX[25:14] based on vCPU topo On Intel target, when host cache passthrough is disabled we will emulate the guest caches with default values and initialize the shared cpu list of the caches based on vCPU topology. However when host cache passthrough is enabled, the shared cpu list is consistent with host regardless what the vCPU topology is. For example, when cache passthrough is enabled, running a guest with vThreads=1 on a host with pThreads=2, we will get that there are every *two* logical vCPUs sharing a L1/L2 cache, which is not consistent with the vCPU topology (vThreads=1). So let's reinitialize BITs[25:14] of Intel CPUID 4 based on the actual vCPU topology instead of host pCPU topology. Signed-off-by: Jian Wang Signed-off-by: Yanan Wang --- target/i386/cpu.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 868cf3e7e8..c1fe2895fd 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -5196,7 +5196,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, { X86CPU *cpu = env_archcpu(env); CPUState *cs = env_cpu(env); - uint32_t die_offset; + uint32_t die_offset, smt_width; uint32_t limit; uint32_t signature[3]; X86CPUTopoInfo topo_info; @@ -5205,6 +5205,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, topo_info.cores_per_die = cs->nr_cores; topo_info.threads_per_core = cs->nr_threads; + die_offset = apicid_die_offset(&topo_info); + smt_width = apicid_smt_width(&topo_info); + /* Calculate & apply limits for different index ranges */ if (index >= 0xC0000000) { limit = env->cpuid_xlevel2; @@ -5272,8 +5275,25 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, /* cache info: needed for Core compatibility */ if (cpu->cache_info_passthrough) { host_cpuid(index, count, eax, ebx, ecx, edx); - /* QEMU gives out its own APIC IDs, never pass down bits 31..26. */ - *eax &= ~0xFC000000; + /* + * QEMU gives out its own APIC IDs, never pass down bits 31..26. + * Update the cache topo bits 25..14, according to the guest + * vCPU topology instead of the host pCPU topology. + */ + *eax &= ~0xFFFFC000; + switch (count) { + case 0: /* L1 dcache info */ + case 1: /* L1 icache info */ + case 2: /* L2 cache info */ + *eax |= ((1 << smt_width) - 1) << 14; + break; + case 3: /* L3 cache info */ + *eax |= ((1 << die_offset) - 1) << 14; + break; + default: /* end of info */ + *eax = *ebx = *ecx = *edx = 0; + break; + } if ((*eax & 31) && cs->nr_cores > 1) { *eax |= (cs->nr_cores - 1) << 26; } @@ -5298,7 +5318,6 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, eax, ebx, ecx, edx); break; case 3: /* L3 cache info */ - die_offset = apicid_die_offset(&topo_info); if (cpu->enable_l3_cache) { encode_cache_cpuid4(env->cache_info_cpuid4.l3_cache, (1 << die_offset), cs->nr_cores, -- Gitee From 475988057789a1f4dcd7354c8a07fd37dcbac79f Mon Sep 17 00:00:00 2001 From: Yanan Wang Date: Thu, 10 Feb 2022 20:06:01 +0800 Subject: [PATCH 2/2] i386: cache passthrough: Update AMD 8000_001D.EAX[25:14] based on vCPU topo On AMD target, when host cache passthrough is disabled we will emulate the guest caches with default values and initialize the shared cpu list of the caches based on vCPU topology. However when host cache passthrough is enabled, the shared cpu list is consistent with host regardless what the vCPU topology is. For example, when cache passthrough is enabled, running a guest with vThreads=1 on a host with pThreads=2, we will get that there are every *two* logical vCPUs sharing a L1/L2 cache, which is not consistent with the vCPU topology (vThreads=1). So let's reinitialize BITs[25:14] of AMD CPUID 8000_001D.EAX based on the actual vCPU topology instead of host pCPU topology. Signed-off-by: Yanan Wang --- target/i386/cpu.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index c1fe2895fd..002e32650d 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -5724,9 +5724,31 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, } break; case 0x8000001D: + /* Populate AMD Processor Cache Information */ *eax = 0; if (cpu->cache_info_passthrough) { host_cpuid(index, count, eax, ebx, ecx, edx); + + /* + * Clear BITs[25:14] and then update them based on the guest + * vCPU topology, like what we do in encode_cache_cpuid8000001d + * when cache_info_passthrough is not enabled. + */ + *eax &= ~0x03FFC000; + switch (count) { + case 0: /* L1 dcache info */ + case 1: /* L1 icache info */ + case 2: /* L2 cache info */ + *eax |= ((topo_info.threads_per_core - 1) << 14); + break; + case 3: /* L3 cache info */ + *eax |= ((topo_info.cores_per_die * + topo_info.threads_per_core - 1) << 14); + break; + default: /* end of info */ + *eax = *ebx = *ecx = *edx = 0; + break; + } break; } switch (count) { -- Gitee