[patch 04/15] x86/entry: Use idtentry for interrupts

From: Thomas Gleixner
Date: Tue Feb 25 2020 - 18:27:32 EST


Use IDTENTRY_IRQ for interrupts. Remove the existing stub code and let the
IDTENTRY machinery emit it automatically.

Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
---
arch/x86/entry/entry_32.S | 39 +++++++++----------------------
arch/x86/entry/entry_64.S | 49 +++++++++++++++-------------------------
arch/x86/include/asm/hw_irq.h | 1
arch/x86/include/asm/idtentry.h | 4 +++
arch/x86/include/asm/irq.h | 2 -
arch/x86/include/asm/traps.h | 1
arch/x86/kernel/apic/apic.c | 7 ++---
arch/x86/kernel/apic/msi.c | 3 +-
arch/x86/kernel/irq.c | 8 +++---
9 files changed, 44 insertions(+), 70 deletions(-)

--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -769,12 +769,6 @@ SYM_CODE_END(\asmsym)
.endm

/*
- * Include the defines which emit the idt entries which are shared
- * shared between 32 and 64 bit.
- */
-#include <asm/idtentry.h>
-
-/*
* %eax: prev task
* %edx: next task
*/
@@ -1235,7 +1229,7 @@ SYM_CODE_START(irq_entries_start)
.rept (FIRST_SYSTEM_VECTOR - FIRST_EXTERNAL_VECTOR)
pushl $(vector)
vector=vector+1
- jmp common_interrupt
+ jmp asm_common_interrupt
.align 8
.endr
SYM_CODE_END(irq_entries_start)
@@ -1247,40 +1241,31 @@ SYM_CODE_START(spurious_entries_start)
.rept (NR_VECTORS - FIRST_SYSTEM_VECTOR)
pushl $(vector)
vector=vector+1
- jmp common_spurious
+ jmp asm_spurious_interrupt
.align 8
.endr
SYM_CODE_END(spurious_entries_start)
+#endif

-SYM_CODE_START_LOCAL(common_spurious)
+.macro idtentry_irq vector cfunc
+ .p2align CONFIG_X86_L1_CACHE_SHIFT
+SYM_CODE_START_LOCAL(asm_\cfunc)
ASM_CLAC
SAVE_ALL switch_stacks=1
ENCODE_FRAME_POINTER
- TRACE_IRQS_OFF
movl %esp, %eax
movl PT_ORIG_EAX(%esp), %edx /* get the vector from stack */
movl $-1, PT_ORIG_EAX(%esp) /* no syscall to restart */
- call smp_spurious_interrupt
+ call \cfunc
jmp ret_from_intr
-SYM_CODE_END(common_spurious)
-#endif
+SYM_CODE_END(asm_\cfunc)
+.endm

/*
- * the CPU automatically disables interrupts when executing an IRQ vector,
- * so IRQ-flags tracing has to follow that:
+ * Include the defines which emit the idt entries which are shared
+ * shared between 32 and 64 bit.
*/
- .p2align CONFIG_X86_L1_CACHE_SHIFT
-SYM_CODE_START_LOCAL(common_interrupt)
- ASM_CLAC
- SAVE_ALL switch_stacks=1
- ENCODE_FRAME_POINTER
- TRACE_IRQS_OFF
- movl %esp, %eax
- movl PT_ORIG_EAX(%esp), %edx /* get the vector from stack */
- movl $-1, PT_ORIG_EAX(%esp) /* no syscall to restart */
- call do_IRQ
- jmp ret_from_intr
-SYM_CODE_END(common_interrupt)
+#include <asm/idtentry.h>

