mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 11:11:45 -04:00
efi/x86: Handle page faults occurring while running EFI runtime services
Memory accesses performed by UEFI runtime services should be limited to: - reading/executing from EFI_RUNTIME_SERVICES_CODE memory regions - reading/writing from/to EFI_RUNTIME_SERVICES_DATA memory regions - reading/writing by-ref arguments - reading/writing from/to the stack. Accesses outside these regions may cause the kernel to hang because the memory region requested by the firmware isn't mapped in efi_pgd, which causes a page fault in ring 0 and the kernel fails to handle it, leading to die(). To save kernel from hanging, add an EFI specific page fault handler which recovers from such faults by 1. If the efi runtime service is efi_reset_system(), reboot the machine through BIOS. 2. If the efi runtime service is _not_ efi_reset_system(), then freeze efi_rts_wq and schedule a new process. The EFI page fault handler offers us two advantages: 1. Avoid potential hangs caused by buggy firmware. 2. Shout loud that the firmware is buggy and hence is not a kernel bug. Tested-by: Bhupesh Sharma <[email protected]> Suggested-by: Matt Fleming <[email protected]> Based-on-code-from: Ricardo Neri <[email protected]> Signed-off-by: Sai Praneeth Prakhya <[email protected]> Reviewed-by: Thomas Gleixner <[email protected]> [ardb: clarify commit log] Signed-off-by: Ard Biesheuvel <[email protected]>
This commit is contained in:
parent
9dbbedaa61
commit
3425d934fc
5 changed files with 103 additions and 1 deletions
|
|
@ -61,6 +61,11 @@ struct efi_runtime_work efi_rts_work;
|
|||
({ \
|
||||
efi_rts_work.status = EFI_ABORTED; \
|
||||
\
|
||||
if (!efi_enabled(EFI_RUNTIME_SERVICES)) { \
|
||||
pr_warn_once("EFI Runtime Services are disabled!\n"); \
|
||||
goto exit; \
|
||||
} \
|
||||
\
|
||||
init_completion(&efi_rts_work.efi_rts_comp); \
|
||||
INIT_WORK_ONSTACK(&efi_rts_work.work, efi_call_rts); \
|
||||
efi_rts_work.arg1 = _arg1; \
|
||||
|
|
@ -79,6 +84,8 @@ struct efi_runtime_work efi_rts_work;
|
|||
else \
|
||||
pr_err("Failed to queue work to efi_rts_wq.\n"); \
|
||||
\
|
||||
exit: \
|
||||
efi_rts_work.efi_rts_id = NONE; \
|
||||
efi_rts_work.status; \
|
||||
})
|
||||
|
||||
|
|
@ -393,6 +400,7 @@ static void virt_efi_reset_system(int reset_type,
|
|||
"could not get exclusive access to the firmware\n");
|
||||
return;
|
||||
}
|
||||
efi_rts_work.efi_rts_id = RESET_SYSTEM;
|
||||
__efi_call_virt(reset_system, reset_type, status, data_size, data);
|
||||
up(&efi_runtime_lock);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue