2 * Debug Store support - selftest
5 * Copyright (C) 2009 Intel Corporation.
6 * Markus Metzger <markus.t.metzger@intel.com>, 2009
9 #include "ds_selftest.h"
11 #include <linux/kernel.h>
12 #include <linux/string.h>
17 #define DS_SELFTEST_BUFFER_SIZE 1021 /* Intentionally chose an odd size. */
20 static int ds_selftest_bts_consistency(const struct bts_trace *trace)
25 printk(KERN_CONT "failed to access trace...");
26 /* Bail out. Other tests are pointless. */
31 printk(KERN_CONT "bts read not available...");
35 /* Do some sanity checks on the trace configuration. */
37 printk(KERN_CONT "empty bts buffer...");
40 if (!trace->ds.size) {
41 printk(KERN_CONT "bad bts trace setup...");
45 (char *)trace->ds.begin + (trace->ds.n * trace->ds.size)) {
46 printk(KERN_CONT "bad bts buffer setup...");
49 if ((trace->ds.top < trace->ds.begin) ||
50 (trace->ds.end <= trace->ds.top)) {
51 printk(KERN_CONT "bts top out of bounds...");
58 static int ds_selftest_bts_read(struct bts_tracer *tracer,
59 const struct bts_trace *trace,
60 const void *from, const void *to)
62 const unsigned char *at;
65 * Check a few things which do not belong to this test.
66 * They should be covered by other tests.
77 if (from < trace->ds.begin)
80 if (trace->ds.end < to)
86 /* Now to the test itself. */
87 for (at = from; (void *)at < to; at += trace->ds.size) {
88 struct bts_struct bts;
92 if (((void *)at - trace->ds.begin) % trace->ds.size) {
94 "read from non-integer index...");
97 index = ((void *)at - trace->ds.begin) / trace->ds.size;
99 memset(&bts, 0, sizeof(bts));
100 error = trace->read(tracer, at, &bts);
103 "error reading bts trace at [%lu] (0x%p)...",
108 switch (bts.qualifier) {
113 "unexpected bts entry %llu at [%lu] (0x%p)...",
114 bts.qualifier, index, at);
122 int ds_selftest_bts(void)
124 const struct bts_trace *trace;
125 struct bts_tracer *tracer;
128 unsigned char buffer[DS_SELFTEST_BUFFER_SIZE];
130 printk(KERN_INFO "[ds] bts selftest...");
132 tracer = ds_request_bts(NULL, buffer, DS_SELFTEST_BUFFER_SIZE,
133 NULL, (size_t)-1, BTS_KERNEL);
134 if (IS_ERR(tracer)) {
135 error = PTR_ERR(tracer);
139 "initialization failed (err: %d)...", error);
143 /* The return should already give us enough trace. */
144 ds_suspend_bts(tracer);
146 /* Let's see if we can access the trace. */
147 trace = ds_read_bts(tracer);
149 error = ds_selftest_bts_consistency(trace);
153 /* If everything went well, we should have a few trace entries. */
154 if (trace->ds.top == trace->ds.begin) {
156 * It is possible but highly unlikely that we got a
157 * buffer overflow and end up at exactly the same
158 * position we started from.
159 * Let's issue a warning, but continue.
161 printk(KERN_CONT "no trace/overflow...");
164 /* Let's try to read the trace we collected. */
165 error = ds_selftest_bts_read(tracer, trace,
166 trace->ds.begin, trace->ds.top);
171 * Let's read the trace again.
172 * Since we suspended tracing, we should get the same result.
176 trace = ds_read_bts(tracer);
177 error = ds_selftest_bts_consistency(trace);
181 if (top != trace->ds.top) {
182 printk(KERN_CONT "suspend not working...");
187 /* Let's collect some more trace - see if resume is working. */
188 ds_resume_bts(tracer);
189 ds_suspend_bts(tracer);
191 trace = ds_read_bts(tracer);
193 error = ds_selftest_bts_consistency(trace);
197 if (trace->ds.top == top) {
199 * It is possible but highly unlikely that we got a
200 * buffer overflow and end up at exactly the same
201 * position we started from.
202 * Let's issue a warning and check the full trace.
205 "no resume progress/overflow...");
207 error = ds_selftest_bts_read(tracer, trace,
208 trace->ds.begin, trace->ds.end);
209 } else if (trace->ds.top < top) {
211 * We had a buffer overflow - the entire buffer should
212 * contain trace records.
214 error = ds_selftest_bts_read(tracer, trace,
215 trace->ds.begin, trace->ds.end);
218 * It is quite likely that the buffer did not overflow.
219 * Let's just check the delta trace.
221 error = ds_selftest_bts_read(tracer, trace,
229 /* The final test: release the tracer while tracing is suspended. */
231 ds_release_bts(tracer);
233 printk(KERN_CONT "%s.\n", (error ? "failed" : "passed"));
238 int ds_selftest_pebs(void)