diff options
| -rw-r--r-- | arch/x86/include/asm/entry_arch.h | 2 | ||||
| -rw-r--r-- | arch/x86/include/asm/hardirq.h | 1 | ||||
| -rw-r--r-- | arch/x86/include/asm/hw_irq.h | 1 | ||||
| -rw-r--r-- | arch/x86/include/asm/irq.h | 1 | ||||
| -rw-r--r-- | arch/x86/include/asm/irq_vectors.h | 5 | ||||
| -rw-r--r-- | arch/x86/kernel/entry_64.S | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/irq.c | 34 | ||||
| -rw-r--r-- | arch/x86/kernel/irqinit_32.c | 3 | ||||
| -rw-r--r-- | arch/x86/kernel/irqinit_64.c | 3 |
9 files changed, 52 insertions, 0 deletions
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h index 854d538ae857..c2e6bedaf258 100644 --- a/arch/x86/include/asm/entry_arch.h +++ b/arch/x86/include/asm/entry_arch.h | |||
| @@ -33,6 +33,8 @@ BUILD_INTERRUPT3(invalidate_interrupt7,INVALIDATE_TLB_VECTOR_START+7, | |||
| 33 | smp_invalidate_interrupt) | 33 | smp_invalidate_interrupt) |
| 34 | #endif | 34 | #endif |
| 35 | 35 | ||
| 36 | BUILD_INTERRUPT(generic_interrupt, GENERIC_INTERRUPT_VECTOR) | ||
| 37 | |||
| 36 | /* | 38 | /* |
| 37 | * every pentium local APIC has two 'local interrupts', with a | 39 | * every pentium local APIC has two 'local interrupts', with a |
| 38 | * soft-definable vector attached to both interrupts, one of | 40 | * soft-definable vector attached to both interrupts, one of |
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h index 176f058e7159..039db6aa8e02 100644 --- a/arch/x86/include/asm/hardirq.h +++ b/arch/x86/include/asm/hardirq.h | |||
| @@ -12,6 +12,7 @@ typedef struct { | |||
| 12 | unsigned int apic_timer_irqs; /* arch dependent */ | 12 | unsigned int apic_timer_irqs; /* arch dependent */ |
| 13 | unsigned int irq_spurious_count; | 13 | unsigned int irq_spurious_count; |
| 14 | #endif | 14 | #endif |
| 15 | unsigned int generic_irqs; /* arch dependent */ | ||
| 15 | #ifdef CONFIG_SMP | 16 | #ifdef CONFIG_SMP |
| 16 | unsigned int irq_resched_count; | 17 | unsigned int irq_resched_count; |
| 17 | unsigned int irq_call_count; | 18 | unsigned int irq_call_count; |
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 370e1c83bb49..b762ea49bd70 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | 27 | ||
| 28 | /* Interrupt handlers registered during init_IRQ */ | 28 | /* Interrupt handlers registered during init_IRQ */ |
| 29 | extern void apic_timer_interrupt(void); | 29 | extern void apic_timer_interrupt(void); |
| 30 | extern void generic_interrupt(void); | ||
| 30 | extern void error_interrupt(void); | 31 | extern void error_interrupt(void); |
| 31 | extern void spurious_interrupt(void); | 32 | extern void spurious_interrupt(void); |
| 32 | extern void thermal_interrupt(void); | 33 | extern void thermal_interrupt(void); |
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index 107eb2196691..f38481bcd455 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h | |||
| @@ -36,6 +36,7 @@ static inline int irq_canonicalize(int irq) | |||
| 36 | extern void fixup_irqs(void); | 36 | extern void fixup_irqs(void); |
| 37 | #endif | 37 | #endif |
| 38 | 38 | ||
| 39 | extern void (*generic_interrupt_extension)(void); | ||
| 39 | extern void init_IRQ(void); | 40 | extern void init_IRQ(void); |
| 40 | extern void native_init_IRQ(void); | 41 | extern void native_init_IRQ(void); |
| 41 | extern bool handle_irq(unsigned irq, struct pt_regs *regs); | 42 | extern bool handle_irq(unsigned irq, struct pt_regs *regs); |
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 8a285f356f8a..3cbd79bbb47c 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h | |||
| @@ -112,6 +112,11 @@ | |||
| 112 | #define LOCAL_PERF_VECTOR 0xee | 112 | #define LOCAL_PERF_VECTOR 0xee |
| 113 | 113 | ||
| 114 | /* | 114 | /* |
| 115 | * Generic system vector for platform specific use | ||
| 116 | */ | ||
| 117 | #define GENERIC_INTERRUPT_VECTOR 0xed | ||
| 118 | |||
| 119 | /* | ||
| 115 | * First APIC vector available to drivers: (vectors 0x30-0xee) we | 120 | * First APIC vector available to drivers: (vectors 0x30-0xee) we |
| 116 | * start at 0x31(0x41) to spread out vectors evenly between priority | 121 | * start at 0x31(0x41) to spread out vectors evenly between priority |
| 117 | * levels. (0x80 is the syscall vector) | 122 | * levels. (0x80 is the syscall vector) |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 83d1836b9467..7ba4621c0dfa 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
| @@ -984,6 +984,8 @@ apicinterrupt UV_BAU_MESSAGE \ | |||
| 984 | #endif | 984 | #endif |
| 985 | apicinterrupt LOCAL_TIMER_VECTOR \ | 985 | apicinterrupt LOCAL_TIMER_VECTOR \ |
| 986 | apic_timer_interrupt smp_apic_timer_interrupt | 986 | apic_timer_interrupt smp_apic_timer_interrupt |
| 987 | apicinterrupt GENERIC_INTERRUPT_VECTOR \ | ||
| 988 | generic_interrupt smp_generic_interrupt | ||
| 987 | 989 | ||
| 988 | #ifdef CONFIG_SMP | 990 | #ifdef CONFIG_SMP |
| 989 | apicinterrupt INVALIDATE_TLB_VECTOR_START+0 \ | 991 | apicinterrupt INVALIDATE_TLB_VECTOR_START+0 \ |
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index f13ca1650aaf..b864341dcc45 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
| @@ -15,6 +15,9 @@ | |||
| 15 | 15 | ||
| 16 | atomic_t irq_err_count; | 16 | atomic_t irq_err_count; |
| 17 | 17 | ||
| 18 | /* Function pointer for generic interrupt vector handling */ | ||
| 19 | void (*generic_interrupt_extension)(void) = NULL; | ||
| 20 | |||
| 18 | /* | 21 | /* |
| 19 | * 'what should we do if we get a hw irq event on an illegal vector'. | 22 | * 'what should we do if we get a hw irq event on an illegal vector'. |
| 20 | * each architecture has to answer this themselves. | 23 | * each architecture has to answer this themselves. |
| @@ -56,6 +59,12 @@ static int show_other_interrupts(struct seq_file *p) | |||
| 56 | seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs); | 59 | seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs); |
| 57 | seq_printf(p, " Local timer interrupts\n"); | 60 | seq_printf(p, " Local timer interrupts\n"); |
| 58 | #endif | 61 | #endif |
| 62 | if (generic_interrupt_extension) { | ||
| 63 | seq_printf(p, "PLT: "); | ||
| 64 | for_each_online_cpu(j) | ||
| 65 | seq_printf(p, "%10u ", irq_stats(j)->generic_irqs); | ||
| 66 | seq_printf(p, " Platform interrupts\n"); | ||
| 67 | } | ||
| 59 | #ifdef CONFIG_SMP | 68 | #ifdef CONFIG_SMP |
| 60 | seq_printf(p, "RES: "); | 69 | seq_printf(p, "RES: "); |
| 61 | for_each_online_cpu(j) | 70 | for_each_online_cpu(j) |
| @@ -163,6 +172,8 @@ u64 arch_irq_stat_cpu(unsigned int cpu) | |||
| 163 | #ifdef CONFIG_X86_LOCAL_APIC | 172 | #ifdef CONFIG_X86_LOCAL_APIC |
| 164 | sum += irq_stats(cpu)->apic_timer_irqs; | 173 | sum += irq_stats(cpu)->apic_timer_irqs; |
| 165 | #endif | 174 | #endif |
| 175 | if (generic_interrupt_extension) | ||
| 176 | sum += irq_stats(cpu)->generic_irqs; | ||
| 166 | #ifdef CONFIG_SMP | 177 | #ifdef CONFIG_SMP |
| 167 | sum += irq_stats(cpu)->irq_resched_count; | 178 | sum += irq_stats(cpu)->irq_resched_count; |
| 168 | sum += irq_stats(cpu)->irq_call_count; | 179 | sum += irq_stats(cpu)->irq_call_count; |
| @@ -226,4 +237,27 @@ unsigned int __irq_entry do_IRQ(struct pt_regs *regs) | |||
| 226 | return 1; | 237 | return 1; |
| 227 | } | 238 | } |
| 228 | 239 | ||
| 240 | /* | ||
| 241 | * Handler for GENERIC_INTERRUPT_VECTOR. | ||
| 242 | */ | ||
| 243 | void smp_generic_interrupt(struct pt_regs *regs) | ||
| 244 | { | ||
| 245 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
| 246 | |||
| 247 | ack_APIC_irq(); | ||
| 248 | |||
| 249 | exit_idle(); | ||
| 250 | |||
| 251 | irq_enter(); | ||
| 252 | |||
| 253 | inc_irq_stat(generic_irqs); | ||
| 254 | |||
| 255 | if (generic_interrupt_extension) | ||
| 256 | generic_interrupt_extension(); | ||
| 257 | |||
| 258 | irq_exit(); | ||
| 259 | |||
| 260 | set_irq_regs(old_regs); | ||
| 261 | } | ||
| 262 | |||
| 229 | EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); | 263 | EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); |
diff --git a/arch/x86/kernel/irqinit_32.c b/arch/x86/kernel/irqinit_32.c index 50b8c3a3006c..bc1326105448 100644 --- a/arch/x86/kernel/irqinit_32.c +++ b/arch/x86/kernel/irqinit_32.c | |||
| @@ -175,6 +175,9 @@ void __init native_init_IRQ(void) | |||
| 175 | /* self generated IPI for local APIC timer */ | 175 | /* self generated IPI for local APIC timer */ |
| 176 | alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); | 176 | alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); |
| 177 | 177 | ||
| 178 | /* generic IPI for platform specific use */ | ||
| 179 | alloc_intr_gate(GENERIC_INTERRUPT_VECTOR, generic_interrupt); | ||
| 180 | |||
| 178 | /* IPI vectors for APIC spurious and error interrupts */ | 181 | /* IPI vectors for APIC spurious and error interrupts */ |
| 179 | alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); | 182 | alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); |
| 180 | alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); | 183 | alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); |
diff --git a/arch/x86/kernel/irqinit_64.c b/arch/x86/kernel/irqinit_64.c index da481a1e3f30..c7a49e0ffbfb 100644 --- a/arch/x86/kernel/irqinit_64.c +++ b/arch/x86/kernel/irqinit_64.c | |||
| @@ -147,6 +147,9 @@ static void __init apic_intr_init(void) | |||
| 147 | /* self generated IPI for local APIC timer */ | 147 | /* self generated IPI for local APIC timer */ |
| 148 | alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); | 148 | alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); |
| 149 | 149 | ||
| 150 | /* generic IPI for platform specific use */ | ||
| 151 | alloc_intr_gate(GENERIC_INTERRUPT_VECTOR, generic_interrupt); | ||
| 152 | |||
| 150 | /* IPI vectors for APIC spurious and error interrupts */ | 153 | /* IPI vectors for APIC spurious and error interrupts */ |
| 151 | alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); | 154 | alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); |
| 152 | alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); | 155 | alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); |
