mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
x86/cpuid: Disentangle logic for new feature leaves
Adding a new feature leaf is a reasonable amount of boilerplate and for the
patch to build, at least one feature from the new leaf needs defining. This
typically causes two non-trivial changes to be merged together.
First, have gen-cpuid.py write out some extra placeholder defines:
#define CPUID_BITFIELD_11 bool :1, :1, lfence_dispatch:1, ...
#define CPUID_BITFIELD_12 uint32_t :32 /* placeholder */
#define CPUID_BITFIELD_13 uint32_t :32 /* placeholder */
#define CPUID_BITFIELD_14 uint32_t :32 /* placeholder */
#define CPUID_BITFIELD_15 uint32_t :32 /* placeholder */
This allows DECL_BITFIELD() to be added to struct cpuid_policy without
requiring a XEN_CPUFEATURE() declared for the leaf. The choice of 4 is
arbitrary, and allows us to add more than one leaf at a time if necessary.
Second, rework generic_identify() to not use specific feature names.
The choice of deriving the index from a feature was to avoid mismatches, but
its correctness depends on bugs like c/s 249e0f1d8f ("x86/cpuid: Fix
TSXLDTRK definition") not happening.
Switch to using FEATURESET_* just like the policy/featureset helpers. This
breaks the cognitive complexity of needing to know which leaf a specifically
named feature should reside in, and is shorter to write. It is also far
easier to identify as correct at a glance, given the correlation with the
CPUID leaf being read.
In addition, tidy up some other bits of generic_identify()
* Drop leading zeros from leaf numbers.
* Don't use a locked update for X86_FEATURE_APERFMPERF.
* Rework extended_cpuid_level calculation to avoid setting it twice.
* Use "leaf >= $N" consistently so $N matches with the CPUID input.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
b4c669fd7e
commit
e3662437eb
2 files changed
+29
-27
No files matched your search
+27
-27
@@ -379,7 +379,7 @@ static void generic_identify(struct cpuinfo_x86 *c)
|
||||
u32 eax, ebx, ecx, edx, tmp;
|
||||
|
||||
/* Get vendor name */
|
||||
cpuid(0x00000000, &c->cpuid_level, &ebx, &ecx, &edx);
|
||||
cpuid(0, &c->cpuid_level, &ebx, &ecx, &edx);
|
||||
*(u32 *)&c->x86_vendor_id[0] = ebx;
|
||||
*(u32 *)&c->x86_vendor_id[8] = ecx;
|
||||
*(u32 *)&c->x86_vendor_id[4] = edx;
|
||||
@@ -394,7 +394,7 @@ static void generic_identify(struct cpuinfo_x86 *c)
|
||||
/* Note that the vendor-specific code below might override */
|
||||
|
||||
/* Model and family information. */
|
||||
cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
|
||||
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||
c->x86 = get_cpu_family(eax, &c->x86_model, &c->x86_mask);
|
||||
c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
|
||||
c->phys_proc_id = c->apicid;
|
||||
@@ -404,53 +404,53 @@ static void generic_identify(struct cpuinfo_x86 *c)
|
||||
|
||||
/* c_early_init() may have adjusted cpuid levels/features. Reread. */
|
||||
c->cpuid_level = cpuid_eax(0);
|
||||
cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
|
||||
c->x86_capability[cpufeat_word(X86_FEATURE_FPU)] = edx;
|
||||
c->x86_capability[cpufeat_word(X86_FEATURE_SSE3)] = ecx;
|
||||
cpuid(1, &eax, &ebx,
|
||||
&c->x86_capability[FEATURESET_1c],
|
||||
&c->x86_capability[FEATURESET_1d]);
|
||||
|
||||
if ( cpu_has(c, X86_FEATURE_CLFLUSH) )
|
||||
c->x86_clflush_size = ((ebx >> 8) & 0xff) * 8;
|
||||
|
||||
if ( (c->cpuid_level >= CPUID_PM_LEAF) &&
|
||||
(cpuid_ecx(CPUID_PM_LEAF) & CPUID6_ECX_APERFMPERF_CAPABILITY) )
|
||||
set_bit(X86_FEATURE_APERFMPERF, c->x86_capability);
|
||||
__set_bit(X86_FEATURE_APERFMPERF, c->x86_capability);
|
||||
|
||||
eax = cpuid_eax(0x80000000);
|
||||
if ((eax >> 16) == 0x8000)
|
||||
c->extended_cpuid_level = eax;
|
||||
|
||||
/* AMD-defined flags: level 0x80000001 */
|
||||
c->extended_cpuid_level = cpuid_eax(0x80000000);
|
||||
if ((c->extended_cpuid_level >> 16) != 0x8000)
|
||||
c->extended_cpuid_level = 0;
|
||||
if (c->extended_cpuid_level > 0x80000000)
|
||||
if (c->extended_cpuid_level >= 0x80000001)
|
||||
cpuid(0x80000001, &tmp, &tmp,
|
||||
&c->x86_capability[cpufeat_word(X86_FEATURE_LAHF_LM)],
|
||||
&c->x86_capability[cpufeat_word(X86_FEATURE_SYSCALL)]);
|
||||
&c->x86_capability[FEATURESET_e1c],
|
||||
&c->x86_capability[FEATURESET_e1d]);
|
||||
|
||||
if (c->extended_cpuid_level >= 0x80000004)
|
||||
get_model_name(c); /* Default name */
|
||||
if (c->extended_cpuid_level >= 0x80000007)
|
||||
c->x86_capability[cpufeat_word(X86_FEATURE_ITSC)]
|
||||
= cpuid_edx(0x80000007);
|
||||
c->x86_capability[FEATURESET_e7d] = cpuid_edx(0x80000007);
|
||||
if (c->extended_cpuid_level >= 0x80000008)
|
||||
c->x86_capability[cpufeat_word(X86_FEATURE_CLZERO)]
|
||||
= cpuid_ebx(0x80000008);
|
||||
c->x86_capability[FEATURESET_e8b] = cpuid_ebx(0x80000008);
|
||||
if (c->extended_cpuid_level >= 0x80000021)
|
||||
c->x86_capability[cpufeat_word(X86_FEATURE_LFENCE_DISPATCH)]
|
||||
= cpuid_eax(0x80000021);
|
||||
c->x86_capability[FEATURESET_e21a] = cpuid_eax(0x80000021);
|
||||
|
||||
/* Intel-defined flags: level 0x00000007 */
|
||||
if ( c->cpuid_level >= 0x00000007 ) {
|
||||
cpuid_count(0x00000007, 0, &eax,
|
||||
&c->x86_capability[cpufeat_word(X86_FEATURE_FSGSBASE)],
|
||||
&c->x86_capability[cpufeat_word(X86_FEATURE_PKU)],
|
||||
&c->x86_capability[cpufeat_word(X86_FEATURE_AVX512_4VNNIW)]);
|
||||
if (eax > 0)
|
||||
cpuid_count(0x00000007, 1,
|
||||
&c->x86_capability[cpufeat_word(X86_FEATURE_AVX512_BF16)],
|
||||
if (c->cpuid_level >= 7) {
|
||||
uint32_t max_subleaf;
|
||||
|
||||
cpuid_count(7, 0, &max_subleaf,
|
||||
&c->x86_capability[FEATURESET_7b0],
|
||||
&c->x86_capability[FEATURESET_7c0],
|
||||
&c->x86_capability[FEATURESET_7d0]);
|
||||
if (max_subleaf >= 1)
|
||||
cpuid_count(7, 1,
|
||||
&c->x86_capability[FEATURESET_7a1],
|
||||
&tmp, &tmp, &tmp);
|
||||
}
|
||||
|
||||
if (c->cpuid_level >= 0xd)
|
||||
cpuid_count(0xd, 1,
|
||||
&c->x86_capability[cpufeat_word(X86_FEATURE_XSAVEOPT)],
|
||||
&c->x86_capability[FEATURESET_Da1],
|
||||
&tmp, &tmp, &tmp);
|
||||
}
|
||||
|
||||
|
||||
@@ -423,6 +423,8 @@ def write_results(state):
|
||||
|
||||
""")
|
||||
|
||||
state.bitfields += ["uint32_t :32 /* placeholder */"] * 4
|
||||
|
||||
for idx, text in enumerate(state.bitfields):
|
||||
state.output.write(
|
||||
"#define CPUID_BITFIELD_%d \\\n %s\n\n"
|
||||
|
||||