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>
13 #include <linux/smp.h>
18 #define BUFFER_SIZE 1021 /* Intentionally chose an odd size. */
21 static int ds_selftest_bts_consistency(const struct bts_trace *trace)
26 printk(KERN_CONT "failed to access trace...");
27 /* Bail out. Other tests are pointless. */
32 printk(KERN_CONT "bts read not available...");
36 /* Do some sanity checks on the trace configuration. */
38 printk(KERN_CONT "empty bts buffer...");
41 if (!trace->ds.size) {
42 printk(KERN_CONT "bad bts trace setup...");
46 (char *)trace->ds.begin + (trace->ds.n * trace->ds.size)) {
47 printk(KERN_CONT "bad bts buffer setup...");
51 * We allow top in [begin; end], since its not clear when the
52 * overflow adjustment happens: after the increment or before the
55 if ((trace->ds.top < trace->ds.begin) ||
56 (trace->ds.end < trace->ds.top)) {
57 printk(KERN_CONT "bts top out of bounds...");
64 static int ds_selftest_bts_read(struct bts_tracer *tracer,
65 const struct bts_trace *trace,
66 const void *from, const void *to)
68 const unsigned char *at;
71 * Check a few things which do not belong to this test.
72 * They should be covered by other tests.
83 if (from < trace->ds.begin)
86 if (trace->ds.end < to)
92 /* Now to the test itself. */
93 for (at = from; (void *)at < to; at += trace->ds.size) {
94 struct bts_struct bts;
98 if (((void *)at - trace->ds.begin) % trace->ds.size) {
100 "read from non-integer index...");
103 index = ((void *)at - trace->ds.begin) / trace->ds.size;
105 memset(&bts, 0, sizeof(bts));
106 error = trace->read(tracer, at, &bts);
109 "error reading bts trace at [%lu] (0x%p)...",
114 switch (bts.qualifier) {
119 "unexpected bts entry %llu at [%lu] (0x%p)...",
120 bts.qualifier, index, at);
128 int ds_selftest_bts(void)
130 const struct bts_trace *trace;
131 struct bts_tracer *tracer;
134 unsigned char buffer[BUFFER_SIZE];
136 printk(KERN_INFO "[ds] bts selftest...");
138 tracer = ds_request_bts_cpu(smp_processor_id(), buffer, BUFFER_SIZE,
139 NULL, (size_t)-1, BTS_KERNEL);
140 if (IS_ERR(tracer)) {
141 error = PTR_ERR(tracer);
145 "initialization failed (err: %d)...", error);
149 /* The return should already give us enough trace. */
150 ds_suspend_bts(tracer);
152 /* Let's see if we can access the trace. */
153 trace = ds_read_bts(tracer);
155 error = ds_selftest_bts_consistency(trace);
159 /* If everything went well, we should have a few trace entries. */
160 if (trace->ds.top == trace->ds.begin) {
162 * It is possible but highly unlikely that we got a
163 * buffer overflow and end up at exactly the same
164 * position we started from.
165 * Let's issue a warning, but continue.
167 printk(KERN_CONT "no trace/overflow...");
170 /* Let's try to read the trace we collected. */
171 error = ds_selftest_bts_read(tracer, trace,
172 trace->ds.begin, trace->ds.top);
177 * Let's read the trace again.
178 * Since we suspended tracing, we should get the same result.
182 trace = ds_read_bts(tracer);
183 error = ds_selftest_bts_consistency(trace);
187 if (top != trace->ds.top) {
188 printk(KERN_CONT "suspend not working...");
193 /* Let's collect some more trace - see if resume is working. */
194 ds_resume_bts(tracer);
195 ds_suspend_bts(tracer);
197 trace = ds_read_bts(tracer);
199 error = ds_selftest_bts_consistency(trace);
203 if (trace->ds.top == top) {
205 * It is possible but highly unlikely that we got a
206 * buffer overflow and end up at exactly the same
207 * position we started from.
208 * Let's issue a warning and check the full trace.
211 "no resume progress/overflow...");
213 error = ds_selftest_bts_read(tracer, trace,
214 trace->ds.begin, trace->ds.end);
215 } else if (trace->ds.top < top) {
217 * We had a buffer overflow - the entire buffer should
218 * contain trace records.
220 error = ds_selftest_bts_read(tracer, trace,
221 trace->ds.begin, trace->ds.end);
224 * It is quite likely that the buffer did not overflow.
225 * Let's just check the delta trace.
227 error = ds_selftest_bts_read(tracer, trace,
235 /* The final test: release the tracer while tracing is suspended. */
237 ds_release_bts(tracer);
239 printk(KERN_CONT "%s.\n", (error ? "failed" : "passed"));
244 int ds_selftest_pebs(void)