x86/traps: Refactor exc_general_protection()
authorKirill A. Shutemov <kirill.shutemov@linux.intel.com>
Tue, 5 Apr 2022 23:29:15 +0000 (02:29 +0300)
committerDave Hansen <dave.hansen@linux.intel.com>
Thu, 7 Apr 2022 15:27:51 +0000 (08:27 -0700)
TDX brings a new exception -- Virtualization Exception (#VE). Handling
of #VE structurally very similar to handling #GP.

Extract two helpers from exc_general_protection() that can be reused for
handling #VE.

No functional changes.

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Link: https://lkml.kernel.org/r/20220405232939.73860-7-kirill.shutemov@linux.intel.com
arch/x86/kernel/traps.c

index 1563fb9..db8d22a 100644 (file)
@@ -686,13 +686,40 @@ static bool try_fixup_enqcmd_gp(void)
 #endif
 }
 
+static bool gp_try_fixup_and_notify(struct pt_regs *regs, int trapnr,
+                                   unsigned long error_code, const char *str)
+{
+       if (fixup_exception(regs, trapnr, error_code, 0))
+               return true;
+
+       current->thread.error_code = error_code;
+       current->thread.trap_nr = trapnr;
+
+       /*
+        * To be potentially processing a kprobe fault and to trust the result
+        * from kprobe_running(), we have to be non-preemptible.
+        */
+       if (!preemptible() && kprobe_running() &&
+           kprobe_fault_handler(regs, trapnr))
+               return true;
+
+       return notify_die(DIE_GPF, str, regs, error_code, trapnr, SIGSEGV) == NOTIFY_STOP;
+}
+
+static void gp_user_force_sig_segv(struct pt_regs *regs, int trapnr,
+                                  unsigned long error_code, const char *str)
+{
+       current->thread.error_code = error_code;
+       current->thread.trap_nr = trapnr;
+       show_signal(current, SIGSEGV, "", str, regs, error_code);
+       force_sig(SIGSEGV);
+}
+
 DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
 {
        char desc[sizeof(GPFSTR) + 50 + 2*sizeof(unsigned long) + 1] = GPFSTR;
        enum kernel_gp_hint hint = GP_NO_HINT;
-       struct task_struct *tsk;
        unsigned long gp_addr;
-       int ret;
 
        if (user_mode(regs) && try_fixup_enqcmd_gp())
                return;
@@ -711,40 +738,18 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
                return;
        }
 
-       tsk = current;
-
        if (user_mode(regs)) {
                if (fixup_iopl_exception(regs))
                        goto exit;
 
-               tsk->thread.error_code = error_code;
-               tsk->thread.trap_nr = X86_TRAP_GP;
-
                if (fixup_vdso_exception(regs, X86_TRAP_GP, error_code, 0))
                        goto exit;
 
-               show_signal(tsk, SIGSEGV, "", desc, regs, error_code);
-               force_sig(SIGSEGV);
+               gp_user_force_sig_segv(regs, X86_TRAP_GP, error_code, desc);
                goto exit;
        }
 
-       if (fixup_exception(regs, X86_TRAP_GP, error_code, 0))
-               goto exit;
-
-       tsk->thread.error_code = error_code;
-       tsk->thread.trap_nr = X86_TRAP_GP;
-
-       /*
-        * To be potentially processing a kprobe fault and to trust the result
-        * from kprobe_running(), we have to be non-preemptible.
-        */
-       if (!preemptible() &&
-           kprobe_running() &&
-           kprobe_fault_handler(regs, X86_TRAP_GP))
-               goto exit;
-
-       ret = notify_die(DIE_GPF, desc, regs, error_code, X86_TRAP_GP, SIGSEGV);
-       if (ret == NOTIFY_STOP)
+       if (gp_try_fixup_and_notify(regs, X86_TRAP_GP, error_code, desc))
                goto exit;
 
        if (error_code)