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 } 47 48 static void __init cleanup_nmi_testsuite(void) 49 { 50 unregister_nmi_handler(NMI_UNKNOWN, "nmi_selftest_unk"); 51 } 52 53 static int __init test_nmi_ipi_callback(unsigned int val, struct pt_regs *regs) 54 { 55 int cpu = raw_smp_processor_id(); 56 57 if (cpumask_test_and_clear_cpu(cpu, to_cpumask(nmi_ipi_mask))) 58 return NMI_HANDLED; 59 60 return NMI_DONE; 61 } 62 63 static void __init test_nmi_ipi(struct cpumask *mask) 64 { 65 unsigned long timeout; 66 67 if (register_nmi_handler(NMI_LOCAL, test_nmi_ipi_callback, 68 NMI_FLAG_FIRST, "nmi_selftest")) { 69 nmi_fail = FAILURE; 70 return; 71 } 72 73 /* sync above data before sending NMI */ 74 wmb(); 75 76 apic->send_IPI_mask(mask, NMI_VECTOR); 77 78 /* Don't wait longer than a second */ 79 timeout = USEC_PER_SEC; 80 while (!cpumask_empty(mask) && timeout--) 81 udelay(1); 82 83 /* What happens if we timeout, do we still unregister?? */ 84 unregister_nmi_handler(NMI_LOCAL, "nmi_selftest"); 85 86 if (!timeout) 87 nmi_fail = TIMEOUT; 88 return; 89 } 90 91 static void __init remote_ipi(void) 92 { 93 cpumask_copy(to_cpumask(nmi_ipi_mask), cpu_online_mask); 94 cpumask_clear_cpu(smp_processor_id(), to_cpumask(nmi_ipi_mask)); 95 if (!cpumask_empty(to_cpumask(nmi_ipi_mask))) 96 test_nmi_ipi(to_cpumask(nmi_ipi_mask)); 97 } 98 99 static void __init local_ipi(void) 100 { 101 cpumask_clear(to_cpumask(nmi_ipi_mask)); 102 cpumask_set_cpu(smp_processor_id(), to_cpumask(nmi_ipi_mask)); 103 test_nmi_ipi(to_cpumask(nmi_ipi_mask)); 104 } 105 106 static void __init reset_nmi(void) 107 { 108 nmi_fail = 0; 109 } 110 111 static void __init dotest(void (*testcase_fn)(void), int expected) 112 { 113 testcase_fn(); 114 /* 115 * Filter out expected failures: 116 */ 117 if (nmi_fail != expected) { 118 unexpected_testcase_failures++; 119 120 if (nmi_fail == FAILURE) 121 printk(KERN_CONT "FAILED |"); 122 else if (nmi_fail == TIMEOUT) 123 printk(KERN_CONT "TIMEOUT|"); 124 else 125 printk(KERN_CONT "ERROR |"); 126 dump_stack(); 127 } else { 128 testcase_successes++; 129 printk(KERN_CONT " ok |"); 130 } 131 testcase_total++; 132 133 reset_nmi(); 134 } 135 136 static inline void __init print_testname(const char *testname) 137 { 138 printk("%12s:", testname); 139 } 140 141 void __init nmi_selftest(void) 142 { 143 init_nmi_testsuite(); 144 145 /* 146 * Run the testsuite: 147 */ 148 printk("----------------\n"); 149 printk("| NMI testsuite:\n"); 150 printk("--------------------\n"); 151 152 print_testname("remote IPI"); 153 dotest(remote_ipi, SUCCESS); 154 printk(KERN_CONT "\n"); 155 print_testname("local IPI"); 156 dotest(local_ipi, SUCCESS); 157 printk(KERN_CONT "\n"); 158 159 cleanup_nmi_testsuite(); 160 161 if (unexpected_testcase_failures) { 162 printk("--------------------\n"); 163 printk("BUG: %3d unexpected failures (out of %3d) - debugging disabled! |\n", 164 unexpected_testcase_failures, testcase_total); 165 printk("-----------------------------------------------------------------\n"); 166 } else if (expected_testcase_failures && testcase_successes) { 167 printk("--------------------\n"); 168 printk("%3d out of %3d testcases failed, as expected. |\n", 169 expected_testcase_failures, testcase_total); 170 printk("----------------------------------------------------\n"); 171 } else if (expected_testcase_failures && !testcase_successes) { 172 printk("--------------------\n"); 173 printk("All %3d testcases failed, as expected. |\n", 174 expected_testcase_failures); 175 printk("----------------------------------------\n"); 176 } else { 177 printk("--------------------\n"); 178 printk("Good, all %3d testcases passed! |\n", 179 testcase_successes); 180 printk("---------------------------------\n"); 181 } 182 } 183