diff options
Diffstat (limited to 'drivers/firmware/efi/runtime-wrappers.c')
-rw-r--r-- | drivers/firmware/efi/runtime-wrappers.c | 60 |
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 | ||
25 | static 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 |