[PATCH 03/17] arm64: entry: arm64: entry: Move DAIF masking for EL1 exit to C code

Jinjie Ruan <[email protected]> Fri, 3 Jul 2026 18:01:21 +0800
Newsgroups org.kernel.vger.linux-efi,dev.linux.lists.kvmarm,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Move the DAIF masking logic on exception exit from the assembly
macro kernel_exit into the respective EL1 C handler functions.

Originally, when returning to a privileged mode (el != 0), kernel_exit
invoked the disable_daif macro ("msr daifset, #0xf") to ensure that the
subsequent registers and PMR state restoration occurred with all local
interrupts fully masked.

Move the DAIF masking out of the assembly macro and into the individual
C exception handlers, immediately after the core handler logic.
Specifically, add `write_sysreg(DAIF_MASK, daif)` at the end of:

- el1h_64_sync_handler().
- el1_interrupt().
- el1h_64_error_handler).

We achieve identical masking behavior before entering the low-level
assembly exit path.

This change cleans up the assembly macro and consolidates the exception
lifecycle management in C code.

No functional change intended.

Signed-off-by: Jinjie Ruan <[email protected]>
---
 arch/arm64/include/asm/assembler.h | 4 ----
 arch/arm64/kernel/entry-common.c   | 5 +++++
 arch/arm64/kernel/entry.S          | 4 ----
 3 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index effae53e9739..0b58b550e8dc 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -34,10 +34,6 @@
 	wx\n	.req	w\n
 	.endr
 
-	.macro disable_daif
-	msr	daifset, #0xf
-	.endm
-
 /*
  * Save/restore interrupts.
  */
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index 195af3f8001e..6fdf74ff4835 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -486,6 +486,8 @@ asmlinkage void noinstr el1h_64_sync_handler(struct pt_regs *regs)
 	default:
 		__panic_unhandled(regs, "64-bit el1h sync", esr);
 	}
+
+	write_sysreg(DAIF_MASK, daif);
 }
 
 static __always_inline void __el1_pnmi(struct pt_regs *regs,
@@ -520,6 +522,8 @@ static void noinstr el1_interrupt(struct pt_regs *regs,
 		__el1_pnmi(regs, handler);
 	else
 		__el1_irq(regs, handler);
+
+	write_sysreg(DAIF_MASK, daif);
 }
 
 asmlinkage void noinstr el1h_64_irq_handler(struct pt_regs *regs)
@@ -541,6 +545,7 @@ asmlinkage void noinstr el1h_64_error_handler(struct pt_regs *regs)
 	state = irqentry_nmi_enter(regs);
 	do_serror(regs, esr);
 	irqentry_nmi_exit(regs, state);
+	write_sysreg(DAIF_MASK, daif);
 }
 
 static void noinstr el0_da(struct pt_regs *regs, unsigned long esr)
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index e0db14e9c843..f63049ac32dc 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -333,10 +333,6 @@ alternative_else_nop_endif
 	.endm
 
 	.macro	kernel_exit, el
-	.if	\el != 0
-	disable_daif
-	.endif
-
 #ifdef CONFIG_ARM64_PSEUDO_NMI
 alternative_if_not ARM64_HAS_GIC_PRIO_MASKING
 	b	.Lskip_pmr_restore\@
-- 
2.34.1