diff --git a/xen/arch/x86/acpi/cpu_idle.c b/xen/arch/x86/acpi/cpu_idle.c index 52808f9809..d0607d8a69 100644 --- a/xen/arch/x86/acpi/cpu_idle.c +++ b/xen/arch/x86/acpi/cpu_idle.c @@ -453,8 +453,14 @@ void cpuidle_wakeup_mwait(cpumask_t *mask) cpumask_andnot(mask, mask, &target); } +/* Force sending of a wakeup IPI regardless of mwait usage. */ +bool __ro_after_init force_mwait_ipi_wakeup; + bool arch_skip_send_event_check(unsigned int cpu) { + if ( force_mwait_ipi_wakeup ) + return false; + /* * This relies on softirq_pending() and mwait_wakeup() to access data * on the same cache line. diff --git a/xen/arch/x86/cpu/intel.c b/xen/arch/x86/cpu/intel.c index bb9c6220de..74d10c93d8 100644 --- a/xen/arch/x86/cpu/intel.c +++ b/xen/arch/x86/cpu/intel.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -368,7 +369,6 @@ static void probe_c3_errata(const struct cpuinfo_x86 *c) INTEL_FAM6_MODEL(0x25), { } }; -#undef INTEL_FAM6_MODEL /* Serialized by the AP bringup code. */ if ( max_cstate > 1 && (c->apicid & (c->x86_num_siblings - 1)) && @@ -380,6 +380,38 @@ static void probe_c3_errata(const struct cpuinfo_x86 *c) } } +/* + * APL30: One use of the MONITOR/MWAIT instruction pair is to allow a logical + * processor to wait in a sleep state until a store to the armed address range + * occurs. Due to this erratum, stores to the armed address range may not + * trigger MWAIT to resume execution. + * + * ICX143: Under complex microarchitectural conditions, a monitor that is armed + * with the MWAIT instruction may not be triggered, leading to a processor + * hang. + * + * LNL030: Problem P-cores may not exit power state Core C6 on monitor hit. + * + * Force the sending of an IPI in those cases. + */ +static void __init probe_mwait_errata(void) +{ + static const struct x86_cpu_id __initconst models[] = { + INTEL_FAM6_MODEL(INTEL_FAM6_ATOM_GOLDMONT), /* APL30 */ + INTEL_FAM6_MODEL(INTEL_FAM6_ICELAKE_X), /* ICX143 */ + INTEL_FAM6_MODEL(INTEL_FAM6_LUNARLAKE_M), /* LNL030 */ + { } + }; +#undef INTEL_FAM6_MODEL + + if ( boot_cpu_has(X86_FEATURE_MONITOR) && x86_match_cpu(models) ) + { + printk(XENLOG_WARNING + "Forcing IPI MWAIT wakeup due to CPU erratum\n"); + force_mwait_ipi_wakeup = true; + } +} + /* * P4 Xeon errata 037 workaround. * Hardware prefetcher may cause stale data to be loaded into the cache. @@ -406,6 +438,8 @@ static void Intel_errata_workarounds(struct cpuinfo_x86 *c) __set_bit(X86_FEATURE_CLFLUSH_MONITOR, c->x86_capability); probe_c3_errata(c); + if (system_state < SYS_STATE_smp_boot) + probe_mwait_errata(); } diff --git a/xen/arch/x86/include/asm/mwait.h b/xen/arch/x86/include/asm/mwait.h index 9298f987c4..1f1e39775b 100644 --- a/xen/arch/x86/include/asm/mwait.h +++ b/xen/arch/x86/include/asm/mwait.h @@ -13,6 +13,9 @@ #define MWAIT_ECX_INTERRUPT_BREAK 0x1 +/* Force sending of a wakeup IPI regardless of mwait usage. */ +extern bool force_mwait_ipi_wakeup; + void mwait_idle_with_hints(unsigned int eax, unsigned int ecx); bool mwait_pc10_supported(void);