aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/nmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/nmi.c')
-rw-r--r--arch/i386/kernel/nmi.c137
1 files changed, 97 insertions, 40 deletions
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 821df34d2b3a..a98ba88a8c0c 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -122,64 +122,129 @@ static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr)
122/* checks for a bit availability (hack for oprofile) */ 122/* checks for a bit availability (hack for oprofile) */
123int avail_to_resrv_perfctr_nmi_bit(unsigned int counter) 123int avail_to_resrv_perfctr_nmi_bit(unsigned int counter)
124{ 124{
125 int cpu;
125 BUG_ON(counter > NMI_MAX_COUNTER_BITS); 126 BUG_ON(counter > NMI_MAX_COUNTER_BITS);
126 127 for_each_possible_cpu (cpu) {
127 return (!test_bit(counter, &__get_cpu_var(perfctr_nmi_owner))); 128 if (test_bit(counter, &per_cpu(perfctr_nmi_owner, cpu)))
129 return 0;
130 }
131 return 1;
128} 132}
129 133
130/* checks the an msr for availability */ 134/* checks the an msr for availability */
131int avail_to_resrv_perfctr_nmi(unsigned int msr) 135int avail_to_resrv_perfctr_nmi(unsigned int msr)
132{ 136{
133 unsigned int counter; 137 unsigned int counter;
138 int cpu;
134 139
135 counter = nmi_perfctr_msr_to_bit(msr); 140 counter = nmi_perfctr_msr_to_bit(msr);
136 BUG_ON(counter > NMI_MAX_COUNTER_BITS); 141 BUG_ON(counter > NMI_MAX_COUNTER_BITS);
137 142
138 return (!test_bit(counter, &__get_cpu_var(perfctr_nmi_owner))); 143 for_each_possible_cpu (cpu) {
144 if (test_bit(counter, &per_cpu(perfctr_nmi_owner, cpu)))
145 return 0;
146 }
147 return 1;
139} 148}
140 149
141int reserve_perfctr_nmi(unsigned int msr) 150static int __reserve_perfctr_nmi(int cpu, unsigned int msr)
142{ 151{
143 unsigned int counter; 152 unsigned int counter;
153 if (cpu < 0)
154 cpu = smp_processor_id();
144 155
145 counter = nmi_perfctr_msr_to_bit(msr); 156 counter = nmi_perfctr_msr_to_bit(msr);
146 BUG_ON(counter > NMI_MAX_COUNTER_BITS); 157 BUG_ON(counter > NMI_MAX_COUNTER_BITS);
147 158
148 if (!test_and_set_bit(counter, &__get_cpu_var(perfctr_nmi_owner))) 159 if (!test_and_set_bit(counter, &per_cpu(perfctr_nmi_owner, cpu)))
149 return 1; 160 return 1;
150 return 0; 161 return 0;
151} 162}
152 163
153void release_perfctr_nmi(unsigned int msr) 164static void __release_perfctr_nmi(int cpu, unsigned int msr)
154{ 165{
155 unsigned int counter; 166 unsigned int counter;
167 if (cpu < 0)
168 cpu = smp_processor_id();
156 169
157 counter = nmi_perfctr_msr_to_bit(msr); 170 counter = nmi_perfctr_msr_to_bit(msr);
158 BUG_ON(counter > NMI_MAX_COUNTER_BITS); 171 BUG_ON(counter > NMI_MAX_COUNTER_BITS);
159 172
160 clear_bit(counter, &__get_cpu_var(perfctr_nmi_owner)); 173 clear_bit(counter, &per_cpu(perfctr_nmi_owner, cpu));
161} 174}
162 175
163int reserve_evntsel_nmi(unsigned int msr) 176int reserve_perfctr_nmi(unsigned int msr)
177{
178 int cpu, i;
179 for_each_possible_cpu (cpu) {
180 if (!__reserve_perfctr_nmi(cpu, msr)) {
181 for_each_possible_cpu (i) {
182 if (i >= cpu)
183 break;
184 __release_perfctr_nmi(i, msr);
185 }
186 return 0;
187 }
188 }
189 return 1;
190}
191
192void release_perfctr_nmi(unsigned int msr)
193{
194 int cpu;
195 for_each_possible_cpu (cpu) {
196 __release_perfctr_nmi(cpu, msr);
197 }
198}
199
200int __reserve_evntsel_nmi(int cpu, unsigned int msr)
164{ 201{
165 unsigned int counter; 202 unsigned int counter;
203 if (cpu < 0)
204 cpu = smp_processor_id();
166 205
167 counter = nmi_evntsel_msr_to_bit(msr); 206 counter = nmi_evntsel_msr_to_bit(msr);
168 BUG_ON(counter > NMI_MAX_COUNTER_BITS); 207 BUG_ON(counter > NMI_MAX_COUNTER_BITS);
169 208
170 if (!test_and_set_bit(counter, &__get_cpu_var(evntsel_nmi_owner)[0])) 209 if (!test_and_set_bit(counter, &per_cpu(evntsel_nmi_owner, cpu)[0]))
171 return 1; 210 return 1;
172 return 0; 211 return 0;
173} 212}
174 213
175void release_evntsel_nmi(unsigned int msr) 214static void __release_evntsel_nmi(int cpu, unsigned int msr)
176{ 215{
177 unsigned int counter; 216 unsigned int counter;
217 if (cpu < 0)
218 cpu = smp_processor_id();
178 219
179 counter = nmi_evntsel_msr_to_bit(msr); 220 counter = nmi_evntsel_msr_to_bit(msr);
180 BUG_ON(counter > NMI_MAX_COUNTER_BITS); 221 BUG_ON(counter > NMI_MAX_COUNTER_BITS);
181 222
182 clear_bit(counter, &__get_cpu_var(evntsel_nmi_owner)[0]); 223 clear_bit(counter, &per_cpu(evntsel_nmi_owner, cpu)[0]);
224}
225
226int reserve_evntsel_nmi(unsigned int msr)
227{
228 int cpu, i;
229 for_each_possible_cpu (cpu) {
230 if (!__reserve_evntsel_nmi(cpu, msr)) {
231 for_each_possible_cpu (i) {
232 if (i >= cpu)
233 break;
234 __release_evntsel_nmi(i, msr);
235 }
236 return 0;
237 }
238 }
239 return 1;
240}
241
242void release_evntsel_nmi(unsigned int msr)
243{
244 int cpu;
245 for_each_possible_cpu (cpu) {
246 __release_evntsel_nmi(cpu, msr);
247 }
183} 248}
184 249
185static __cpuinit inline int nmi_known_cpu(void) 250static __cpuinit inline int nmi_known_cpu(void)
@@ -245,14 +310,6 @@ static int __init check_nmi_watchdog(void)
245 unsigned int *prev_nmi_count; 310 unsigned int *prev_nmi_count;
246 int cpu; 311 int cpu;
247 312
248 /* Enable NMI watchdog for newer systems.
249 Probably safe on most older systems too, but let's be careful.
250 IBM ThinkPads use INT10 inside SMM and that allows early NMI inside SMM
251 which hangs the system. Disable watchdog for all thinkpads */
252 if (nmi_watchdog == NMI_DEFAULT && dmi_get_year(DMI_BIOS_DATE) >= 2004 &&
253 !dmi_name_in_vendors("ThinkPad"))
254 nmi_watchdog = NMI_LOCAL_APIC;
255
256 if ((nmi_watchdog == NMI_NONE) || (nmi_watchdog == NMI_DEFAULT)) 313 if ((nmi_watchdog == NMI_NONE) || (nmi_watchdog == NMI_DEFAULT))
257 return 0; 314 return 0;
258 315
@@ -271,7 +328,7 @@ static int __init check_nmi_watchdog(void)
271 for_each_possible_cpu(cpu) 328 for_each_possible_cpu(cpu)
272 prev_nmi_count[cpu] = per_cpu(irq_stat, cpu).__nmi_count; 329 prev_nmi_count[cpu] = per_cpu(irq_stat, cpu).__nmi_count;
273 local_irq_enable(); 330 local_irq_enable();
274 mdelay((10*1000)/nmi_hz); // wait 10 ticks 331 mdelay((20*1000)/nmi_hz); // wait 20 ticks
275 332
276 for_each_possible_cpu(cpu) { 333 for_each_possible_cpu(cpu) {
277#ifdef CONFIG_SMP 334#ifdef CONFIG_SMP
@@ -515,10 +572,10 @@ static int setup_k7_watchdog(void)
515 572
516 perfctr_msr = MSR_K7_PERFCTR0; 573 perfctr_msr = MSR_K7_PERFCTR0;
517 evntsel_msr = MSR_K7_EVNTSEL0; 574 evntsel_msr = MSR_K7_EVNTSEL0;
518 if (!reserve_perfctr_nmi(perfctr_msr)) 575 if (!__reserve_perfctr_nmi(-1, perfctr_msr))
519 goto fail; 576 goto fail;
520 577
521 if (!reserve_evntsel_nmi(evntsel_msr)) 578 if (!__reserve_evntsel_nmi(-1, evntsel_msr))
522 goto fail1; 579 goto fail1;
523 580
524 wrmsrl(perfctr_msr, 0UL); 581 wrmsrl(perfctr_msr, 0UL);
@@ -541,7 +598,7 @@ static int setup_k7_watchdog(void)
541 wd->check_bit = 1ULL<<63; 598 wd->check_bit = 1ULL<<63;
542 return 1; 599 return 1;
543fail1: 600fail1:
544 release_perfctr_nmi(perfctr_msr); 601 __release_perfctr_nmi(-1, perfctr_msr);
545fail: 602fail:
546 return 0; 603 return 0;
547} 604}
@@ -552,8 +609,8 @@ static void stop_k7_watchdog(void)
552 609
553 wrmsr(wd->evntsel_msr, 0, 0); 610 wrmsr(wd->evntsel_msr, 0, 0);
554 611
555 release_evntsel_nmi(wd->evntsel_msr); 612 __release_evntsel_nmi(-1, wd->evntsel_msr);
556 release_perfctr_nmi(wd->perfctr_msr); 613 __release_perfctr_nmi(-1, wd->perfctr_msr);
557} 614}
558 615
559#define P6_EVNTSEL0_ENABLE (1 << 22) 616#define P6_EVNTSEL0_ENABLE (1 << 22)
@@ -571,10 +628,10 @@ static int setup_p6_watchdog(void)
571 628
572 perfctr_msr = MSR_P6_PERFCTR0; 629 perfctr_msr = MSR_P6_PERFCTR0;
573 evntsel_msr = MSR_P6_EVNTSEL0; 630 evntsel_msr = MSR_P6_EVNTSEL0;
574 if (!reserve_perfctr_nmi(perfctr_msr)) 631 if (!__reserve_perfctr_nmi(-1, perfctr_msr))
575 goto fail; 632 goto fail;
576 633
577 if (!reserve_evntsel_nmi(evntsel_msr)) 634 if (!__reserve_evntsel_nmi(-1, evntsel_msr))
578 goto fail1; 635 goto fail1;
579 636
580 wrmsrl(perfctr_msr, 0UL); 637 wrmsrl(perfctr_msr, 0UL);
@@ -598,7 +655,7 @@ static int setup_p6_watchdog(void)
598 wd->check_bit = 1ULL<<39; 655 wd->check_bit = 1ULL<<39;
599 return 1; 656 return 1;
600fail1: 657fail1:
601 release_perfctr_nmi(perfctr_msr); 658 __release_perfctr_nmi(-1, perfctr_msr);
602fail: 659fail:
603 return 0; 660 return 0;
604} 661}
@@ -609,8 +666,8 @@ static void stop_p6_watchdog(void)
609 666
610 wrmsr(wd->evntsel_msr, 0, 0); 667 wrmsr(wd->evntsel_msr, 0, 0);
611 668
612 release_evntsel_nmi(wd->evntsel_msr); 669 __release_evntsel_nmi(-1, wd->evntsel_msr);
613 release_perfctr_nmi(wd->perfctr_msr); 670 __release_perfctr_nmi(-1, wd->perfctr_msr);
614} 671}
615 672
616/* Note that these events don't tick when the CPU idles. This means 673/* Note that these events don't tick when the CPU idles. This means
@@ -676,10 +733,10 @@ static int setup_p4_watchdog(void)
676 cccr_val = P4_CCCR_OVF_PMI1 | P4_CCCR_ESCR_SELECT(4); 733 cccr_val = P4_CCCR_OVF_PMI1 | P4_CCCR_ESCR_SELECT(4);
677 } 734 }
678 735
679 if (!reserve_perfctr_nmi(perfctr_msr)) 736 if (!__reserve_perfctr_nmi(-1, perfctr_msr))
680 goto fail; 737 goto fail;
681 738
682 if (!reserve_evntsel_nmi(evntsel_msr)) 739 if (!__reserve_evntsel_nmi(-1, evntsel_msr))
683 goto fail1; 740 goto fail1;
684 741
685 evntsel = P4_ESCR_EVENT_SELECT(0x3F) 742 evntsel = P4_ESCR_EVENT_SELECT(0x3F)
@@ -703,7 +760,7 @@ static int setup_p4_watchdog(void)
703 wd->check_bit = 1ULL<<39; 760 wd->check_bit = 1ULL<<39;
704 return 1; 761 return 1;
705fail1: 762fail1:
706 release_perfctr_nmi(perfctr_msr); 763 __release_perfctr_nmi(-1, perfctr_msr);
707fail: 764fail:
708 return 0; 765 return 0;
709} 766}
@@ -715,8 +772,8 @@ static void stop_p4_watchdog(void)
715 wrmsr(wd->cccr_msr, 0, 0); 772 wrmsr(wd->cccr_msr, 0, 0);
716 wrmsr(wd->evntsel_msr, 0, 0); 773 wrmsr(wd->evntsel_msr, 0, 0);
717 774
718 release_evntsel_nmi(wd->evntsel_msr); 775 __release_evntsel_nmi(-1, wd->evntsel_msr);
719 release_perfctr_nmi(wd->perfctr_msr); 776 __release_perfctr_nmi(-1, wd->perfctr_msr);
720} 777}
721 778
722#define ARCH_PERFMON_NMI_EVENT_SEL ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL 779#define ARCH_PERFMON_NMI_EVENT_SEL ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
@@ -744,10 +801,10 @@ static int setup_intel_arch_watchdog(void)
744 perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0; 801 perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0;
745 evntsel_msr = MSR_ARCH_PERFMON_EVENTSEL0; 802 evntsel_msr = MSR_ARCH_PERFMON_EVENTSEL0;
746 803
747 if (!reserve_perfctr_nmi(perfctr_msr)) 804 if (!__reserve_perfctr_nmi(-1, perfctr_msr))
748 goto fail; 805 goto fail;
749 806
750 if (!reserve_evntsel_nmi(evntsel_msr)) 807 if (!__reserve_evntsel_nmi(-1, evntsel_msr))
751 goto fail1; 808 goto fail1;
752 809
753 wrmsrl(perfctr_msr, 0UL); 810 wrmsrl(perfctr_msr, 0UL);
@@ -772,7 +829,7 @@ static int setup_intel_arch_watchdog(void)
772 wd->check_bit = 1ULL << (eax.split.bit_width - 1); 829 wd->check_bit = 1ULL << (eax.split.bit_width - 1);
773 return 1; 830 return 1;
774fail1: 831fail1:
775 release_perfctr_nmi(perfctr_msr); 832 __release_perfctr_nmi(-1, perfctr_msr);
776fail: 833fail:
777 return 0; 834 return 0;
778} 835}
@@ -795,8 +852,8 @@ static void stop_intel_arch_watchdog(void)
795 return; 852 return;
796 853
797 wrmsr(wd->evntsel_msr, 0, 0); 854 wrmsr(wd->evntsel_msr, 0, 0);
798 release_evntsel_nmi(wd->evntsel_msr); 855 __release_evntsel_nmi(-1, wd->evntsel_msr);
799 release_perfctr_nmi(wd->perfctr_msr); 856 __release_perfctr_nmi(-1, wd->perfctr_msr);
800} 857}
801 858
802void setup_apic_nmi_watchdog (void *unused) 859void setup_apic_nmi_watchdog (void *unused)