x86/entry: Provide IDTENTRY_SYSVEC
authorThomas Gleixner <tglx@linutronix.de>
Thu, 21 May 2020 20:05:38 +0000 (22:05 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Thu, 11 Jun 2020 13:15:13 +0000 (15:15 +0200)
Provide IDTENTRY variants for system vectors to consolidate the different
mechanisms to emit the ASM stubs for 32- and 64-bit.

On 64-bit this also moves the stack switching from ASM to C code. 32-bit will
excute the system vectors w/o stack switching as before.

The simple variant is meant for "empty" system vectors like scheduler IPI
and KVM posted interrupt vectors. These do not need the full glory of irq
enter/exit handling with softirq processing and more.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Andy Lutomirski <luto@kernel.org>
Link: https://lore.kernel.org/r/20200521202119.185317067@linutronix.de
arch/x86/entry/entry_32.S
arch/x86/entry/entry_64.S
arch/x86/include/asm/idtentry.h

index b47b7b2238111fc9b4247553ca5e3cd62de71699..a8803aa3a07bfd57a78acb5e86c4ce5c9288f92e 100644 (file)
@@ -765,6 +765,10 @@ SYM_CODE_START_LOCAL(asm_\cfunc)
 SYM_CODE_END(asm_\cfunc)
 .endm
 
+.macro idtentry_sysvec vector cfunc
+       idtentry \vector asm_\cfunc \cfunc has_error_code=0
+.endm
+
 /*
  * Include the defines which emit the idt entries which are shared
  * shared between 32 and 64 bit.
index e54bcd3244f8a2666e93d3ddc0a067013fab3c8c..9b7183dac202c90f6bd7487424f3e0176b5b06be 100644 (file)
@@ -541,6 +541,14 @@ SYM_CODE_END(\asmsym)
        idtentry \vector asm_\cfunc \cfunc has_error_code=1
 .endm
 
+/*
+ * System vectors which invoke their handlers directly and are not
+ * going through the regular common device interrupt handling code.
+ */
+.macro idtentry_sysvec vector cfunc
+       idtentry \vector asm_\cfunc \cfunc has_error_code=0
+.endm
+
 /*
  * MCE and DB exceptions
  */
index 341888184d1c9eea14e75ab05eb55142808a99ea..63f7b99703cf879d17d5913737a04c487ae6506a 100644 (file)
@@ -6,6 +6,9 @@
 #include <asm/trapnr.h>
 
 #ifndef __ASSEMBLY__
+#include <linux/hardirq.h>
+
+#include <asm/irq_stack.h>
 
 void idtentry_enter_user(struct pt_regs *regs);
 void idtentry_exit_user(struct pt_regs *regs);
@@ -210,6 +213,78 @@ __visible noinstr void func(struct pt_regs *regs,                  \
                                                                        \
 static __always_inline void __##func(struct pt_regs *regs, u8 vector)
 
+/**
+ * DECLARE_IDTENTRY_SYSVEC - Declare functions for system vector entry points
+ * @vector:    Vector number (ignored for C)
+ * @func:      Function name of the entry point
+ *
+ * Declares three functions:
+ * - The ASM entry point: asm_##func
+ * - The XEN PV trap entry point: xen_##func (maybe unused)
+ * - The C handler called from the ASM entry point
+ *
+ * Maps to DECLARE_IDTENTRY().
+ */
+#define DECLARE_IDTENTRY_SYSVEC(vector, func)                          \
+       DECLARE_IDTENTRY(vector, func)
+
+/**
+ * DEFINE_IDTENTRY_SYSVEC - Emit code for system vector IDT entry points
+ * @func:      Function name of the entry point
+ *
+ * idtentry_enter/exit() and irq_enter/exit_rcu() are invoked before the
+ * function body. KVM L1D flush request is set.
+ *
+ * Runs the function on the interrupt stack if the entry hit kernel mode
+ */
+#define DEFINE_IDTENTRY_SYSVEC(func)                                   \
+static void __##func(struct pt_regs *regs);                            \
+                                                                       \
+__visible noinstr void func(struct pt_regs *regs)                      \
+{                                                                      \
+       bool rcu_exit = idtentry_enter_cond_rcu(regs);                  \
+                                                                       \
+       instrumentation_begin();                                        \
+       irq_enter_rcu();                                                \
+       kvm_set_cpu_l1tf_flush_l1d();                                   \
+       run_on_irqstack_cond(__##func, regs, regs);                     \
+       irq_exit_rcu();                                                 \
+       lockdep_hardirq_exit();                                         \
+       instrumentation_end();                                          \
+       idtentry_exit_cond_rcu(regs, rcu_exit);                         \
+}                                                                      \
+                                                                       \
+static noinline void __##func(struct pt_regs *regs)
+
+/**
+ * DEFINE_IDTENTRY_SYSVEC_SIMPLE - Emit code for simple system vector IDT
+ *                                entry points
+ * @func:      Function name of the entry point
+ *
+ * Runs the function on the interrupted stack. No switch to IRQ stack and
+ * only the minimal __irq_enter/exit() handling.
+ *
+ * Only use for 'empty' vectors like reschedule IPI and KVM posted
+ * interrupt vectors.
+ */
+#define DEFINE_IDTENTRY_SYSVEC_SIMPLE(func)                            \
+static __always_inline void __##func(struct pt_regs *regs);            \
+                                                                       \
+__visible noinstr void func(struct pt_regs *regs)                      \
+{                                                                      \
+       bool rcu_exit = idtentry_enter_cond_rcu(regs);                  \
+                                                                       \
+       instrumentation_begin();                                        \
+       __irq_enter_raw();                                              \
+       kvm_set_cpu_l1tf_flush_l1d();                                   \
+       __##func (regs);                                                \
+       __irq_exit_raw();                                               \
+       instrumentation_end();                                          \
+       idtentry_exit_cond_rcu(regs, rcu_exit);                         \
+}                                                                      \
+                                                                       \
+static __always_inline void __##func(struct pt_regs *regs)
+
 /**
  * DECLARE_IDTENTRY_XENCB - Declare functions for XEN HV callback entry point
  * @vector:    Vector number (ignored for C)
@@ -361,6 +436,10 @@ __visible noinstr void func(struct pt_regs *regs,                  \
 #define DECLARE_IDTENTRY_IRQ(vector, func)                             \
        idtentry_irq vector func
 
+/* System vector entries */
+#define DECLARE_IDTENTRY_SYSVEC(vector, func)                          \
+       idtentry_sysvec vector func
+
 #ifdef CONFIG_X86_64
 # define DECLARE_IDTENTRY_MCE(vector, func)                            \
        idtentry_mce_db vector asm_##func func