nmi_selftest.c 4.2 KB

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