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...");
50 if ((trace
->ds
.top
< trace
->ds
.begin
) ||
51 (trace
->ds
.end
<= trace
->ds
.top
)) {
52 printk(KERN_CONT
"bts top out of bounds...");
59 static int ds_selftest_bts_read(struct bts_tracer
*tracer
,
60 const struct bts_trace
*trace
,
61 const void *from
, const void *to
)
63 const unsigned char *at
;
66 * Check a few things which do not belong to this test.
67 * They should be covered by other tests.
78 if (from
< trace
->ds
.begin
)
81 if (trace
->ds
.end
< to
)
87 /* Now to the test itself. */
88 for (at
= from
; (void *)at
< to
; at
+= trace
->ds
.size
) {
89 struct bts_struct bts
;
93 if (((void *)at
- trace
->ds
.begin
) % trace
->ds
.size
) {
95 "read from non-integer index...");
98 index
= ((void *)at
- trace
->ds
.begin
) / trace
->ds
.size
;
100 memset(&bts
, 0, sizeof(bts
));
101 error
= trace
->read(tracer
, at
, &bts
);
104 "error reading bts trace at [%lu] (0x%p)...",
109 switch (bts
.qualifier
) {
114 "unexpected bts entry %llu at [%lu] (0x%p)...",
115 bts
.qualifier
, index
, at
);
123 int ds_selftest_bts(void)
125 const struct bts_trace
*trace
;
126 struct bts_tracer
*tracer
;
129 unsigned char buffer
[BUFFER_SIZE
];
131 printk(KERN_INFO
"[ds] bts selftest...");
133 tracer
= ds_request_bts_cpu(smp_processor_id(), buffer
, BUFFER_SIZE
,
134 NULL
, (size_t)-1, BTS_KERNEL
);
135 if (IS_ERR(tracer
)) {
136 error
= PTR_ERR(tracer
);
140 "initialization failed (err: %d)...", error
);
144 /* The return should already give us enough trace. */
145 ds_suspend_bts(tracer
);
147 /* Let's see if we can access the trace. */
148 trace
= ds_read_bts(tracer
);
150 error
= ds_selftest_bts_consistency(trace
);
154 /* If everything went well, we should have a few trace entries. */
155 if (trace
->ds
.top
== trace
->ds
.begin
) {
157 * It is possible but highly unlikely that we got a
158 * buffer overflow and end up at exactly the same
159 * position we started from.
160 * Let's issue a warning, but continue.
162 printk(KERN_CONT
"no trace/overflow...");
165 /* Let's try to read the trace we collected. */
166 error
= ds_selftest_bts_read(tracer
, trace
,
167 trace
->ds
.begin
, trace
->ds
.top
);
172 * Let's read the trace again.
173 * Since we suspended tracing, we should get the same result.
177 trace
= ds_read_bts(tracer
);
178 error
= ds_selftest_bts_consistency(trace
);
182 if (top
!= trace
->ds
.top
) {
183 printk(KERN_CONT
"suspend not working...");
188 /* Let's collect some more trace - see if resume is working. */
189 ds_resume_bts(tracer
);
190 ds_suspend_bts(tracer
);
192 trace
= ds_read_bts(tracer
);
194 error
= ds_selftest_bts_consistency(trace
);
198 if (trace
->ds
.top
== top
) {
200 * It is possible but highly unlikely that we got a
201 * buffer overflow and end up at exactly the same
202 * position we started from.
203 * Let's issue a warning and check the full trace.
206 "no resume progress/overflow...");
208 error
= ds_selftest_bts_read(tracer
, trace
,
209 trace
->ds
.begin
, trace
->ds
.end
);
210 } else if (trace
->ds
.top
< top
) {
212 * We had a buffer overflow - the entire buffer should
213 * contain trace records.
215 error
= ds_selftest_bts_read(tracer
, trace
,
216 trace
->ds
.begin
, trace
->ds
.end
);
219 * It is quite likely that the buffer did not overflow.
220 * Let's just check the delta trace.
222 error
= ds_selftest_bts_read(tracer
, trace
,
230 /* The final test: release the tracer while tracing is suspended. */
232 ds_release_bts(tracer
);
234 printk(KERN_CONT
"%s.\n", (error
? "failed" : "passed"));
239 int ds_selftest_pebs(void)