diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index b9ece374d4d3191e01ab031177a35873a1a325b9..89dcdb3a16a2960bfd1ac869d100eb95be77902f 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c @@ -16,10 +16,35 @@ #include #include +#include #include #include +#include #include +/* + * Temporary scaffolding until all users provide ARCH_EFI_IRQ_FLAGS_MASK. + */ +#ifdef ARCH_EFI_IRQ_FLAGS_MASK +static void efi_call_virt_check_flags(unsigned long flags, const char *call) +{ + unsigned long cur_flags, mismatch; + + local_save_flags(cur_flags); + + mismatch = flags ^ cur_flags; + if (!WARN_ON_ONCE(mismatch & ARCH_EFI_IRQ_FLAGS_MASK)) + return; + + add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_NOW_UNRELIABLE); + pr_err_ratelimited(FW_BUG "IRQ flags corrupted (0x%08lx=>0x%08lx) by EFI %s\n", + flags, cur_flags, call); + local_irq_restore(flags); +} +#else /* ARCH_EFI_IRQ_FLAGS_MASK */ +static inline void efi_call_virt_check_flags(unsigned long flags, const char *call) {} +#endif /* ARCH_EFI_IRQ_FLAGS_MASK */ + /* * Arch code can implement the following three template macros, avoiding * reptition for the void/non-void return cases of {__,}efi_call_virt: @@ -43,16 +68,22 @@ #define efi_call_virt(f, args...) \ ({ \ efi_status_t __s; \ + unsigned long flags; \ arch_efi_call_virt_setup(); \ + local_save_flags(flags); \ __s = arch_efi_call_virt(f, args); \ + efi_call_virt_check_flags(flags, __stringify(f)); \ arch_efi_call_virt_teardown(); \ __s; \ }) #define __efi_call_virt(f, args...) \ ({ \ + unsigned long flags; \ arch_efi_call_virt_setup(); \ + local_save_flags(flags); \ arch_efi_call_virt(f, args); \ + efi_call_virt_check_flags(flags, __stringify(f)); \ arch_efi_call_virt_teardown(); \ })