Re: [PATCH v2] arm64: errata: Handle Apple WFI State Loss
From: Sven Peter
Date: Mon Jun 15 2026 - 11:28:20 EST
On 15.06.26 17:02, Will Deacon wrote:
On Mon, Jun 15, 2026 at 02:21:36PM +0200, Yureka Lilian wrote:
Apple Silicon CPUs can lose register state in WFI, leading to crashes
in the idle loop early in the boot process.
This applies to any previous Apple Silicon CPUs too, but is worked
around by configuring the WFI mode in SYS_IMP_APL_CYC_OVRD sysreg
during m1n1's chickens setup.
This workaround no longer exists since M4.
Add a workaround capability for replacing wfi and wfit with nop, and
an erratum to enable it on the affected CPUs if the workaround using the
sysreg is not already applied. Leave the decision whether the sysreg
workaround can be used up to the earlier parts of the boot chain which
already configure the Apple Silicon chicken bits.
This alternative has to be applied in early boot, since otherwise some
cores might enter the idle loop before apply_alternatives_all() is run.
Reviewed-by: Sasha Finkelstein <k@xxxxxxxxxxxxxx>
Signed-off-by: Yureka Lilian <yureka@xxxxxxxxxxxxxx>
---
Changes since v1:
Restricted the erratum to EL2 only, since in EL1 we'd expect the
hypervisor to trap WFI and handle the erratum.
Tested on M4 and M4 Pro (which now sometimes nondeterministically
crash later during boot).
Successfully booted on M3 Max with the SYS_IMP_APL_CYC_OVRD
workaround disabled in the bootloader, as well as A18 Pro (which,
like M4 / M4 Pro, doesn't have SYS_IMP_APL_CYC_OVRD).
There is probably a better place for the SYS_IMP_APL_CYC_OVRD
defines, which I currently put in the middle of cpu_errata.c, but I
wouldn't know where.
---
arch/arm64/Kconfig | 12 ++++++++++++
arch/arm64/include/asm/barrier.h | 19 ++++++++++++++++---
arch/arm64/kernel/cpu_errata.c | 21 +++++++++++++++++++++
arch/arm64/tools/cpucaps | 1 +
4 files changed, 50 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b3afe0688919..8c8ff069856f 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -453,6 +453,18 @@ config AMPERE_ERRATUM_AC04_CPU_23
If unsure, say Y.
+config APPLE_ERRATUM_WFI_STATE
+ bool "Apple Silicon: WFI loses state"
+ default y
+ help
+ This option adds an alternative code sequence to work around some
+ Apple Silicon CPUs losing register state during wfi and wfit
+ instructions.
+
+ As a workaround, the wfi and wfit instructions are replaced with nop
+ operations via the alternative framework if an affected CPU is
+ detected.
+
config ARM64_WORKAROUND_CLEAN_CACHE
bool
diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h
index 9495c4441a46..f72eddc7c434 100644
--- a/arch/arm64/include/asm/barrier.h
+++ b/arch/arm64/include/asm/barrier.h
@@ -20,9 +20,22 @@
#define wfe() asm volatile("wfe" : : : "memory")
#define wfet(val) asm volatile("msr s0_3_c1_c0_0, %0" \
: : "r" (val) : "memory")
-#define wfi() asm volatile("wfi" : : : "memory")
-#define wfit(val) asm volatile("msr s0_3_c1_c0_1, %0" \
- : : "r" (val) : "memory")
+#define wfi() \
+ do { \
+ asm volatile( \
+ ALTERNATIVE("wfi", \
+ "nop", \
+ ARM64_WORKAROUND_WFI_STATE) \
+ : : : "memory"); \
+ } while (0)
+#define wfit(val) \
+ do { \
+ asm volatile( \
+ ALTERNATIVE("msr s0_3_c1_c0_1, %0", \
+ "nop", \
+ ARM64_WORKAROUND_WFI_STATE) \
+ : : "r" (val) : "memory"); \
+ } while (0)
How can you guarantee that we don't run one of these prior to patching?
I wonder if we're better off doing something like x86 and having an "idle="
cmdline option. which could choose between e.g. nop, wfe, wfi and yield, for
example? In fact, would wfe be a better choice than nop for you?
I think that should also solve the issue of detecting if we're running on bare metal and need this or if there's something that mitigates the issue (e.g. M1-M3 where we can still enable that chicken bit or a hypervisor that just traps wfi): Just let the bootloader decide and inject that cmdline option.
Best,
Sven