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