From: Sai Praneeth <[email protected]> This patch set is an outcome of the discussion at https://lkml.org/lkml/2017/8/21/607
Presently, efi_runtime_services() are executed by firmware in process context. To execute efi_runtime_service(), kernel switches the page directory from swapper_pgd to efi_pgd. However, efi_pgd doesn't have any user space mappings. A potential issue could be, for instance, an NMI interrupt (like perf) trying to profile some user data while in efi_pgd. A solution for this issue could be to use kthread to run efi_runtime_service(). When a user/kernel thread requests to execute efi_runtime_service(), kernel off-loads this work to kthread which in turn uses efi_pgd. Anything that tries to touch user space addresses while in kthread is terminally broken. This patch set adds support to the efi subsystem to handle all calls to efi_runtime_services() using a work queue (which in turn uses kthread). Implementation summary: ----------------------- 1. When a user/kernel thread requests to execute efi_runtime_service(), enqueue work to a work queue, efi_rts_workqueue. 2. The caller thread waits until the work is finished because it's dependent on the return status of efi_runtime_service() and, in specific cases, the arguments populated by efi_runtime_service(). Some efi_runtime_services() takes a pointer to buffer as an argument and fills up the buffer with requested data. For instance, efi_get_variable() and efi_get_next_variable(). Hence, the caller process cannot just post the work and get going, it has to wait for results from firmware. Caveat: efi_rts_workqueue to run efi_runtime_services() shouldn't be used while in atomic, because caller thread might sleep. Presently, pstore code doesn't use efi_rts_workqueue. Tested using LUV (Linux UEFI Validation) for x86_64 and x86_32. Builds fine for arm and arm64. Will appreciate the effort if someone could test the patches on real ARM/ARM64 machines. LUV: https://01.org/linux-uefi-validation Thanks to Ricardo and Dan for initial reviews and suggestions. Please feel free to pour in your comments and concerns. Note: Patches are based on Linus's kernel v4.16-rc4 Changes from V1 to V2: ---------------------- 1. Remove unnecessary include of asm/efi.h file - Fixes build error on ia64, reported by 0-day 2. Use enum to identify efi_runtime_services() 3. Use alloc_ordered_workqueue() to create efi_rts_wq as create_workqueue() is scheduled for depreciation. 4. Make efi_call_rts() static, as it has no callers outside runtime-wrappers.c 5. Use BUG(), when we are unable to queue work or unable to identify requested efi_runtime_service() - Because these two situations should *never* happen. Sai Praneeth (3): x86/efi: Call efi_delete_dummy_variable() during efi subsystem initialization efi: Introduce efi_rts_workqueue and some infrastructure to invoke all efi_runtime_services() efi: Use efi_rts_workqueue to invoke EFI Runtime Services arch/x86/include/asm/efi.h | 1 - arch/x86/platform/efi/efi.c | 6 - drivers/firmware/efi/efi.c | 21 +++ drivers/firmware/efi/runtime-wrappers.c | 229 +++++++++++++++++++++++++++++--- include/linux/efi.h | 23 ++++ 5 files changed, 253 insertions(+), 27 deletions(-) Signed-off-by: Sai Praneeth Prakhya <[email protected]> Suggested-by: Andy Lutomirski <[email protected]> Cc: Lee, Chun-Yi <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Tony Luck <[email protected]> Cc: Will Deacon <[email protected]> Cc: Dave Hansen <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Bhupesh Sharma <[email protected]> Cc: Ricardo Neri <[email protected]> Cc: Ravi Shankar <[email protected]> Cc: Matt Fleming <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Ard Biesheuvel <[email protected]> Cc: Dan Williams <[email protected]> -- 2.7.4

