On 6/20/2025 5:27 PM, Zhao Liu wrote: > Modern Intel CPUs use CPUID 0x4 leaf to describe cache information > and leave space in 0x2 for prefetch and TLBs (even TLB has its own leaf > CPUID 0x18). > > And 0x2 leaf provides a descriptor 0xFF to instruct software to check > cache information in 0x4 leaf instead. > > Therefore, follow this behavior to encode 0xFF when Intel CPU has 0x4 > leaf with "x-consistent-cache=true" for compatibility. > > In addition, for older CPUs without 0x4 leaf, still enumerate the cache > descriptor in 0x2 leaf, except the case that there's no descriptor > matching the cache model, then directly encode 0xFF in 0x2 leaf. This > makes sense, as in the 0x2 leaf era, all supported caches should have > the corresponding descriptor. > > Signed-off-by: Zhao Liu <zhao1....@intel.com> > --- > target/i386/cpu.c | 48 ++++++++++++++++++++++++++++++++++++----------- > 1 file changed, 37 insertions(+), 11 deletions(-) > > diff --git a/target/i386/cpu.c b/target/i386/cpu.c > index 2f895bf13523..a06aa1d629dc 100644 > --- a/target/i386/cpu.c > +++ b/target/i386/cpu.c > @@ -223,7 +223,7 @@ struct CPUID2CacheDescriptorInfo > cpuid2_cache_descriptors[] = { > * Return a CPUID 2 cache descriptor for a given cache. > * If no known descriptor is found, return CACHE_DESCRIPTOR_UNAVAILABLE > */ > -static uint8_t cpuid2_cache_descriptor(CPUCacheInfo *cache) > +static uint8_t cpuid2_cache_descriptor(CPUCacheInfo *cache, bool *unmacthed) > { > int i; > > @@ -240,9 +240,44 @@ static uint8_t cpuid2_cache_descriptor(CPUCacheInfo > *cache) > } > } > > + *unmacthed |= true; > return CACHE_DESCRIPTOR_UNAVAILABLE; > } > > +/* Encode cache info for CPUID[4] */ > +static void encode_cache_cpuid2(X86CPU *cpu, > + uint32_t *eax, uint32_t *ebx, > + uint32_t *ecx, uint32_t *edx) > +{ > + CPUX86State *env = &cpu->env; > + CPUCaches *caches = &env->cache_info_cpuid2; > + int l1d, l1i, l2, l3; > + bool unmatched = false; > + > + *eax = 1; /* Number of CPUID[EAX=2] calls required */ > + *ebx = *ecx = *edx = 0; > + > + l1d = cpuid2_cache_descriptor(caches->l1d_cache, &unmatched); > + l1i = cpuid2_cache_descriptor(caches->l1i_cache, &unmatched); > + l2 = cpuid2_cache_descriptor(caches->l2_cache, &unmatched); > + l3 = cpuid2_cache_descriptor(caches->l3_cache, &unmatched); > + > + if (!cpu->consistent_cache || > + (env->cpuid_min_level < 0x4 && !unmatched)) { > + /* > + * Though SDM defines code 0x40 for cases with no L2 or L3. It's > + * also valid to just ignore l3's code if there's no l2. > + */ > + if (cpu->enable_l3_cache) { > + *ecx = l3; > + } > + *edx = (l1d << 16) | (l1i << 8) | l2; > + } else { > + *ecx = 0; > + *edx = CACHE_DESCRIPTOR_UNAVAILABLE; > + } > +} > + > /* CPUID Leaf 4 constants: */ > > /* EAX: */ > @@ -7451,16 +7486,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, > uint32_t count, > *eax = *ebx = *ecx = *edx = 0; > break; > } > - *eax = 1; /* Number of CPUID[EAX=2] calls required */ > - *ebx = 0; > - if (!cpu->enable_l3_cache) { > - *ecx = 0; > - } else { > - *ecx = cpuid2_cache_descriptor(env->cache_info_cpuid2.l3_cache); > - } > - *edx = (cpuid2_cache_descriptor(env->cache_info_cpuid2.l1d_cache) << > 16) | > - (cpuid2_cache_descriptor(env->cache_info_cpuid2.l1i_cache) << > 8) | > - (cpuid2_cache_descriptor(env->cache_info_cpuid2.l2_cache)); > + encode_cache_cpuid2(cpu, eax, ebx, ecx, edx); > break; > case 4: > /* cache info: needed for Core compatibility */
LGTM. Reviewed-by: Dapeng Mi <dapeng1...@linux.intel.com>