From 7fb0f14ebeaf93b71e4c337aae4d01d373dcd72d Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Wed, 19 Nov 2025 15:57:15 -0800 Subject: [PATCH] libpayload: arm64: Fix asynchronous exception routing in payload Six years ago we had a problem with not getting SError exceptions in coreboot, and we fixed it by setting the right SCR_EL3 bits to force exception routing to EL3 (commit bb345abbfc99 ("arm64: Correctly unmask asynchronous SError interrupts")). Turns out that we have the same problem in the payload but we never fixed it there. EL2 exception routing works differently, so in order to achieve the same effect here we can either enable the HCR_EL2 AMO, FMO and IMO bits (respectively), or we can just enable the TGE bit which traps everything. This patch chooses the latter, and it also ensures that the PSTATE exception masking (DAIF) bits are in the expected state (although they usually already are). This state will persist after handoff to the kernel or chained payload, and will prevent transition into EL1 if not cleared first. This should be fine since any code taking control in EL2 should be expected to correctly reintialize HCR_EL2 before handing off into EL1 (the Linux kernel has always reinitialized this very early after its entry point). If any selfboot() payloads are broken after this change, the payload should be fixed to reinitialize HCR_EL2 to 0 (or desired value). Change-Id: I339eded5a5344b5753c94be82e4f1e52e00b39f4 Signed-off-by: Julius Werner Reviewed-on: https://review.coreboot.org/c/coreboot/+/90127 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel Reviewed-by: Yidi Lin Reviewed-by: Chen-Tsung Hsieh --- payloads/libpayload/arch/arm64/head.S | 7 +++++++ payloads/libpayload/include/arm64/arch/lib_helpers.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/payloads/libpayload/arch/arm64/head.S b/payloads/libpayload/arch/arm64/head.S index 0ebadeae34..5fc7ef2967 100644 --- a/payloads/libpayload/arch/arm64/head.S +++ b/payloads/libpayload/arch/arm64/head.S @@ -37,6 +37,13 @@ ENTRY(_entry) ldr w1, =(SCTLR_RES1 | SCTLR_I | SCTLR_SA) msr sctlr_el2, x1 + /* Initialize HCR to intended state (route all exceptions to EL2) */ + mov x1, #HCR_TGE + msr hcr_el2, x1 + + /* Initialize PSTATE.DAIF to intended state (unmask all exceptions) */ + msr DAIFClr, #0xf + /* Save off the location of the coreboot tables */ ldr x1, 1f str x0, [x1] diff --git a/payloads/libpayload/include/arm64/arch/lib_helpers.h b/payloads/libpayload/include/arm64/arch/lib_helpers.h index c086098da0..fd4ff9e3fc 100644 --- a/payloads/libpayload/include/arm64/arch/lib_helpers.h +++ b/payloads/libpayload/include/arm64/arch/lib_helpers.h @@ -45,6 +45,8 @@ #define SCTLR_RES1 ((0x3 << 4) | (0x1 << 11) | (0x1 << 16) | \ (0x1 << 18) | (0x3 << 22) | (0x3 << 28)) +#define HCR_TGE (1 << 27) /* Trap General Exception */ + #define DAIF_DBG_BIT (1 << 3) #define DAIF_ABT_BIT (1 << 2) #define DAIF_IRQ_BIT (1 << 1)