]> www.infradead.org Git - users/willy/xarray.git/commitdiff
x86/entry/32: Provide macro to emit IDT entry stubs
authorThomas Gleixner <tglx@linutronix.de>
Tue, 25 Feb 2020 22:16:11 +0000 (23:16 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Thu, 11 Jun 2020 13:14:44 +0000 (15:14 +0200)
32 and 64 bit have unnecessary different ways to populate the exception
entry code. Provide a idtentry macro which allows to consolidate all of
that.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Alexandre Chartre <alexandre.chartre@oracle.com>
Acked-by: Andy Lutomirski <luto@kernel.org>
Acked-by: Peter Zijlstra <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20200505134904.166735365@linutronix.de
arch/x86/entry/entry_32.S

index d9da0b7f38ff92d4882ff410783cea4a2596808b..eb64e78052e17c6e2015a5f28b602cea1db135ae 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/asm.h>
 #include <asm/smap.h>
 #include <asm/frame.h>
+#include <asm/trapnr.h>
 #include <asm/nospec-branch.h>
 
 #include "calling.h"
 
 .Lend_\@:
 .endm
+
+/**
+ * idtentry - Macro to generate entry stubs for simple IDT entries
+ * @vector:            Vector number
+ * @asmsym:            ASM symbol for the entry point
+ * @cfunc:             C function to be called
+ * @has_error_code:    Hardware pushed error code on stack
+ * @sane:              Compatibility flag with 64bit
+ */
+.macro idtentry vector asmsym cfunc has_error_code:req sane=0
+SYM_CODE_START(\asmsym)
+       ASM_CLAC
+       cld
+
+       .if \has_error_code == 0
+               pushl   $0              /* Clear the error code */
+       .endif
+
+       /* Push the C-function address into the GS slot */
+       pushl   $\cfunc
+       /* Invoke the common exception entry */
+       jmp     handle_exception
+SYM_CODE_END(\asmsym)
+.endm
+
 /*
  * %eax: prev task
  * %edx: next task
@@ -1517,6 +1543,48 @@ SYM_CODE_START_LOCAL_NOALIGN(common_exception)
        jmp     ret_from_exception
 SYM_CODE_END(common_exception)
 
+SYM_CODE_START_LOCAL_NOALIGN(handle_exception)
+       /* the function address is in %gs's slot on the stack */
+       SAVE_ALL switch_stacks=1 skip_gs=1 unwind_espfix=1
+       ENCODE_FRAME_POINTER
+
+       /* fixup %gs */
+       GS_TO_REG %ecx
+       movl    PT_GS(%esp), %edi               # get the function address
+       REG_TO_PTGS %ecx
+       SET_KERNEL_GS %ecx
+
+       /* fixup orig %eax */
+       movl    PT_ORIG_EAX(%esp), %edx         # get the error code
+       movl    $-1, PT_ORIG_EAX(%esp)          # no syscall to restart
+
+       movl    %esp, %eax                      # pt_regs pointer
+       CALL_NOSPEC edi
+
+#ifdef CONFIG_VM86
+       movl    PT_EFLAGS(%esp), %eax           # mix EFLAGS and CS
+       movb    PT_CS(%esp), %al
+       andl    $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
+#else
+       /*
+        * We can be coming here from child spawned by kernel_thread().
+        */
+       movl    PT_CS(%esp), %eax
+       andl    $SEGMENT_RPL_MASK, %eax
+#endif
+       cmpl    $USER_RPL, %eax                 # returning to v8086 or userspace ?
+       jnb     ret_to_user
+
+       PARANOID_EXIT_TO_KERNEL_MODE
+       BUG_IF_WRONG_CR3
+       RESTORE_REGS 4
+       jmp     .Lirq_return
+
+ret_to_user:
+       movl    %esp, %eax
+       jmp     restore_all_switch_stack
+SYM_CODE_END(handle_exception)
+
 SYM_CODE_START(debug)
        /*
         * Entry from sysenter is now handled in common_exception