diff options
Diffstat (limited to 'arch/x86_64/kernel/nmi.c')
-rw-r--r-- | arch/x86_64/kernel/nmi.c | 135 |
1 files changed, 99 insertions, 36 deletions
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index 486f4c61a948..dfab9f167366 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c | |||
@@ -39,15 +39,17 @@ int panic_on_unrecovered_nmi; | |||
39 | * different subsystems this reservation system just tries to coordinate | 39 | * different subsystems this reservation system just tries to coordinate |
40 | * things a little | 40 | * things a little |
41 | */ | 41 | */ |
42 | static DEFINE_PER_CPU(unsigned, perfctr_nmi_owner); | ||
43 | static DEFINE_PER_CPU(unsigned, evntsel_nmi_owner[2]); | ||
44 | |||
45 | static cpumask_t backtrace_mask = CPU_MASK_NONE; | ||
46 | 42 | ||
47 | /* this number is calculated from Intel's MSR_P4_CRU_ESCR5 register and it's | 43 | /* this number is calculated from Intel's MSR_P4_CRU_ESCR5 register and it's |
48 | * offset from MSR_P4_BSU_ESCR0. It will be the max for all platforms (for now) | 44 | * offset from MSR_P4_BSU_ESCR0. It will be the max for all platforms (for now) |
49 | */ | 45 | */ |
50 | #define NMI_MAX_COUNTER_BITS 66 | 46 | #define NMI_MAX_COUNTER_BITS 66 |
47 | #define NMI_MAX_COUNTER_LONGS BITS_TO_LONGS(NMI_MAX_COUNTER_BITS) | ||
48 | |||
49 | static DEFINE_PER_CPU(unsigned, perfctr_nmi_owner[NMI_MAX_COUNTER_LONGS]); | ||
50 | static DEFINE_PER_CPU(unsigned, evntsel_nmi_owner[NMI_MAX_COUNTER_LONGS]); | ||
51 | |||
52 | static cpumask_t backtrace_mask = CPU_MASK_NONE; | ||
51 | 53 | ||
52 | /* nmi_active: | 54 | /* nmi_active: |
53 | * >0: the lapic NMI watchdog is active, but can be disabled | 55 | * >0: the lapic NMI watchdog is active, but can be disabled |
@@ -108,64 +110,128 @@ static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr) | |||
108 | /* checks for a bit availability (hack for oprofile) */ | 110 | /* checks for a bit availability (hack for oprofile) */ |
109 | int avail_to_resrv_perfctr_nmi_bit(unsigned int counter) | 111 | int avail_to_resrv_perfctr_nmi_bit(unsigned int counter) |
110 | { | 112 | { |
113 | int cpu; | ||
111 | BUG_ON(counter > NMI_MAX_COUNTER_BITS); | 114 | BUG_ON(counter > NMI_MAX_COUNTER_BITS); |
112 | 115 | for_each_possible_cpu (cpu) { | |
113 | return (!test_bit(counter, &__get_cpu_var(perfctr_nmi_owner))); | 116 | if (test_bit(counter, &per_cpu(perfctr_nmi_owner, cpu))) |
117 | return 0; | ||
118 | } | ||
119 | return 1; | ||
114 | } | 120 | } |
115 | 121 | ||
116 | /* checks the an msr for availability */ | 122 | /* checks the an msr for availability */ |
117 | int avail_to_resrv_perfctr_nmi(unsigned int msr) | 123 | int avail_to_resrv_perfctr_nmi(unsigned int msr) |
118 | { | 124 | { |
119 | unsigned int counter; | 125 | unsigned int counter; |
126 | int cpu; | ||
120 | 127 | ||
121 | counter = nmi_perfctr_msr_to_bit(msr); | 128 | counter = nmi_perfctr_msr_to_bit(msr); |
122 | BUG_ON(counter > NMI_MAX_COUNTER_BITS); | 129 | BUG_ON(counter > NMI_MAX_COUNTER_BITS); |
123 | 130 | ||
124 | return (!test_bit(counter, &__get_cpu_var(perfctr_nmi_owner))); | 131 | for_each_possible_cpu (cpu) { |
132 | if (test_bit(counter, &per_cpu(perfctr_nmi_owner, cpu))) | ||
133 | return 0; | ||
134 | } | ||
135 | return 1; | ||
125 | } | 136 | } |
126 | 137 | ||
127 | int reserve_perfctr_nmi(unsigned int msr) | 138 | static int __reserve_perfctr_nmi(int cpu, unsigned int msr) |
128 | { | 139 | { |
129 | unsigned int counter; | 140 | unsigned int counter; |
141 | if (cpu < 0) | ||
142 | cpu = smp_processor_id(); | ||
130 | 143 | ||
131 | counter = nmi_perfctr_msr_to_bit(msr); | 144 | counter = nmi_perfctr_msr_to_bit(msr); |
132 | BUG_ON(counter > NMI_MAX_COUNTER_BITS); | 145 | BUG_ON(counter > NMI_MAX_COUNTER_BITS); |
133 | 146 | ||
134 | if (!test_and_set_bit(counter, &__get_cpu_var(perfctr_nmi_owner))) | 147 | if (!test_and_set_bit(counter, &per_cpu(perfctr_nmi_owner, cpu))) |
135 | return 1; | 148 | return 1; |
136 | return 0; | 149 | return 0; |
137 | } | 150 | } |
138 | 151 | ||
139 | void release_perfctr_nmi(unsigned int msr) | 152 | static void __release_perfctr_nmi(int cpu, unsigned int msr) |
140 | { | 153 | { |
141 | unsigned int counter; | 154 | unsigned int counter; |
155 | if (cpu < 0) | ||
156 | cpu = smp_processor_id(); | ||
142 | 157 | ||
143 | counter = nmi_perfctr_msr_to_bit(msr); | 158 | counter = nmi_perfctr_msr_to_bit(msr); |
144 | BUG_ON(counter > NMI_MAX_COUNTER_BITS); | 159 | BUG_ON(counter > NMI_MAX_COUNTER_BITS); |
145 | 160 | ||
146 | clear_bit(counter, &__get_cpu_var(perfctr_nmi_owner)); | 161 | clear_bit(counter, &per_cpu(perfctr_nmi_owner, cpu)); |
147 | } | 162 | } |
148 | 163 | ||
149 | int reserve_evntsel_nmi(unsigned int msr) | 164 | int reserve_perfctr_nmi(unsigned int msr) |
165 | { | ||
166 | int cpu, i; | ||
167 | for_each_possible_cpu (cpu) { | ||
168 | if (!__reserve_perfctr_nmi(cpu, msr)) { | ||
169 | for_each_possible_cpu (i) { | ||
170 | if (i >= cpu) | ||
171 | break; | ||
172 | __release_perfctr_nmi(i, msr); | ||
173 | } | ||
174 | return 0; | ||
175 | } | ||
176 | } | ||
177 | return 1; | ||
178 | } | ||
179 | |||
180 | void release_perfctr_nmi(unsigned int msr) | ||
181 | { | ||
182 | int cpu; | ||
183 | for_each_possible_cpu (cpu) | ||
184 | __release_perfctr_nmi(cpu, msr); | ||
185 | } | ||
186 | |||
187 | int __reserve_evntsel_nmi(int cpu, unsigned int msr) | ||
150 | { | 188 | { |
151 | unsigned int counter; | 189 | unsigned int counter; |
190 | if (cpu < 0) | ||
191 | cpu = smp_processor_id(); | ||
152 | 192 | ||
153 | counter = nmi_evntsel_msr_to_bit(msr); | 193 | counter = nmi_evntsel_msr_to_bit(msr); |
154 | BUG_ON(counter > NMI_MAX_COUNTER_BITS); | 194 | BUG_ON(counter > NMI_MAX_COUNTER_BITS); |
155 | 195 | ||
156 | if (!test_and_set_bit(counter, &__get_cpu_var(evntsel_nmi_owner))) | 196 | if (!test_and_set_bit(counter, &per_cpu(evntsel_nmi_owner, cpu)[0])) |
157 | return 1; | 197 | return 1; |
158 | return 0; | 198 | return 0; |
159 | } | 199 | } |
160 | 200 | ||
161 | void release_evntsel_nmi(unsigned int msr) | 201 | static void __release_evntsel_nmi(int cpu, unsigned int msr) |
162 | { | 202 | { |
163 | unsigned int counter; | 203 | unsigned int counter; |
204 | if (cpu < 0) | ||
205 | cpu = smp_processor_id(); | ||
164 | 206 | ||
165 | counter = nmi_evntsel_msr_to_bit(msr); | 207 | counter = nmi_evntsel_msr_to_bit(msr); |
166 | BUG_ON(counter > NMI_MAX_COUNTER_BITS); | 208 | BUG_ON(counter > NMI_MAX_COUNTER_BITS); |
167 | 209 | ||
168 | clear_bit(counter, &__get_cpu_var(evntsel_nmi_owner)); | 210 | clear_bit(counter, &per_cpu(evntsel_nmi_owner, cpu)[0]); |
211 | } | ||
212 | |||
213 | int reserve_evntsel_nmi(unsigned int msr) | ||
214 | { | ||
215 | int cpu, i; | ||
216 | for_each_possible_cpu (cpu) { | ||
217 | if (!__reserve_evntsel_nmi(cpu, msr)) { | ||
218 | for_each_possible_cpu (i) { | ||
219 | if (i >= cpu) | ||
220 | break; | ||
221 | __release_evntsel_nmi(i, msr); | ||
222 | } | ||
223 | return 0; | ||
224 | } | ||
225 | } | ||
226 | return 1; | ||
227 | } | ||
228 | |||
229 | void release_evntsel_nmi(unsigned int msr) | ||
230 | { | ||
231 | int cpu; | ||
232 | for_each_possible_cpu (cpu) { | ||
233 | __release_evntsel_nmi(cpu, msr); | ||
234 | } | ||
169 | } | 235 | } |
170 | 236 | ||
171 | static __cpuinit inline int nmi_known_cpu(void) | 237 | static __cpuinit inline int nmi_known_cpu(void) |
@@ -187,10 +253,7 @@ void nmi_watchdog_default(void) | |||
187 | { | 253 | { |
188 | if (nmi_watchdog != NMI_DEFAULT) | 254 | if (nmi_watchdog != NMI_DEFAULT) |
189 | return; | 255 | return; |
190 | if (nmi_known_cpu()) | 256 | nmi_watchdog = NMI_NONE; |
191 | nmi_watchdog = NMI_LOCAL_APIC; | ||
192 | else | ||
193 | nmi_watchdog = NMI_IO_APIC; | ||
194 | } | 257 | } |
195 | 258 | ||
196 | static int endflag __initdata = 0; | 259 | static int endflag __initdata = 0; |
@@ -256,7 +319,7 @@ int __init check_nmi_watchdog (void) | |||
256 | for (cpu = 0; cpu < NR_CPUS; cpu++) | 319 | for (cpu = 0; cpu < NR_CPUS; cpu++) |
257 | counts[cpu] = cpu_pda(cpu)->__nmi_count; | 320 | counts[cpu] = cpu_pda(cpu)->__nmi_count; |
258 | local_irq_enable(); | 321 | local_irq_enable(); |
259 | mdelay((10*1000)/nmi_hz); // wait 10 ticks | 322 | mdelay((20*1000)/nmi_hz); // wait 20 ticks |
260 | 323 | ||
261 | for_each_online_cpu(cpu) { | 324 | for_each_online_cpu(cpu) { |
262 | if (!per_cpu(nmi_watchdog_ctlblk, cpu).enabled) | 325 | if (!per_cpu(nmi_watchdog_ctlblk, cpu).enabled) |
@@ -475,10 +538,10 @@ static int setup_k7_watchdog(void) | |||
475 | 538 | ||
476 | perfctr_msr = MSR_K7_PERFCTR0; | 539 | perfctr_msr = MSR_K7_PERFCTR0; |
477 | evntsel_msr = MSR_K7_EVNTSEL0; | 540 | evntsel_msr = MSR_K7_EVNTSEL0; |
478 | if (!reserve_perfctr_nmi(perfctr_msr)) | 541 | if (!__reserve_perfctr_nmi(-1, perfctr_msr)) |
479 | goto fail; | 542 | goto fail; |
480 | 543 | ||
481 | if (!reserve_evntsel_nmi(evntsel_msr)) | 544 | if (!__reserve_evntsel_nmi(-1, evntsel_msr)) |
482 | goto fail1; | 545 | goto fail1; |
483 | 546 | ||
484 | /* Simulator may not support it */ | 547 | /* Simulator may not support it */ |
@@ -504,9 +567,9 @@ static int setup_k7_watchdog(void) | |||
504 | wd->check_bit = 1ULL<<63; | 567 | wd->check_bit = 1ULL<<63; |
505 | return 1; | 568 | return 1; |
506 | fail2: | 569 | fail2: |
507 | release_evntsel_nmi(evntsel_msr); | 570 | __release_evntsel_nmi(-1, evntsel_msr); |
508 | fail1: | 571 | fail1: |
509 | release_perfctr_nmi(perfctr_msr); | 572 | __release_perfctr_nmi(-1, perfctr_msr); |
510 | fail: | 573 | fail: |
511 | return 0; | 574 | return 0; |
512 | } | 575 | } |
@@ -517,8 +580,8 @@ static void stop_k7_watchdog(void) | |||
517 | 580 | ||
518 | wrmsr(wd->evntsel_msr, 0, 0); | 581 | wrmsr(wd->evntsel_msr, 0, 0); |
519 | 582 | ||
520 | release_evntsel_nmi(wd->evntsel_msr); | 583 | __release_evntsel_nmi(-1, wd->evntsel_msr); |
521 | release_perfctr_nmi(wd->perfctr_msr); | 584 | __release_perfctr_nmi(-1, wd->perfctr_msr); |
522 | } | 585 | } |
523 | 586 | ||
524 | /* Note that these events don't tick when the CPU idles. This means | 587 | /* Note that these events don't tick when the CPU idles. This means |
@@ -584,10 +647,10 @@ static int setup_p4_watchdog(void) | |||
584 | cccr_val = P4_CCCR_OVF_PMI1 | P4_CCCR_ESCR_SELECT(4); | 647 | cccr_val = P4_CCCR_OVF_PMI1 | P4_CCCR_ESCR_SELECT(4); |
585 | } | 648 | } |
586 | 649 | ||
587 | if (!reserve_perfctr_nmi(perfctr_msr)) | 650 | if (!__reserve_perfctr_nmi(-1, perfctr_msr)) |
588 | goto fail; | 651 | goto fail; |
589 | 652 | ||
590 | if (!reserve_evntsel_nmi(evntsel_msr)) | 653 | if (!__reserve_evntsel_nmi(-1, evntsel_msr)) |
591 | goto fail1; | 654 | goto fail1; |
592 | 655 | ||
593 | evntsel = P4_ESCR_EVENT_SELECT(0x3F) | 656 | evntsel = P4_ESCR_EVENT_SELECT(0x3F) |
@@ -612,7 +675,7 @@ static int setup_p4_watchdog(void) | |||
612 | wd->check_bit = 1ULL<<39; | 675 | wd->check_bit = 1ULL<<39; |
613 | return 1; | 676 | return 1; |
614 | fail1: | 677 | fail1: |
615 | release_perfctr_nmi(perfctr_msr); | 678 | __release_perfctr_nmi(-1, perfctr_msr); |
616 | fail: | 679 | fail: |
617 | return 0; | 680 | return 0; |
618 | } | 681 | } |
@@ -624,8 +687,8 @@ static void stop_p4_watchdog(void) | |||
624 | wrmsr(wd->cccr_msr, 0, 0); | 687 | wrmsr(wd->cccr_msr, 0, 0); |
625 | wrmsr(wd->evntsel_msr, 0, 0); | 688 | wrmsr(wd->evntsel_msr, 0, 0); |
626 | 689 | ||
627 | release_evntsel_nmi(wd->evntsel_msr); | 690 | __release_evntsel_nmi(-1, wd->evntsel_msr); |
628 | release_perfctr_nmi(wd->perfctr_msr); | 691 | __release_perfctr_nmi(-1, wd->perfctr_msr); |
629 | } | 692 | } |
630 | 693 | ||
631 | #define ARCH_PERFMON_NMI_EVENT_SEL ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL | 694 | #define ARCH_PERFMON_NMI_EVENT_SEL ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL |
@@ -653,10 +716,10 @@ static int setup_intel_arch_watchdog(void) | |||
653 | perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0; | 716 | perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0; |
654 | evntsel_msr = MSR_ARCH_PERFMON_EVENTSEL0; | 717 | evntsel_msr = MSR_ARCH_PERFMON_EVENTSEL0; |
655 | 718 | ||
656 | if (!reserve_perfctr_nmi(perfctr_msr)) | 719 | if (!__reserve_perfctr_nmi(-1, perfctr_msr)) |
657 | goto fail; | 720 | goto fail; |
658 | 721 | ||
659 | if (!reserve_evntsel_nmi(evntsel_msr)) | 722 | if (!__reserve_evntsel_nmi(-1, evntsel_msr)) |
660 | goto fail1; | 723 | goto fail1; |
661 | 724 | ||
662 | wrmsrl(perfctr_msr, 0UL); | 725 | wrmsrl(perfctr_msr, 0UL); |
@@ -683,7 +746,7 @@ static int setup_intel_arch_watchdog(void) | |||
683 | wd->check_bit = 1ULL << (eax.split.bit_width - 1); | 746 | wd->check_bit = 1ULL << (eax.split.bit_width - 1); |
684 | return 1; | 747 | return 1; |
685 | fail1: | 748 | fail1: |
686 | release_perfctr_nmi(perfctr_msr); | 749 | __release_perfctr_nmi(-1, perfctr_msr); |
687 | fail: | 750 | fail: |
688 | return 0; | 751 | return 0; |
689 | } | 752 | } |
@@ -707,8 +770,8 @@ static void stop_intel_arch_watchdog(void) | |||
707 | 770 | ||
708 | wrmsr(wd->evntsel_msr, 0, 0); | 771 | wrmsr(wd->evntsel_msr, 0, 0); |
709 | 772 | ||
710 | release_evntsel_nmi(wd->evntsel_msr); | 773 | __release_evntsel_nmi(-1, wd->evntsel_msr); |
711 | release_perfctr_nmi(wd->perfctr_msr); | 774 | __release_perfctr_nmi(-1, wd->perfctr_msr); |
712 | } | 775 | } |
713 | 776 | ||
714 | void setup_apic_nmi_watchdog(void *unused) | 777 | void setup_apic_nmi_watchdog(void *unused) |