diff options
author | Mark Rutland <mark.rutland@arm.com> | 2024-02-06 15:38:46 +0300 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2024-02-20 21:12:13 +0300 |
commit | 270de609ae2af441d15289406340ff209e5dc864 (patch) | |
tree | 8bc18acec0a6e3257f00cc017b04d217276aefb3 | |
parent | 54be6c6c5ae8e0d93a6c4641cb7528eb0b6ba478 (diff) | |
download | linux-270de609ae2af441d15289406340ff209e5dc864.tar.xz |
arm64: Simplify do_notify_resume() DAIF masking
In do_notify_resume, we handle _TIF_NEED_RESCHED differently from all
other flags, leaving IRQ+FIQ masked when calling into schedule(). This
masking is a historical artifact, and it is not currently necessary
to mask IRQ+FIQ when calling into schedule (as evidenced by the generic
exit_to_user_mode_loop(), which unmasks IRQs before checking
_TIF_NEED_RESCHED and calling schedule()).
This patch removes the special case for _TIF_NEED_RESCHED, moving this
check into the main loop such that schedule() will be called from a
regular process context with IRQ+FIQ unmasked. This is a minor
simplification to do_notify_resume() and brings it into line with the
generic exit_to_user_mode_loop() logic. This will also aid subsequent
rework of DAIF management.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Will Deacon <will@kernel.org>
Reviewed-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20240206123848.1696480-2-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Itaru Kitayama <itaru.kitayama@linux.dev>
-rw-r--r-- | arch/arm64/kernel/signal.c | 34 |
1 files changed, 15 insertions, 19 deletions
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 0e8beb3349ea..50e108741599 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -1281,32 +1281,28 @@ static void do_signal(struct pt_regs *regs) void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags) { do { - if (thread_flags & _TIF_NEED_RESCHED) { - /* Unmask Debug and SError for the next task */ - local_daif_restore(DAIF_PROCCTX_NOIRQ); + local_daif_restore(DAIF_PROCCTX); + if (thread_flags & _TIF_NEED_RESCHED) schedule(); - } else { - local_daif_restore(DAIF_PROCCTX); - if (thread_flags & _TIF_UPROBE) - uprobe_notify_resume(regs); + if (thread_flags & _TIF_UPROBE) + uprobe_notify_resume(regs); - if (thread_flags & _TIF_MTE_ASYNC_FAULT) { - clear_thread_flag(TIF_MTE_ASYNC_FAULT); - send_sig_fault(SIGSEGV, SEGV_MTEAERR, - (void __user *)NULL, current); - } + if (thread_flags & _TIF_MTE_ASYNC_FAULT) { + clear_thread_flag(TIF_MTE_ASYNC_FAULT); + send_sig_fault(SIGSEGV, SEGV_MTEAERR, + (void __user *)NULL, current); + } - if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) - do_signal(regs); + if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) + do_signal(regs); - if (thread_flags & _TIF_NOTIFY_RESUME) - resume_user_mode_work(regs); + if (thread_flags & _TIF_NOTIFY_RESUME) + resume_user_mode_work(regs); - if (thread_flags & _TIF_FOREIGN_FPSTATE) - fpsimd_restore_current_state(); - } + if (thread_flags & _TIF_FOREIGN_FPSTATE) + fpsimd_restore_current_state(); local_daif_mask(); thread_flags = read_thread_flags(); |