#define BUILD_INTERRUPT3(name, nr, fn) \
SYM_FUNC_START(name) \
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -365,7 +365,7 @@ SYM_CODE_START(irq_entries_start)
.rept (FIRST_SYSTEM_VECTOR - FIRST_EXTERNAL_VECTOR)
UNWIND_HINT_IRET_REGS
pushq $(vector)
- jmp common_interrupt
+ jmp asm_common_interrupt
.align 8
vector=vector+1
.endr
@@ -377,7 +377,7 @@ SYM_CODE_START(spurious_entries_start)
.rept (NR_VECTORS - FIRST_SYSTEM_VECTOR)
UNWIND_HINT_IRET_REGS
pushq $(vector)
- jmp common_spurious
+ jmp asm_spurious_interrupt
.align 8
vector=vector+1
.endr
@@ -563,6 +563,20 @@ SYM_CODE_END(\asmsym)
.endm

/*
+ * Interrupt entry/exit.
+ *
+ + The interrupt stubs push (vector) onto the stack, which is the error_code
+ * position of idtentry exceptions, and jump to one of the two idtentry points
+ * (common/spurious).
+ *
+ * common_interrupt is a hotpath, align it to a cache line
+ */
+.macro idtentry_irq vector cfunc
+ .p2align CONFIG_X86_L1_CACHE_SHIFT
+ idtentry \vector asm_\cfunc \cfunc has_error_code=1 irq_stack=1
+.endm
+
+/*
* MCE and DB exceptions
*/
#define CPU_TSS_IST(x) PER_CPU_VAR(cpu_tss_rw) + (TSS_ist + (x) * 8)
@@ -758,32 +772,7 @@ SYM_CODE_START(interrupt_entry)
SYM_CODE_END(interrupt_entry)
_ASM_NOKPROBE(interrupt_entry)

