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