[PATCH v2] arm64: errata: Handle Apple WFI State Loss
Sven Peter
sven at kernel.org
Mon Jun 15 08:27:59 PDT 2026
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 at chaosmail.tech>
>> Signed-off-by: Yureka Lilian <yureka at cyberchaos.dev>
>> ---
>> 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
More information about the linux-arm-kernel
mailing list