diff mbox series

[3/3] arm64: Unmask Debug + SError in do_notify_resume()

Message ID 20240206123848.1696480-4-mark.rutland@arm.com (mailing list archive)
State New, archived
Headers show
Series arm64: cleanup DAIF handling for EL0 returns | expand

Commit Message

Mark Rutland Feb. 6, 2024, 12:38 p.m. UTC
When returning to a user context, the arm64 entry code masks all DAIF
exceptions before handling pending work in exit_to_user_mode_prepare()
and do_notify_resume(), where it will transiently unmask all DAIF
exceptions. This is a holdover from the old entry assembly, which
conservatively masked all DAIF exceptions, and it's only necessary to
mask interrupts at this point during the exception return path, so long
as we subsequently mask all DAIF exceptions before the actual exception
return.

While most DAIF manipulation follows a save...restore sequence, the
manipulation in do_notify_resume() is the other way around, unmasking
all DAIF exceptions before masking them again. This is unfortunate as we
unnecessarily mask Debug and SError exceptions, and it would be nice to
remove this special case to make DAIF manipulation simpler and most
consistent.

This patch changes exit_to_user_mode_prepare() and do_notify_resume() to
only mask interrupts while handling pending work, masking other DAIF
exceptions after this has completed. This removes the unusual DAIF
manipulation and allows Debug and SError exceptions to be taken for a
slightly longer window during the exception return path.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Will Deacon <will@kernel.org>
---
 arch/arm64/kernel/entry-common.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

Comments

Mark Brown Feb. 8, 2024, 2:08 p.m. UTC | #1
On Tue, Feb 06, 2024 at 12:38:48PM +0000, Mark Rutland wrote:
> When returning to a user context, the arm64 entry code masks all DAIF
> exceptions before handling pending work in exit_to_user_mode_prepare()
> and do_notify_resume(), where it will transiently unmask all DAIF
> exceptions. This is a holdover from the old entry assembly, which
> conservatively masked all DAIF exceptions, and it's only necessary to
> mask interrupts at this point during the exception return path, so long
> as we subsequently mask all DAIF exceptions before the actual exception
> return.

Reviewed-by: Mark Brown <broonie@kernel.org>
diff mbox series

Patch

diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index 3c849ad03bf83..b77a15955f28b 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -130,7 +130,7 @@  static __always_inline void __exit_to_user_mode(void)
 static void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags)
 {
 	do {
-		local_daif_restore(DAIF_PROCCTX);
+		local_irq_enable();
 
 		if (thread_flags & _TIF_NEED_RESCHED)
 			schedule();
@@ -153,7 +153,7 @@  static void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags)
 		if (thread_flags & _TIF_FOREIGN_FPSTATE)
 			fpsimd_restore_current_state();
 
-		local_daif_mask();
+		local_irq_disable();
 		thread_flags = read_thread_flags();
 	} while (thread_flags & _TIF_WORK_MASK);
 }
@@ -162,12 +162,14 @@  static __always_inline void exit_to_user_mode_prepare(struct pt_regs *regs)
 {
 	unsigned long flags;
 
-	local_daif_mask();
+	local_irq_disable();
 
 	flags = read_thread_flags();
 	if (unlikely(flags & _TIF_WORK_MASK))
 		do_notify_resume(regs, flags);
 
+	local_daif_mask();
+
 	lockdep_sys_exit();
 }