diff options
| author | Breno Leitao <leitao@debian.org> | 2026-06-16 05:09:35 -0700 |
|---|---|---|
| committer | Ard Biesheuvel <ardb@kernel.org> | 2026-08-20 14:45:04 +0300 |
| commit | ecbccdbdab5d31e1e465e3f789d57bb34e5452cd (patch) | |
| tree | 073a19c95934d300d29f09418c624e6425841f47 | |
| parent | 718ee46ba4d95d28d50d3f6437afbbe2be531175 (diff) | |
efi/runtime-wrappers: factor out efi_rts_park_worker()
x86's efi_crash_gracefully_on_page_fault() ends in an infinite
schedule() loop so the kworker that faulted in firmware never runs
efi_rts_wq again. A later change needs the same "park this worker
forever" primitive on the runtime service timeout path, so factor the
loop into a shared efi_rts_park_worker() and call it from the x86
page-fault handler.
No functional change.
Signed-off-by: Breno Leitao <leitao@debian.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
| -rw-r--r-- | arch/x86/platform/efi/quirks.c | 9 | ||||
| -rw-r--r-- | drivers/firmware/efi/runtime-wrappers.c | 15 | ||||
| -rw-r--r-- | include/linux/efi.h | 2 | ||||
| -rw-r--r-- | tools/objtool/noreturns.h | 1 |
4 files changed, 18 insertions, 9 deletions
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index 90a065fcb1fa..02c56a02eb9b 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c @@ -832,12 +832,5 @@ void efi_crash_gracefully_on_page_fault(unsigned long phys_addr, clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); pr_info("Froze efi_rts_wq and disabled EFI Runtime Services\n"); - /* - * Call schedule() in an infinite loop, so that any spurious wake ups - * will never run efi_rts_wq again. - */ - for (;;) { - set_current_state(TASK_IDLE); - schedule(); - } + efi_rts_park_worker(); } diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index da8d29621644..dc2e5c370edc 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c @@ -202,7 +202,7 @@ void efi_call_virt_check_flags(unsigned long flags, const void *caller) */ static DEFINE_SEMAPHORE(efi_runtime_lock, 1); -static struct task_struct *efi_runtime_lock_owner; +static struct task_struct *efi_runtime_lock_owner __used; /* * Expose the EFI runtime lock to the UV platform @@ -212,6 +212,19 @@ extern struct semaphore __efi_uv_runtime_lock __alias(efi_runtime_lock); #endif /* + * Park a worker that must never run efi_rts_wq again: EFI runtime services + * have been disabled and its efi_rts_work is abandoned. Loop in schedule() + * so a spurious wakeup cannot resume it. + */ +void __noreturn efi_rts_park_worker(void) +{ + for (;;) { + set_current_state(TASK_IDLE); + schedule(); + } +} + +/* * Calls the appropriate efi_runtime_service() with the appropriate * arguments. */ diff --git a/include/linux/efi.h b/include/linux/efi.h index 24221a842412..b3c83516593d 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -1256,6 +1256,8 @@ extern struct efi_runtime_work efi_rts_work; /* Workqueue to queue EFI Runtime Services */ extern struct workqueue_struct *efi_rts_wq; +void __noreturn efi_rts_park_worker(void); + struct linux_efi_memreserve { int size; // allocated size of the array atomic_t count; // number of entries used diff --git a/tools/objtool/noreturns.h b/tools/objtool/noreturns.h index 14f8ab653449..0e9dfd0a2446 100644 --- a/tools/objtool/noreturns.h +++ b/tools/objtool/noreturns.h @@ -26,6 +26,7 @@ NORETURN(cpu_startup_entry) NORETURN(do_exit) NORETURN(do_group_exit) NORETURN(do_task_dead) +NORETURN(efi_rts_park_worker) NORETURN(ex_handler_msr_mce) NORETURN(hlt_play_dead) NORETURN(hv_ghcb_terminate) |
