nmi_selftest.c 4.5 KB

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