ds_selftest.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * Debug Store support - selftest
  3. *
  4. *
  5. * Copyright (C) 2009 Intel Corporation.
  6. * Markus Metzger <markus.t.metzger@intel.com>, 2009
  7. */
  8. #include "ds_selftest.h"
  9. #include <linux/kernel.h>
  10. #include <linux/string.h>
  11. #include <linux/smp.h>
  12. #include <asm/ds.h>
  13. #define BUFFER_SIZE 1021 /* Intentionally chose an odd size. */
  14. static int ds_selftest_bts_consistency(const struct bts_trace *trace)
  15. {
  16. int error = 0;
  17. if (!trace) {
  18. printk(KERN_CONT "failed to access trace...");
  19. /* Bail out. Other tests are pointless. */
  20. return -1;
  21. }
  22. if (!trace->read) {
  23. printk(KERN_CONT "bts read not available...");
  24. error = -1;
  25. }
  26. /* Do some sanity checks on the trace configuration. */
  27. if (!trace->ds.n) {
  28. printk(KERN_CONT "empty bts buffer...");
  29. error = -1;
  30. }
  31. if (!trace->ds.size) {
  32. printk(KERN_CONT "bad bts trace setup...");
  33. error = -1;
  34. }
  35. if (trace->ds.end !=
  36. (char *)trace->ds.begin + (trace->ds.n * trace->ds.size)) {
  37. printk(KERN_CONT "bad bts buffer setup...");
  38. error = -1;
  39. }
  40. if ((trace->ds.top < trace->ds.begin) ||
  41. (trace->ds.end <= trace->ds.top)) {
  42. printk(KERN_CONT "bts top out of bounds...");
  43. error = -1;
  44. }
  45. return error;
  46. }
  47. static int ds_selftest_bts_read(struct bts_tracer *tracer,
  48. const struct bts_trace *trace,
  49. const void *from, const void *to)
  50. {
  51. const unsigned char *at;
  52. /*
  53. * Check a few things which do not belong to this test.
  54. * They should be covered by other tests.
  55. */
  56. if (!trace)
  57. return -1;
  58. if (!trace->read)
  59. return -1;
  60. if (to < from)
  61. return -1;
  62. if (from < trace->ds.begin)
  63. return -1;
  64. if (trace->ds.end < to)
  65. return -1;
  66. if (!trace->ds.size)
  67. return -1;
  68. /* Now to the test itself. */
  69. for (at = from; (void *)at < to; at += trace->ds.size) {
  70. struct bts_struct bts;
  71. unsigned long index;
  72. int error;
  73. if (((void *)at - trace->ds.begin) % trace->ds.size) {
  74. printk(KERN_CONT
  75. "read from non-integer index...");
  76. return -1;
  77. }
  78. index = ((void *)at - trace->ds.begin) / trace->ds.size;
  79. memset(&bts, 0, sizeof(bts));
  80. error = trace->read(tracer, at, &bts);
  81. if (error < 0) {
  82. printk(KERN_CONT
  83. "error reading bts trace at [%lu] (0x%p)...",
  84. index, at);
  85. return error;
  86. }
  87. switch (bts.qualifier) {
  88. case BTS_BRANCH:
  89. break;
  90. default:
  91. printk(KERN_CONT
  92. "unexpected bts entry %llu at [%lu] (0x%p)...",
  93. bts.qualifier, index, at);
  94. return -1;
  95. }
  96. }
  97. return 0;
  98. }
  99. int ds_selftest_bts(void)
  100. {
  101. const struct bts_trace *trace;
  102. struct bts_tracer *tracer;
  103. int error = 0;
  104. void *top;
  105. unsigned char buffer[BUFFER_SIZE];
  106. printk(KERN_INFO "[ds] bts selftest...");
  107. tracer = ds_request_bts_cpu(smp_processor_id(), buffer, BUFFER_SIZE,
  108. NULL, (size_t)-1, BTS_KERNEL);
  109. if (IS_ERR(tracer)) {
  110. error = PTR_ERR(tracer);
  111. tracer = NULL;
  112. printk(KERN_CONT
  113. "initialization failed (err: %d)...", error);
  114. goto out;
  115. }
  116. /* The return should already give us enough trace. */
  117. ds_suspend_bts(tracer);
  118. /* Let's see if we can access the trace. */
  119. trace = ds_read_bts(tracer);
  120. error = ds_selftest_bts_consistency(trace);
  121. if (error < 0)
  122. goto out;
  123. /* If everything went well, we should have a few trace entries. */
  124. if (trace->ds.top == trace->ds.begin) {
  125. /*
  126. * It is possible but highly unlikely that we got a
  127. * buffer overflow and end up at exactly the same
  128. * position we started from.
  129. * Let's issue a warning, but continue.
  130. */
  131. printk(KERN_CONT "no trace/overflow...");
  132. }
  133. /* Let's try to read the trace we collected. */
  134. error = ds_selftest_bts_read(tracer, trace,
  135. trace->ds.begin, trace->ds.top);
  136. if (error < 0)
  137. goto out;
  138. /*
  139. * Let's read the trace again.
  140. * Since we suspended tracing, we should get the same result.
  141. */
  142. top = trace->ds.top;
  143. trace = ds_read_bts(tracer);
  144. error = ds_selftest_bts_consistency(trace);
  145. if (error < 0)
  146. goto out;
  147. if (top != trace->ds.top) {
  148. printk(KERN_CONT "suspend not working...");
  149. error = -1;
  150. goto out;
  151. }
  152. /* Let's collect some more trace - see if resume is working. */
  153. ds_resume_bts(tracer);
  154. ds_suspend_bts(tracer);
  155. trace = ds_read_bts(tracer);
  156. error = ds_selftest_bts_consistency(trace);
  157. if (error < 0)
  158. goto out;
  159. if (trace->ds.top == top) {
  160. /*
  161. * It is possible but highly unlikely that we got a
  162. * buffer overflow and end up at exactly the same
  163. * position we started from.
  164. * Let's issue a warning and check the full trace.
  165. */
  166. printk(KERN_CONT
  167. "no resume progress/overflow...");
  168. error = ds_selftest_bts_read(tracer, trace,
  169. trace->ds.begin, trace->ds.end);
  170. } else if (trace->ds.top < top) {
  171. /*
  172. * We had a buffer overflow - the entire buffer should
  173. * contain trace records.
  174. */
  175. error = ds_selftest_bts_read(tracer, trace,
  176. trace->ds.begin, trace->ds.end);
  177. } else {
  178. /*
  179. * It is quite likely that the buffer did not overflow.
  180. * Let's just check the delta trace.
  181. */
  182. error = ds_selftest_bts_read(tracer, trace,
  183. top, trace->ds.top);
  184. }
  185. if (error < 0)
  186. goto out;
  187. error = 0;
  188. /* The final test: release the tracer while tracing is suspended. */
  189. out:
  190. ds_release_bts(tracer);
  191. printk(KERN_CONT "%s.\n", (error ? "failed" : "passed"));
  192. return error;
  193. }
  194. int ds_selftest_pebs(void)
  195. {
  196. return 0;
  197. }