diff options
-rw-r--r-- | arch/x86/include/asm/entry_arch.h | 1 | ||||
-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_vectors.h | 5 | ||||
-rw-r--r-- | arch/x86/include/asm/perf_counter.h | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_counter.c | 14 | ||||
-rw-r--r-- | arch/x86/kernel/entry_64.S | 2 | ||||
-rw-r--r-- | arch/x86/kernel/irq.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/irqinit_32.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/irqinit_64.c | 1 |
10 files changed, 33 insertions, 1 deletions
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h index c2e6bedaf258..fe24d2802490 100644 --- a/arch/x86/include/asm/entry_arch.h +++ b/arch/x86/include/asm/entry_arch.h | |||
@@ -50,6 +50,7 @@ BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR) | |||
50 | 50 | ||
51 | #ifdef CONFIG_PERF_COUNTERS | 51 | #ifdef CONFIG_PERF_COUNTERS |
52 | BUILD_INTERRUPT(perf_counter_interrupt, LOCAL_PERF_VECTOR) | 52 | BUILD_INTERRUPT(perf_counter_interrupt, LOCAL_PERF_VECTOR) |
53 | BUILD_INTERRUPT(perf_pending_interrupt, LOCAL_PENDING_VECTOR) | ||
53 | #endif | 54 | #endif |
54 | 55 | ||
55 | #ifdef CONFIG_X86_MCE_P4THERMAL | 56 | #ifdef CONFIG_X86_MCE_P4THERMAL |
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h index 25454427ceea..f5ebe2aaca4b 100644 --- a/arch/x86/include/asm/hardirq.h +++ b/arch/x86/include/asm/hardirq.h | |||
@@ -14,6 +14,7 @@ typedef struct { | |||
14 | #endif | 14 | #endif |
15 | unsigned int generic_irqs; /* arch dependent */ | 15 | unsigned int generic_irqs; /* arch dependent */ |
16 | unsigned int apic_perf_irqs; | 16 | unsigned int apic_perf_irqs; |
17 | unsigned int apic_pending_irqs; | ||
17 | #ifdef CONFIG_SMP | 18 | #ifdef CONFIG_SMP |
18 | unsigned int irq_resched_count; | 19 | unsigned int irq_resched_count; |
19 | unsigned int irq_call_count; | 20 | unsigned int irq_call_count; |
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index ae80f64973e0..7309c0ad6902 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h | |||
@@ -30,6 +30,7 @@ extern void apic_timer_interrupt(void); | |||
30 | extern void generic_interrupt(void); | 30 | extern void generic_interrupt(void); |
31 | extern void error_interrupt(void); | 31 | extern void error_interrupt(void); |
32 | extern void perf_counter_interrupt(void); | 32 | extern void perf_counter_interrupt(void); |
33 | extern void perf_pending_interrupt(void); | ||
33 | 34 | ||
34 | extern void spurious_interrupt(void); | 35 | extern void spurious_interrupt(void); |
35 | extern void thermal_interrupt(void); | 36 | extern void thermal_interrupt(void); |
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 3cbd79bbb47c..545bb811ccb5 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h | |||
@@ -117,6 +117,11 @@ | |||
117 | #define GENERIC_INTERRUPT_VECTOR 0xed | 117 | #define GENERIC_INTERRUPT_VECTOR 0xed |
118 | 118 | ||
119 | /* | 119 | /* |
120 | * Performance monitoring pending work vector: | ||
121 | */ | ||
122 | #define LOCAL_PENDING_VECTOR 0xec | ||
123 | |||
124 | /* | ||
120 | * First APIC vector available to drivers: (vectors 0x30-0xee) we | 125 | * First APIC vector available to drivers: (vectors 0x30-0xee) we |
121 | * start at 0x31(0x41) to spread out vectors evenly between priority | 126 | * start at 0x31(0x41) to spread out vectors evenly between priority |
122 | * levels. (0x80 is the syscall vector) | 127 | * levels. (0x80 is the syscall vector) |
diff --git a/arch/x86/include/asm/perf_counter.h b/arch/x86/include/asm/perf_counter.h index e2b0e66b2353..d08dd52cb8ff 100644 --- a/arch/x86/include/asm/perf_counter.h +++ b/arch/x86/include/asm/perf_counter.h | |||
@@ -84,7 +84,8 @@ union cpuid10_edx { | |||
84 | #define MSR_ARCH_PERFMON_FIXED_CTR2 0x30b | 84 | #define MSR_ARCH_PERFMON_FIXED_CTR2 0x30b |
85 | #define X86_PMC_IDX_FIXED_BUS_CYCLES (X86_PMC_IDX_FIXED + 2) | 85 | #define X86_PMC_IDX_FIXED_BUS_CYCLES (X86_PMC_IDX_FIXED + 2) |
86 | 86 | ||
87 | #define set_perf_counter_pending() do { } while (0) | 87 | extern void set_perf_counter_pending(void); |
88 | |||
88 | #define clear_perf_counter_pending() do { } while (0) | 89 | #define clear_perf_counter_pending() do { } while (0) |
89 | #define test_perf_counter_pending() (0) | 90 | #define test_perf_counter_pending() (0) |
90 | 91 | ||
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c index c74e20d593a7..438415866fe4 100644 --- a/arch/x86/kernel/cpu/perf_counter.c +++ b/arch/x86/kernel/cpu/perf_counter.c | |||
@@ -849,6 +849,20 @@ void smp_perf_counter_interrupt(struct pt_regs *regs) | |||
849 | irq_exit(); | 849 | irq_exit(); |
850 | } | 850 | } |
851 | 851 | ||
852 | void smp_perf_pending_interrupt(struct pt_regs *regs) | ||
853 | { | ||
854 | irq_enter(); | ||
855 | ack_APIC_irq(); | ||
856 | inc_irq_stat(apic_pending_irqs); | ||
857 | perf_counter_do_pending(); | ||
858 | irq_exit(); | ||
859 | } | ||
860 | |||
861 | void set_perf_counter_pending(void) | ||
862 | { | ||
863 | apic->send_IPI_self(LOCAL_PENDING_VECTOR); | ||
864 | } | ||
865 | |||
852 | void perf_counters_lapic_init(int nmi) | 866 | void perf_counters_lapic_init(int nmi) |
853 | { | 867 | { |
854 | u32 apic_val; | 868 | u32 apic_val; |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 3f129d963a05..1d46cba56fd8 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -1028,6 +1028,8 @@ apicinterrupt SPURIOUS_APIC_VECTOR \ | |||
1028 | #ifdef CONFIG_PERF_COUNTERS | 1028 | #ifdef CONFIG_PERF_COUNTERS |
1029 | apicinterrupt LOCAL_PERF_VECTOR \ | 1029 | apicinterrupt LOCAL_PERF_VECTOR \ |
1030 | perf_counter_interrupt smp_perf_counter_interrupt | 1030 | perf_counter_interrupt smp_perf_counter_interrupt |
1031 | apicinterrupt LOCAL_PENDING_VECTOR \ | ||
1032 | perf_pending_interrupt smp_perf_pending_interrupt | ||
1031 | #endif | 1033 | #endif |
1032 | 1034 | ||
1033 | /* | 1035 | /* |
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 9c2754302ecc..d465487da587 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
@@ -67,6 +67,10 @@ static int show_other_interrupts(struct seq_file *p, int prec) | |||
67 | for_each_online_cpu(j) | 67 | for_each_online_cpu(j) |
68 | seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs); | 68 | seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs); |
69 | seq_printf(p, " Performance counter interrupts\n"); | 69 | seq_printf(p, " Performance counter interrupts\n"); |
70 | seq_printf(p, "PND: "); | ||
71 | for_each_online_cpu(j) | ||
72 | seq_printf(p, "%10u ", irq_stats(j)->apic_pending_irqs); | ||
73 | seq_printf(p, " Performance pending work\n"); | ||
70 | #endif | 74 | #endif |
71 | if (generic_interrupt_extension) { | 75 | if (generic_interrupt_extension) { |
72 | seq_printf(p, "PLT: "); | 76 | seq_printf(p, "PLT: "); |
@@ -171,6 +175,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu) | |||
171 | sum += irq_stats(cpu)->apic_timer_irqs; | 175 | sum += irq_stats(cpu)->apic_timer_irqs; |
172 | sum += irq_stats(cpu)->irq_spurious_count; | 176 | sum += irq_stats(cpu)->irq_spurious_count; |
173 | sum += irq_stats(cpu)->apic_perf_irqs; | 177 | sum += irq_stats(cpu)->apic_perf_irqs; |
178 | sum += irq_stats(cpu)->apic_pending_irqs; | ||
174 | #endif | 179 | #endif |
175 | if (generic_interrupt_extension) | 180 | if (generic_interrupt_extension) |
176 | sum += irq_stats(cpu)->generic_irqs; | 181 | sum += irq_stats(cpu)->generic_irqs; |
diff --git a/arch/x86/kernel/irqinit_32.c b/arch/x86/kernel/irqinit_32.c index 925d87cfc551..3190a6b961e6 100644 --- a/arch/x86/kernel/irqinit_32.c +++ b/arch/x86/kernel/irqinit_32.c | |||
@@ -166,6 +166,7 @@ static void __init apic_intr_init(void) | |||
166 | alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); | 166 | alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); |
167 | # ifdef CONFIG_PERF_COUNTERS | 167 | # ifdef CONFIG_PERF_COUNTERS |
168 | alloc_intr_gate(LOCAL_PERF_VECTOR, perf_counter_interrupt); | 168 | alloc_intr_gate(LOCAL_PERF_VECTOR, perf_counter_interrupt); |
169 | alloc_intr_gate(LOCAL_PENDING_VECTOR, perf_pending_interrupt); | ||
169 | # endif | 170 | # endif |
170 | 171 | ||
171 | # ifdef CONFIG_X86_MCE_P4THERMAL | 172 | # ifdef CONFIG_X86_MCE_P4THERMAL |
diff --git a/arch/x86/kernel/irqinit_64.c b/arch/x86/kernel/irqinit_64.c index 665e2ab48abd..53ceb26f80ff 100644 --- a/arch/x86/kernel/irqinit_64.c +++ b/arch/x86/kernel/irqinit_64.c | |||
@@ -156,6 +156,7 @@ static void __init apic_intr_init(void) | |||
156 | /* Performance monitoring interrupt: */ | 156 | /* Performance monitoring interrupt: */ |
157 | #ifdef CONFIG_PERF_COUNTERS | 157 | #ifdef CONFIG_PERF_COUNTERS |
158 | alloc_intr_gate(LOCAL_PERF_VECTOR, perf_counter_interrupt); | 158 | alloc_intr_gate(LOCAL_PERF_VECTOR, perf_counter_interrupt); |
159 | alloc_intr_gate(LOCAL_PENDING_VECTOR, perf_pending_interrupt); | ||
159 | #endif | 160 | #endif |
160 | } | 161 | } |
161 | 162 | ||