diff options
| author | Peter Zijlstra <peterz@infradead.org> | 2025-09-22 15:47:56 +0200 |
|---|---|---|
| committer | Peter Zijlstra <peterz@infradead.org> | 2025-10-29 10:29:56 +0100 |
| commit | a38a64712e740d6e9df6940a997a47f5fab7efa2 (patch) | |
| tree | 6b2e1ae3b6d6c770ddd6e46df8a2378d4c85103f | |
| parent | ae577ea0bc5249c483da09670f784dbc288c80b6 (diff) | |
unwind: Fix unwind_deferred_request() vs NMI
task_work_add(RWA_RESUME) isn't NMI-safe, use TWA_NMI_CURRENT when
used from NMI context.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Link: https://patch.msgid.link/20250924080119.005422353@infradead.org
| -rw-r--r-- | kernel/unwind/deferred.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/kernel/unwind/deferred.c b/kernel/unwind/deferred.c index dc6040aae3ee..d2cd3a7fd286 100644 --- a/kernel/unwind/deferred.c +++ b/kernel/unwind/deferred.c @@ -231,6 +231,7 @@ void unwind_deferred_task_exit(struct task_struct *task) int unwind_deferred_request(struct unwind_work *work, u64 *cookie) { struct unwind_task_info *info = ¤t->unwind_info; + int twa_mode = TWA_RESUME; unsigned long old, bits; unsigned long bit; int ret; @@ -246,8 +247,11 @@ int unwind_deferred_request(struct unwind_work *work, u64 *cookie) * Trigger a warning to make it obvious that an architecture * is using this in NMI when it should not be. */ - if (WARN_ON_ONCE(!CAN_USE_IN_NMI && in_nmi())) - return -EINVAL; + if (in_nmi()) { + if (WARN_ON_ONCE(!CAN_USE_IN_NMI)) + return -EINVAL; + twa_mode = TWA_NMI_CURRENT; + } /* Do not allow cancelled works to request again */ bit = READ_ONCE(work->bit); @@ -285,7 +289,7 @@ int unwind_deferred_request(struct unwind_work *work, u64 *cookie) } /* The work has been claimed, now schedule it. */ - ret = task_work_add(current, &info->work, TWA_RESUME); + ret = task_work_add(current, &info->work, twa_mode); if (WARN_ON_ONCE(ret)) WRITE_ONCE(info->unwind_mask, 0); |