On 6/20/2025 5:27 PM, Zhao Liu wrote: > For a long time, the default cache models used in CPUID 0x2 and > 0x4 were inconsistent and had a FIXME note from Eduardo at commit > 5e891bf8fd50 ("target-i386: Use #defines instead of magic numbers for > CPUID cache info"): > > "/*FIXME: CPUID leaf 2 descriptor is inconsistent with CPUID leaf 4 */". > > This difference is wrong, in principle, both 0x2 and 0x4 are used for > Intel's cache description. 0x2 leaf is used for ancient machines while > 0x4 leaf is a subsequent addition, and both should be based on the same > cache model. Furthermore, on real hardware, 0x4 leaf should be used in > preference to 0x2 when it is available. > > Revisiting the git history, that difference occurred much earlier. > > Current legacy_l2_cache_cpuid2 (hardcode: "0x2c307d"), which is used for > CPUID 0x2 leaf, is introduced in commit d8134d91d9b7 ("Intel cache info, > by Filip Navara."). Its commit message didn't said anything, but its > patch [1] mentioned the cache model chosen is "closest to the ones > reported in the AMD registers". Now it is not possible to check which > AMD generation this cache model is based on (unfortunately, AMD does not > use 0x2 leaf), but at least it is close to the Pentium 4. > > In fact, the patch description of commit d8134d91d9b7 is also a bit > wrong, the original cache model in leaf 2 is from Pentium Pro, and its > cache descriptor had specified the cache line size ad 32 byte by default, > while the updated cache model in commit d8134d91d9b7 has 64 byte line > size. But after so many years, such judgments are no longer meaningful. > > On the other hand, for legacy_l2_cache, which is used in CPUID 0x4 leaf, > is based on Intel Core Duo (patch [2]) and Core2 Duo (commit e737b32a3688 > ("Core 2 Duo specification (Alexander Graf).") > > The patches of Core Duo and Core 2 Duo add the cache model for CPUID > 0x4, but did not update CPUID 0x2 encoding. This is the reason that > Intel Guests use two cache models in 0x2 and 0x4 all the time. > > Of course, while no Core Duo or Core 2 Duo machines have been found for > double checking, this still makes no sense to encode different cache > models on a single machine. > > Referring to the SDM and the real hardware available, 0x2 leaf can be > directly encoded 0xFF to instruct software to go to 0x4 leaf to get the > cache information, when 0x4 is available. > > Therefore, it's time to clean up Intel's default cache models. As the > first step, add "x-consistent-cache" compat option to allow newer > machines (v10.1 and newer) to have the consistent cache model in CPUID > 0x2 and 0x4 leaves. > > This doesn't affect the CPU models with CPUID level < 4 ("486", > "pentium", "pentium2" and "pentium3"), because they have already had the > special default cache model - legacy_intel_cpuid2_cache_info. > > [1]: > https://lore.kernel.org/qemu-devel/5b31733c0709081227w3e5f1036odbc649edfdc8c...@mail.gmail.com/ > [2]: https://lore.kernel.org/qemu-devel/478b65c8.2080...@csgraf.de/ > > Cc: Alexander Graf <ag...@csgraf.de> > Signed-off-by: Zhao Liu <zhao1....@intel.com> > --- > hw/i386/pc.c | 4 +++- > target/i386/cpu.c | 7 ++++++- > target/i386/cpu.h | 7 +++++++ > 3 files changed, 16 insertions(+), 2 deletions(-) > > diff --git a/hw/i386/pc.c b/hw/i386/pc.c > index b2116335752d..ad2d6495ebde 100644 > --- a/hw/i386/pc.c > +++ b/hw/i386/pc.c > @@ -81,7 +81,9 @@ > { "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\ > { "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, }, > > -GlobalProperty pc_compat_10_0[] = {}; > +GlobalProperty pc_compat_10_0[] = { > + { TYPE_X86_CPU, "x-consistent-cache", "false" }, > +}; > const size_t pc_compat_10_0_len = G_N_ELEMENTS(pc_compat_10_0); > > GlobalProperty pc_compat_9_2[] = {}; > diff --git a/target/i386/cpu.c b/target/i386/cpu.c > index 0a2c32214cc3..2f895bf13523 100644 > --- a/target/i386/cpu.c > +++ b/target/i386/cpu.c > @@ -8931,7 +8931,11 @@ static void x86_cpu_realizefn(DeviceState *dev, Error > **errp) > /* Build legacy cache information */ > env->cache_info_cpuid2.l1d_cache = &legacy_l1d_cache; > env->cache_info_cpuid2.l1i_cache = &legacy_l1i_cache; > - env->cache_info_cpuid2.l2_cache = &legacy_l2_cache_cpuid2; > + if (!cpu->consistent_cache) { > + env->cache_info_cpuid2.l2_cache = &legacy_l2_cache_cpuid2; > + } else { > + env->cache_info_cpuid2.l2_cache = &legacy_l2_cache; > + }
This would encode the valid L1 and L3 cache descriptors and "0xff" descriptor into CPUID leaf 0x2 when there is CPUID leaf 0x4. It seems a little bit of ambiguous to mix "0xff" descriptor with other valid descriptors and it isn't identical with real HW. Do we consider to make it identical with real HW? Thanks. > env->cache_info_cpuid2.l3_cache = &legacy_l3_cache; > > env->cache_info_cpuid4.l1d_cache = &legacy_l1d_cache; > @@ -9457,6 +9461,7 @@ static const Property x86_cpu_properties[] = { > * own cache information (see x86_cpu_load_def()). > */ > DEFINE_PROP_BOOL("legacy-cache", X86CPU, legacy_cache, true), > + DEFINE_PROP_BOOL("x-consistent-cache", X86CPU, consistent_cache, true), > DEFINE_PROP_BOOL("legacy-multi-node", X86CPU, legacy_multi_node, false), > DEFINE_PROP_BOOL("xen-vapic", X86CPU, xen_vapic, false), > > diff --git a/target/i386/cpu.h b/target/i386/cpu.h > index 5910dcf74d42..3c7e59ffb12a 100644 > --- a/target/i386/cpu.h > +++ b/target/i386/cpu.h > @@ -2259,6 +2259,13 @@ struct ArchCPU { > */ > bool legacy_cache; > > + /* > + * Compatibility bits for old machine types. > + * If true, use the same cache model in CPUID leaf 0x2 > + * and 0x4. > + */ > + bool consistent_cache; > + > /* Compatibility bits for old machine types. > * If true decode the CPUID Function 0x8000001E_ECX to support multiple > * nodes per processor