summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBreno Leitao <leitao@debian.org>2026-06-16 05:09:35 -0700
committerArd Biesheuvel <ardb@kernel.org>2026-08-20 14:45:04 +0300
commitecbccdbdab5d31e1e465e3f789d57bb34e5452cd (patch)
tree073a19c95934d300d29f09418c624e6425841f47
parent718ee46ba4d95d28d50d3f6437afbbe2be531175 (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.c9
-rw-r--r--drivers/firmware/efi/runtime-wrappers.c15
-rw-r--r--include/linux/efi.h2
-rw-r--r--tools/objtool/noreturns.h1
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)