-
-/* Interrupt entry/exit. */
-
-/*
- * The interrupt stubs push (~vector+0x80) onto the stack and
- * then jump to common_spurious/interrupt.
- */
-SYM_CODE_START_LOCAL(common_spurious)
- call interrupt_entry
- UNWIND_HINT_REGS indirect=1
- movq ORIG_RAX(%rdi), %rsi /* get vector from stack */
- movq $-1, ORIG_RAX(%rdi) /* no syscall to restart */
- call smp_spurious_interrupt /* rdi points to pt_regs */
- jmp ret_from_intr
-SYM_CODE_END(common_spurious)
-_ASM_NOKPROBE(common_spurious)
-
-/* common_interrupt is a hotpath. Align it */
- .p2align CONFIG_X86_L1_CACHE_SHIFT
-SYM_CODE_START_LOCAL(common_interrupt)
- call interrupt_entry
- UNWIND_HINT_REGS indirect=1
- movq ORIG_RAX(%rdi), %rsi /* get vector from stack */
- movq $-1, ORIG_RAX(%rdi) /* no syscall to restart */
- call do_IRQ /* rdi points to pt_regs */
- /* 0(%rsp): old RSP */
+SYM_CODE_START_LOCAL(common_interrupt_return)
ret_from_intr:
DISABLE_INTERRUPTS(CLBR_ANY)
TRACE_IRQS_OFF
@@ -965,8 +954,8 @@ SYM_INNER_LABEL(native_irq_return_iret,
*/
jmp native_irq_return_iret
#endif
-SYM_CODE_END(common_interrupt)
-_ASM_NOKPROBE(common_interrupt)
+SYM_CODE_END(common_interrupt_return)
+_ASM_NOKPROBE(common_interrupt_return)

/*
* APIC interrupts.
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -38,7 +38,6 @@ extern asmlinkage void error_interrupt(v
extern asmlinkage void irq_work_interrupt(void);
extern asmlinkage void uv_bau_message_intr1(void);

-extern asmlinkage void spurious_interrupt(void);
extern asmlinkage void spurious_apic_interrupt(void);
extern asmlinkage void thermal_interrupt(void);
extern asmlinkage void reschedule_interrupt(void);
--- a/arch/x86/include/asm/idtentry.h
+++ b/arch/x86/include/asm/idtentry.h
@@ -450,6 +450,10 @@ DECLARE_IDTENTRY_CR2(X86_TRAP_PF, exc_pa
DECLARE_IDTENTRY_CR2(X86_TRAP_PF, exc_async_page_fault);
#endif

+/* Device interrupts common/spurious */
+DECLARE_IDTENTRY_IRQ(X6_TRAP_OTHER, common_interrupt);
+DECLARE_IDTENTRY_IRQ(X6_TRAP_OTHER, spurious_interrupt);
+
#ifdef CONFIG_X86_MCE
/* Machine check */
DECLARE_IDTENTRY_MCE(X86_TRAP_MC, exc_machine_check);
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -36,8 +36,6 @@ extern void native_init_IRQ(void);

extern void handle_irq(struct irq_desc *desc, struct pt_regs *regs);

-extern __visible void do_IRQ(struct pt_regs *regs, unsigned long vector);
-
extern void init_ISA_irqs(void);

extern void __init init_IRQ(void);
--- a/arch/x86/include/asm/traps.h
+++ b/arch/x86/include/asm/traps.h
@@ -41,7 +41,6 @@ asmlinkage void smp_deferred_error_inter
void smp_apic_timer_interrupt(struct pt_regs *regs);
void smp_error_interrupt(struct pt_regs *regs);
void smp_spurious_apic_interrupt(struct pt_regs *regs);
-void smp_spurious_interrupt(struct pt_regs *regs, unsigned long vector);
asmlinkage void smp_irq_move_cleanup_interrupt(void);

extern void ist_enter(struct pt_regs *regs);
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -2159,7 +2159,7 @@ void __init register_lapic_address(unsig
*/

/**
- * smp_spurious_interrupt - Catch all for interrupts raised on unused vectors
+ * spurious_interrupt - Catch all for interrupts raised on unused vectors
* @regs: Pointer to pt_regs on stack
* @vector: Vector number
*
@@ -2169,8 +2169,7 @@ void __init register_lapic_address(unsig
*
* Also called from smp_spurious_apic_interrupt().
*/
-__visible void __irq_entry smp_spurious_interrupt(struct pt_regs *regs,
- unsigned long vector)
+DEFINE_IDTENTRY_IRQ(spurious_interrupt)
{
u32 v;

@@ -2209,7 +2208,7 @@ void __init register_lapic_address(unsig

__visible void smp_spurious_apic_interrupt(struct pt_regs *regs)
{
- smp_spurious_interrupt(regs, SPURIOUS_APIC_VECTOR);
+ __spurious_interrupt(regs, SPURIOUS_APIC_VECTOR);
}

/*
--- a/arch/x86/kernel/apic/msi.c
+++ b/arch/x86/kernel/apic/msi.c
@@ -115,7 +115,8 @@ msi_set_affinity(struct irq_data *irqd,
* denote it as spurious which is no harm as this is a rare event
* and interrupt handlers have to cope with spurious interrupts
* anyway. If the vector is unused, then it is marked so it won't
- * trigger the 'No irq handler for vector' warning in do_IRQ().
+ * trigger the 'No irq handler for vector' warning in
+ * common_interrupt().
*
* This requires to hold vector lock to prevent concurrent updates to
* the affected vector.
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -19,6 +19,7 @@
#include <asm/mce.h>
#include <asm/hw_irq.h>
#include <asm/desc.h>
+#include <asm/traps.h>

#define CREATE_TRACE_POINTS
#include <asm/trace/irq_vectors.h>
@@ -226,11 +227,10 @@ u64 arch_irq_stat(void)


/*
- * do_IRQ handles all normal device IRQ's (the special
- * SMP cross-CPU interrupts have their own specific
- * handlers).
+ * common_interrupt() handles all normal device IRQ's (the special SMP
+ * cross-CPU interrupts have their own specific handlers).
*/
-__visible void __irq_entry do_IRQ(struct pt_regs *regs, unsigned long vector)
+DEFINE_IDTENTRY_IRQ(common_interrupt)
{
struct pt_regs *old_regs = set_irq_regs(regs);
struct irq_desc * desc;