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 25static int __initdata nmi_fail; 26 27/* check to see if NMI IPIs work on this machine */ 28static DECLARE_BITMAP(nmi_ipi_mask, NR_CPUS) __initdata; 29 30static int __initdata testcase_total; 31static int __initdata testcase_successes; 32static int __initdata expected_testcase_failures; 33static int __initdata unexpected_testcase_failures; 34static int __initdata unexpected_testcase_unknowns; 35 36static int __init nmi_unk_cb(unsigned int val, struct pt_regs *regs) 37{ 38 unexpected_testcase_unknowns++; 39 return NMI_HANDLED; 40} 41 42static 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 49static void __init cleanup_nmi_testsuite(void) 50{ 51 unregister_nmi_handler(NMI_UNKNOWN, "nmi_selftest_unk"); 52} 53 54static 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 64static 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 92static 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 100static 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 107static void __init reset_nmi(void) 108{ 109 nmi_fail = 0; 110} 111 112static 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 137static inline void __init print_testname(const char *testname) 138{ 139 printk("%12s:", testname); 140} 141 142void __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