Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * arch/x86/kernel/nmi-selftest.c
0004  *
0005  * Testsuite for NMI: IPIs
0006  *
0007  * Started by Don Zickus:
0008  * (using lib/locking-selftest.c as a guide)
0009  *
0010  *   Copyright (C) 2011 Red Hat, Inc., Don Zickus <dzickus@redhat.com>
0011  */
0012 
0013 #include <linux/smp.h>
0014 #include <linux/cpumask.h>
0015 #include <linux/delay.h>
0016 #include <linux/init.h>
0017 #include <linux/percpu.h>
0018 
0019 #include <asm/apic.h>
0020 #include <asm/nmi.h>
0021 
0022 #define SUCCESS     0
0023 #define FAILURE     1
0024 #define TIMEOUT     2
0025 
0026 static int __initdata nmi_fail;
0027 
0028 /* check to see if NMI IPIs work on this machine */
0029 static DECLARE_BITMAP(nmi_ipi_mask, NR_CPUS) __initdata;
0030 
0031 static int __initdata testcase_total;
0032 static int __initdata testcase_successes;
0033 static int __initdata expected_testcase_failures;
0034 static int __initdata unexpected_testcase_failures;
0035 static int __initdata unexpected_testcase_unknowns;
0036 
0037 static int __init nmi_unk_cb(unsigned int val, struct pt_regs *regs)
0038 {
0039     unexpected_testcase_unknowns++;
0040     return NMI_HANDLED;
0041 }
0042 
0043 static void __init init_nmi_testsuite(void)
0044 {
0045     /* trap all the unknown NMIs we may generate */
0046     register_nmi_handler(NMI_UNKNOWN, nmi_unk_cb, 0, "nmi_selftest_unk",
0047             __initdata);
0048 }
0049 
0050 static void __init cleanup_nmi_testsuite(void)
0051 {
0052     unregister_nmi_handler(NMI_UNKNOWN, "nmi_selftest_unk");
0053 }
0054 
0055 static int __init test_nmi_ipi_callback(unsigned int val, struct pt_regs *regs)
0056 {
0057         int cpu = raw_smp_processor_id();
0058 
0059         if (cpumask_test_and_clear_cpu(cpu, to_cpumask(nmi_ipi_mask)))
0060                 return NMI_HANDLED;
0061 
0062         return NMI_DONE;
0063 }
0064 
0065 static void __init test_nmi_ipi(struct cpumask *mask)
0066 {
0067     unsigned long timeout;
0068 
0069     if (register_nmi_handler(NMI_LOCAL, test_nmi_ipi_callback,
0070                  NMI_FLAG_FIRST, "nmi_selftest", __initdata)) {
0071         nmi_fail = FAILURE;
0072         return;
0073     }
0074 
0075     /* sync above data before sending NMI */
0076     wmb();
0077 
0078     apic->send_IPI_mask(mask, NMI_VECTOR);
0079 
0080     /* Don't wait longer than a second */
0081     timeout = USEC_PER_SEC;
0082     while (!cpumask_empty(mask) && --timeout)
0083             udelay(1);
0084 
0085     /* What happens if we timeout, do we still unregister?? */
0086     unregister_nmi_handler(NMI_LOCAL, "nmi_selftest");
0087 
0088     if (!timeout)
0089         nmi_fail = TIMEOUT;
0090     return;
0091 }
0092 
0093 static void __init remote_ipi(void)
0094 {
0095     cpumask_copy(to_cpumask(nmi_ipi_mask), cpu_online_mask);
0096     cpumask_clear_cpu(smp_processor_id(), to_cpumask(nmi_ipi_mask));
0097     if (!cpumask_empty(to_cpumask(nmi_ipi_mask)))
0098         test_nmi_ipi(to_cpumask(nmi_ipi_mask));
0099 }
0100 
0101 static void __init local_ipi(void)
0102 {
0103     cpumask_clear(to_cpumask(nmi_ipi_mask));
0104     cpumask_set_cpu(smp_processor_id(), to_cpumask(nmi_ipi_mask));
0105     test_nmi_ipi(to_cpumask(nmi_ipi_mask));
0106 }
0107 
0108 static void __init reset_nmi(void)
0109 {
0110     nmi_fail = 0;
0111 }
0112 
0113 static void __init dotest(void (*testcase_fn)(void), int expected)
0114 {
0115     testcase_fn();
0116     /*
0117      * Filter out expected failures:
0118      */
0119     if (nmi_fail != expected) {
0120         unexpected_testcase_failures++;
0121 
0122         if (nmi_fail == FAILURE)
0123             printk(KERN_CONT "FAILED |");
0124         else if (nmi_fail == TIMEOUT)
0125             printk(KERN_CONT "TIMEOUT|");
0126         else
0127             printk(KERN_CONT "ERROR  |");
0128         dump_stack();
0129     } else {
0130         testcase_successes++;
0131         printk(KERN_CONT "  ok  |");
0132     }
0133     testcase_total++;
0134 
0135     reset_nmi();
0136 }
0137 
0138 static inline void __init print_testname(const char *testname)
0139 {
0140     printk("%12s:", testname);
0141 }
0142 
0143 void __init nmi_selftest(void)
0144 {
0145     init_nmi_testsuite();
0146 
0147         /*
0148      * Run the testsuite:
0149      */
0150     printk("----------------\n");
0151     printk("| NMI testsuite:\n");
0152     printk("--------------------\n");
0153 
0154     print_testname("remote IPI");
0155     dotest(remote_ipi, SUCCESS);
0156     printk(KERN_CONT "\n");
0157     print_testname("local IPI");
0158     dotest(local_ipi, SUCCESS);
0159     printk(KERN_CONT "\n");
0160 
0161     cleanup_nmi_testsuite();
0162 
0163     if (unexpected_testcase_failures) {
0164         printk("--------------------\n");
0165         printk("BUG: %3d unexpected failures (out of %3d) - debugging disabled! |\n",
0166             unexpected_testcase_failures, testcase_total);
0167         printk("-----------------------------------------------------------------\n");
0168     } else if (expected_testcase_failures && testcase_successes) {
0169         printk("--------------------\n");
0170         printk("%3d out of %3d testcases failed, as expected. |\n",
0171             expected_testcase_failures, testcase_total);
0172         printk("----------------------------------------------------\n");
0173     } else if (expected_testcase_failures && !testcase_successes) {
0174         printk("--------------------\n");
0175         printk("All %3d testcases failed, as expected. |\n",
0176             expected_testcase_failures);
0177         printk("----------------------------------------\n");
0178     } else {
0179         printk("--------------------\n");
0180         printk("Good, all %3d testcases passed! |\n",
0181             testcase_successes);
0182         printk("---------------------------------\n");
0183     }
0184 }