Skip to content

Commit 97d935f

Browse files
mrutland-armctmarinas
authored andcommitted
arm64: Unmask Debug + SError in do_notify_resume()
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 <[email protected]> Cc: James Morse <[email protected]> Cc: Mark Brown <[email protected]> Cc: Will Deacon <[email protected]> Reviewed-by: Mark Brown <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]> Tested-by: Itaru Kitayama <[email protected]>
1 parent 997d79e commit 97d935f

File tree

1 file changed

+5
-3
lines changed

1 file changed

+5
-3
lines changed

arch/arm64/kernel/entry-common.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ static __always_inline void __exit_to_user_mode(void)
130130
static void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags)
131131
{
132132
do {
133-
local_daif_restore(DAIF_PROCCTX);
133+
local_irq_enable();
134134

135135
if (thread_flags & _TIF_NEED_RESCHED)
136136
schedule();
@@ -153,7 +153,7 @@ static void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags)
153153
if (thread_flags & _TIF_FOREIGN_FPSTATE)
154154
fpsimd_restore_current_state();
155155

156-
local_daif_mask();
156+
local_irq_disable();
157157
thread_flags = read_thread_flags();
158158
} while (thread_flags & _TIF_WORK_MASK);
159159
}
@@ -162,12 +162,14 @@ static __always_inline void exit_to_user_mode_prepare(struct pt_regs *regs)
162162
{
163163
unsigned long flags;
164164

165-
local_daif_mask();
165+
local_irq_disable();
166166

167167
flags = read_thread_flags();
168168
if (unlikely(flags & _TIF_WORK_MASK))
169169
do_notify_resume(regs, flags);
170170

171+
local_daif_mask();
172+
171173
lockdep_sys_exit();
172174
}
173175

0 commit comments

Comments
 (0)