Skip to content

Commit 8a9a1a1

Browse files
committed
arm64: efi: Avoid workqueue to check whether EFI runtime is live
Comparing current_work() against efi_rts_work.work is sufficient to decide whether current is currently running EFI runtime services code at any level in its call stack. However, there are other potential users of the EFI runtime stack, such as the ACPI subsystem, which may invoke efi_call_virt_pointer() directly, and so any sync exceptions occurring in firmware during those calls are currently misidentified. So instead, let's check whether the stashed value of the thread stack pointer points into current's thread stack. This can only be the case if current was interrupted while running EFI runtime code. Note that this implies that we should clear the stashed value after switching back, to avoid false positives. Reviewed-by: Mark Rutland <[email protected]> Signed-off-by: Ard Biesheuvel <[email protected]>
1 parent d3f4505 commit 8a9a1a1

File tree

3 files changed

+17
-1
lines changed

3 files changed

+17
-1
lines changed

arch/arm64/include/asm/efi.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,17 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
4848
})
4949

5050
extern spinlock_t efi_rt_lock;
51+
extern u64 *efi_rt_stack_top;
5152
efi_status_t __efi_rt_asm_wrapper(void *, const char *, ...);
5253

54+
/*
55+
* efi_rt_stack_top[-1] contains the value the stack pointer had before
56+
* switching to the EFI runtime stack.
57+
*/
58+
#define current_in_efi() \
59+
(!preemptible() && efi_rt_stack_top != NULL && \
60+
on_task_stack(current, READ_ONCE(efi_rt_stack_top[-1]), 1))
61+
5362
#define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT)
5463

5564
/*

arch/arm64/kernel/efi-rt-wrapper.S

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ SYM_FUNC_START(__efi_rt_asm_wrapper)
4646
mov x4, x6
4747
blr x8
4848

49+
mov x16, sp
4950
mov sp, x29
51+
str xzr, [x16, #8] // clear recorded task SP value
52+
5053
ldp x1, x2, [sp, #16]
5154
cmp x2, x18
5255
ldp x29, x30, [sp], #112
@@ -71,6 +74,9 @@ SYM_FUNC_END(__efi_rt_asm_wrapper)
7174
SYM_CODE_START(__efi_rt_asm_recover)
7275
mov sp, x30
7376

77+
ldr_l x16, efi_rt_stack_top // clear recorded task SP value
78+
str xzr, [x16, #-8]
79+
7480
ldp x19, x20, [sp, #32]
7581
ldp x21, x22, [sp, #48]
7682
ldp x23, x24, [sp, #64]

arch/arm64/kernel/efi.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/init.h>
1212

1313
#include <asm/efi.h>
14+
#include <asm/stacktrace.h>
1415

1516
static bool region_is_misaligned(const efi_memory_desc_t *md)
1617
{
@@ -154,7 +155,7 @@ asmlinkage efi_status_t __efi_rt_asm_recover(void);
154155
bool efi_runtime_fixup_exception(struct pt_regs *regs, const char *msg)
155156
{
156157
/* Check whether the exception occurred while running the firmware */
157-
if (current_work() != &efi_rts_work.work || regs->pc >= TASK_SIZE_64)
158+
if (!current_in_efi() || regs->pc >= TASK_SIZE_64)
158159
return false;
159160

160161
pr_err(FW_BUG "Unable to handle %s in EFI runtime service\n", msg);

0 commit comments

Comments
 (0)