aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware/efi/runtime-wrappers.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware/efi/runtime-wrappers.c')
-rw-r--r--drivers/firmware/efi/runtime-wrappers.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c
index de6953039af6..23bef6bb73ee 100644
--- a/drivers/firmware/efi/runtime-wrappers.c
+++ b/drivers/firmware/efi/runtime-wrappers.c
@@ -16,10 +16,70 @@
16 16
17#include <linux/bug.h> 17#include <linux/bug.h>
18#include <linux/efi.h> 18#include <linux/efi.h>
19#include <linux/irqflags.h>
19#include <linux/mutex.h> 20#include <linux/mutex.h>
20#include <linux/spinlock.h> 21#include <linux/spinlock.h>
22#include <linux/stringify.h>
21#include <asm/efi.h> 23#include <asm/efi.h>
22 24
25static void efi_call_virt_check_flags(unsigned long flags, const char *call)
26{
27 unsigned long cur_flags, mismatch;
28
29 local_save_flags(cur_flags);
30
31 mismatch = flags ^ cur_flags;
32 if (!WARN_ON_ONCE(mismatch & ARCH_EFI_IRQ_FLAGS_MASK))
33 return;
34
35 add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_NOW_UNRELIABLE);
36 pr_err_ratelimited(FW_BUG "IRQ flags corrupted (0x%08lx=>0x%08lx) by EFI %s\n",
37 flags, cur_flags, call);
38 local_irq_restore(flags);
39}
40
41/*
42 * Arch code can implement the following three template macros, avoiding
43 * reptition for the void/non-void return cases of {__,}efi_call_virt:
44 *
45 * * arch_efi_call_virt_setup
46 *
47 * Sets up the environment for the call (e.g. switching page tables,
48 * allowing kernel-mode use of floating point, if required).
49 *
50 * * arch_efi_call_virt
51 *
52 * Performs the call. The last expression in the macro must be the call
53 * itself, allowing the logic to be shared by the void and non-void
54 * cases.
55 *
56 * * arch_efi_call_virt_teardown
57 *
58 * Restores the usual kernel environment once the call has returned.
59 */
60
61#define efi_call_virt(f, args...) \
62({ \
63 efi_status_t __s; \
64 unsigned long flags; \
65 arch_efi_call_virt_setup(); \
66 local_save_flags(flags); \
67 __s = arch_efi_call_virt(f, args); \
68 efi_call_virt_check_flags(flags, __stringify(f)); \
69 arch_efi_call_virt_teardown(); \
70 __s; \
71})
72
73#define __efi_call_virt(f, args...) \
74({ \
75 unsigned long flags; \
76 arch_efi_call_virt_setup(); \
77 local_save_flags(flags); \
78 arch_efi_call_virt(f, args); \
79 efi_call_virt_check_flags(flags, __stringify(f)); \
80 arch_efi_call_virt_teardown(); \
81})
82
23/* 83/*
24 * According to section 7.1 of the UEFI spec, Runtime Services are not fully 84 * According to section 7.1 of the UEFI spec, Runtime Services are not fully
25 * reentrant, and there are particular combinations of calls that need to be 85 * reentrant, and there are particular combinations of calls that need to be