1 /* 2 * arch/x86/kernel/nmi-selftest.c 3 * 4 * Testsuite for NMI: IPIs 5 * 6 * Started by Don Zickus: 7 * (using lib/locking-selftest.c as a guide) 8 * 9 * Copyright (C) 2011 Red Hat, Inc., Don Zickus <dzickus@redhat.com> 10 */ 11 12 #include <linux/smp.h> 13 #include <linux/cpumask.h> 14 #include <linux/delay.h> 15 #include <linux/init.h> 16 #include <linux/percpu.h> 17 18 #include <asm/apic.h> 19 #include <asm/nmi.h> 20 21 #define SUCCESS 0 22 #define FAILURE 1 23 #define TIMEOUT 2 24 25 static int __initdata nmi_fail; 26 27 /* check to see if NMI IPIs work on this machine */ 28 static DECLARE_BITMAP(nmi_ipi_mask, NR_CPUS) __initdata; 29 30 static int __initdata testcase_total; 31 static int __initdata testcase_successes; 32 static int __initdata expected_testcase_failures; 33 static int __initdata unexpected_testcase_failures; 34 static int __initdata unexpected_testcase_unknowns; 35 36 static int __init nmi_unk_cb(unsigned int val, struct pt_regs *regs) 37 { 38 unexpected_testcase_unknowns++; 39 return NMI_HANDLED; 40 } 41 42 static void __init init_nmi_testsuite(void) 43 { 44 /* trap all the unknown NMIs we may generate */ 45 register_nmi_handler(NMI_UNKNOWN, nmi_unk_cb, 0, "nmi_selftest_unk", 46 __initdata); 47 } 48 49 static void __init cleanup_nmi_testsuite(void) 50 { 51 unregister_nmi_handler(NMI_UNKNOWN, "nmi_selftest_unk"); 52 } 53 54 static int __init test_nmi_ipi_callback(unsigned int val, struct pt_regs *regs) 55 { 56 int cpu = raw_smp_processor_id(); 57 58 if (cpumask_test_and_clear_cpu(cpu, to_cpumask(nmi_ipi_mask))) 59 return NMI_HANDLED; 60 61 return NMI_DONE; 62 } 63 64 static void __init test_nmi_ipi(struct cpumask *mask) 65 { 66 unsigned long timeout; 67 68 if (register_nmi_handler(NMI_LOCAL, test_nmi_ipi_callback, 69 NMI_FLAG_FIRST, "nmi_selftest", __initdata)) { 70 nmi_fail = FAILURE; 71 return; 72 } 73 74 /* sync above data before sending NMI */ 75 wmb(); 76 77 apic->send_IPI_mask(mask, NMI_VECTOR); 78 79 /* Don't wait longer than a second */ 80 timeout = USEC_PER_SEC; 81 while (!cpumask_empty(mask) && --timeout) 82 udelay(1); 83 84 /* What happens if we timeout, do we still unregister?? */ 85 unregister_nmi_handler(NMI_LOCAL, "nmi_selftest"); 86 87 if (!timeout) 88 nmi_fail = TIMEOUT; 89 return; 90 } 91 92 static void __init remote_ipi(void) 93 { 94 cpumask_copy(to_cpumask(nmi_ipi_mask), cpu_online_mask); 95 cpumask_clear_cpu(smp_processor_id(), to_cpumask(nmi_ipi_mask)); 96 if (!cpumask_empty(to_cpumask(nmi_ipi_mask))) 97 test_nmi_ipi(to_cpumask(nmi_ipi_mask)); 98 } 99 100 static void __init local_ipi(void) 101 { 102 cpumask_clear(to_cpumask(nmi_ipi_mask)); 103 cpumask_set_cpu(smp_processor_id(), to_cpumask(nmi_ipi_mask)); 104 test_nmi_ipi(to_cpumask(nmi_ipi_mask)); 105 } 106 107 static void __init reset_nmi(void) 108 { 109 nmi_fail = 0; 110 } 111 112 static void __init dotest(void (*testcase_fn)(void), int expected) 113 { 114 testcase_fn(); 115 /* 116 * Filter out expected failures: 117 */ 118 if (nmi_fail != expected) { 119 unexpected_testcase_failures++; 120 121 if (nmi_fail == FAILURE) 122 printk(KERN_CONT "FAILED |"); 123 else if (nmi_fail == TIMEOUT) 124 printk(KERN_CONT "TIMEOUT|"); 125 else 126 printk(KERN_CONT "ERROR |"); 127 dump_stack(); 128 } else { 129 testcase_successes++; 130 printk(KERN_CONT " ok |"); 131 } 132 testcase_total++; 133 134 reset_nmi(); 135 } 136 137 static inline void __init print_testname(const char *testname) 138 { 139 printk("%12s:", testname); 140 } 141 142 void __init nmi_selftest(void) 143 { 144 init_nmi_testsuite(); 145 146 /* 147 * Run the testsuite: 148 */ 149 printk("----------------\n"); 150 printk("| NMI testsuite:\n"); 151 printk("--------------------\n"); 152 153 print_testname("remote IPI"); 154 dotest(remote_ipi, SUCCESS); 155 printk(KERN_CONT "\n"); 156 print_testname("local IPI"); 157 dotest(local_ipi, SUCCESS); 158 printk(KERN_CONT "\n"); 159 160 cleanup_nmi_testsuite(); 161 162 if (unexpected_testcase_failures) { 163 printk("--------------------\n"); 164 printk("BUG: %3d unexpected failures (out of %3d) - debugging disabled! |\n", 165 unexpected_testcase_failures, testcase_total); 166 printk("-----------------------------------------------------------------\n"); 167 } else if (expected_testcase_failures && testcase_successes) { 168 printk("--------------------\n"); 169 printk("%3d out of %3d testcases failed, as expected. |\n", 170 expected_testcase_failures, testcase_total); 171 printk("----------------------------------------------------\n"); 172 } else if (expected_testcase_failures && !testcase_successes) { 173 printk("--------------------\n"); 174 printk("All %3d testcases failed, as expected. |\n", 175 expected_testcase_failures); 176 printk("----------------------------------------\n"); 177 } else { 178 printk("--------------------\n"); 179 printk("Good, all %3d testcases passed! |\n", 180 testcase_successes); 181 printk("---------------------------------\n"); 182 } 183 } 184