With the ability to match on steppings, introduce a new X86_MATCH_VFMS()
helper to match a specific stepping, and use it to rework deadline_match[].
Currently, the table is scanned on all systems, even those without the
TSC_DEADLINE feature. Introduce another early exit for that case, which
removes the need to encode every row in the table with TSC_DEADLINE.
Notably this removes the overloading of driver_data possibly being a function
pointer, and removes the latent bug where the target functions are missing
ENDBR instructions owing to the lack of the cf_check attribute.
No functional change.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
v2:
* Move deadline_match[] into check_deadline_errata() which produces a far
more legible diff.
* Check for TSC_DEADLINE early and skip the search on non-capable CPUs.
The bloat-o-meter summary shows that the use of functions really wasn't the
wisest idea:
add/remove: 0/3 grow/shrink: 1/2 up/down: 80/-146 (-66)
Function old new delta
deadline_match 224 304 +80
APIC_init_uniprocessor 334 331 -3
skx_deadline_rev 30 - -30
CSWTCH 335 299 -36
hsx_deadline_rev 38 - -38
bdx_deadline_rev 39 - -39
---
xen/arch/x86/apic.c | 95 +++++++---------------------
xen/arch/x86/include/asm/match-cpu.h | 5 ++
2 files changed, 29 insertions(+), 71 deletions(-)
diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c
index c4272ab4de4f..0fd8bdba7067 100644
--- a/xen/arch/x86/apic.c
+++ b/xen/arch/x86/apic.c
@@ -1051,88 +1051,41 @@ static void setup_APIC_timer(void)
local_irq_restore(flags);
}
-#define DEADLINE_MODEL_MATCH(m, fr) \
- { .vendor = X86_VENDOR_INTEL, .family = 6, .model = (m), \
- .feature = X86_FEATURE_TSC_DEADLINE, \
- .driver_data = (void *)(unsigned long)(fr) }
-
-static unsigned int __init hsx_deadline_rev(void)
-{
- switch ( boot_cpu_data.x86_mask )
- {
- case 0x02: return 0x3a; /* EP */
- case 0x04: return 0x0f; /* EX */
- }
-
- return ~0U;
-}
-
-static unsigned int __init bdx_deadline_rev(void)
-{
- switch ( boot_cpu_data.x86_mask )
- {
- case 0x02: return 0x00000011;
- case 0x03: return 0x0700000e;
- case 0x04: return 0x0f00000c;
- case 0x05: return 0x0e000003;
- }
-
- return ~0U;
-}
-
-static unsigned int __init skx_deadline_rev(void)
-{
- switch ( boot_cpu_data.x86_mask )
- {
- case 0x00 ... 0x02: return ~0U;
- case 0x03: return 0x01000136;
- case 0x04: return 0x02000014;
- }
-
- return 0;
-}
-
-static const struct x86_cpu_id __initconstrel deadline_match[] = {
- DEADLINE_MODEL_MATCH(0x3c, 0x22), /* Haswell */
- DEADLINE_MODEL_MATCH(0x3f, hsx_deadline_rev), /* Haswell EP/EX */
- DEADLINE_MODEL_MATCH(0x45, 0x20), /* Haswell D */
- DEADLINE_MODEL_MATCH(0x46, 0x17), /* Haswell H */
-
- DEADLINE_MODEL_MATCH(0x3d, 0x25), /* Broadwell */
- DEADLINE_MODEL_MATCH(0x47, 0x17), /* Broadwell H */
- DEADLINE_MODEL_MATCH(0x4f, 0x0b000020), /* Broadwell EP/EX */
- DEADLINE_MODEL_MATCH(0x56, bdx_deadline_rev), /* Broadwell D */
-
- DEADLINE_MODEL_MATCH(0x4e, 0xb2), /* Skylake M */
- DEADLINE_MODEL_MATCH(0x55, skx_deadline_rev), /* Skylake X */
- DEADLINE_MODEL_MATCH(0x5e, 0xb2), /* Skylake D */
-
- DEADLINE_MODEL_MATCH(0x8e, 0x52), /* Kabylake M */
- DEADLINE_MODEL_MATCH(0x9e, 0x52), /* Kabylake D */
-
- {}
-};
-
static void __init check_deadline_errata(void)
{
+ static const struct x86_cpu_id __initconst deadline_match[] = {
+ X86_MATCH_VFM (INTEL_HASWELL, 0x22),
+ X86_MATCH_VFMS(INTEL_HASWELL_X, 0x2, 0x3a),
+ X86_MATCH_VFMS(INTEL_HASWELL_X, 0x4, 0x0f),
+ X86_MATCH_VFM (INTEL_HASWELL_L, 0x20),
+ X86_MATCH_VFM (INTEL_HASWELL_G, 0x17),
+ X86_MATCH_VFM (INTEL_BROADWELL, 0x25),
+ X86_MATCH_VFM (INTEL_BROADWELL_G, 0x17),
+ X86_MATCH_VFM (INTEL_BROADWELL_X, 0x0b000020),
+ X86_MATCH_VFMS(INTEL_BROADWELL_D, 0x2, 0x00000011),
+ X86_MATCH_VFMS(INTEL_BROADWELL_D, 0x3, 0x0700000e),
+ X86_MATCH_VFMS(INTEL_BROADWELL_D, 0x4, 0x0f00000c),
+ X86_MATCH_VFMS(INTEL_BROADWELL_D, 0x5, 0x0e000003),
+ X86_MATCH_VFM (INTEL_SKYLAKE_L, 0xb2),
+ X86_MATCH_VFM (INTEL_SKYLAKE, 0xb2),
+ X86_MATCH_VFMS(INTEL_SKYLAKE_X, 0x3, 0x01000136),
+ X86_MATCH_VFMS(INTEL_SKYLAKE_X, 0x4, 0x02000014),
+ X86_MATCH_VFM (INTEL_KABYLAKE_L, 0x52),
+ X86_MATCH_VFM (INTEL_KABYLAKE, 0x52),
+ {}
+ };
+
const struct x86_cpu_id *m;
unsigned int rev;
- if ( cpu_has_hypervisor )
+ if ( cpu_has_hypervisor || !boot_cpu_has(X86_FEATURE_TSC_DEADLINE) )
return;
m = x86_match_cpu(deadline_match);
if ( !m )
return;
- /*
- * Function pointers will have the MSB set due to address layout,
- * immediate revisions will not.
- */
- if ( (long)m->driver_data < 0 )
- rev = ((unsigned int (*)(void))(m->driver_data))();
- else
- rev = (unsigned long)m->driver_data;
+ rev = (unsigned long)m->driver_data;
if ( this_cpu(cpu_sig).rev >= rev )
return;
diff --git a/xen/arch/x86/include/asm/match-cpu.h b/xen/arch/x86/include/asm/match-cpu.h
index e25f414ea1b4..6d535c41c713 100644
--- a/xen/arch/x86/include/asm/match-cpu.h
+++ b/xen/arch/x86/include/asm/match-cpu.h
@@ -35,6 +35,11 @@ struct x86_cpu_id {
VFM_MODEL(vfm), X86_STEPPING_ANY, \
X86_FEATURE_ANY, data)
+#define X86_MATCH_VFMS(vfm, stepping, data) \
+ X86_MATCH_CPU(VFM_VENDOR(vfm), VFM_FAMILY(vfm), \
+ VFM_MODEL(vfm), 1U << (stepping), \
+ X86_FEATURE_ANY, data)
+
/*
* x86_match_cpu() - match the CPU against an array of x86_cpu_ids[]
*
--
2.39.5
On 18.07.2025 16:20, Andrew Cooper wrote: > With the ability to match on steppings, introduce a new X86_MATCH_VFMS() > helper to match a specific stepping, and use it to rework deadline_match[]. > > Currently, the table is scanned on all systems, even those without the > TSC_DEADLINE feature. Introduce another early exit for that case, which > removes the need to encode every row in the table with TSC_DEADLINE. > > Notably this removes the overloading of driver_data possibly being a function > pointer, and removes the latent bug where the target functions are missing > ENDBR instructions owing to the lack of the cf_check attribute. > > No functional change. > > Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Jan Beulich <jbeulich@suse.com>
© 2016 - 2025 Red Hat, Inc.