arm64: efi: Recover from synchronous exceptions occurring in firmware
[linux-2.6-microblaze.git] / arch / arm64 / kernel / efi.c
index e1be6c4..8d36e66 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/efi.h>
 #include <linux/init.h>
+#include <linux/percpu.h>
 
 #include <asm/efi.h>
 
@@ -128,3 +129,28 @@ asmlinkage efi_status_t efi_handle_corrupted_x18(efi_status_t s, const char *f)
        pr_err_ratelimited(FW_BUG "register x18 corrupted by EFI %s\n", f);
        return s;
 }
+
+asmlinkage DEFINE_PER_CPU(u64, __efi_rt_asm_recover_sp);
+
+asmlinkage efi_status_t __efi_rt_asm_recover(void);
+
+asmlinkage efi_status_t efi_handle_runtime_exception(const char *f)
+{
+       pr_err(FW_BUG "Synchronous exception occurred in EFI runtime service %s()\n", f);
+       clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
+       return EFI_ABORTED;
+}
+
+bool efi_runtime_fixup_exception(struct pt_regs *regs, const char *msg)
+{
+        /* Check whether the exception occurred while running the firmware */
+       if (current_work() != &efi_rts_work.work || regs->pc >= TASK_SIZE_64)
+               return false;
+
+       pr_err(FW_BUG "Unable to handle %s in EFI runtime service\n", msg);
+       add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
+       dump_stack();
+
+       regs->pc = (u64)__efi_rt_asm_recover;
+       return true;
+}