x86, ds: fix compiler warning
[linux-2.6/kvm.git] / arch / x86 / kernel / ds_selftest.c
blobe1ba5101b57653b8fdab4265eb94b848142a3c17
1 /*
2 * Debug Store support - selftest
5 * Copyright (C) 2009 Intel Corporation.
6 * Markus Metzger <markus.t.metzger@intel.com>, 2009
7 */
9 #include "ds_selftest.h"
11 #include <linux/kernel.h>
12 #include <linux/string.h>
13 #include <linux/smp.h>
15 #include <asm/ds.h>
18 #define BUFFER_SIZE 1021 /* Intentionally chose an odd size. */
21 static int ds_selftest_bts_consistency(const struct bts_trace *trace)
23 int error = 0;
25 if (!trace) {
26 printk(KERN_CONT "failed to access trace...");
27 /* Bail out. Other tests are pointless. */
28 return -1;
31 if (!trace->read) {
32 printk(KERN_CONT "bts read not available...");
33 error = -1;
36 /* Do some sanity checks on the trace configuration. */
37 if (!trace->ds.n) {
38 printk(KERN_CONT "empty bts buffer...");
39 error = -1;
41 if (!trace->ds.size) {
42 printk(KERN_CONT "bad bts trace setup...");
43 error = -1;
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;
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;
56 return error;
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.
69 if (!trace)
70 return -1;
72 if (!trace->read)
73 return -1;
75 if (to < from)
76 return -1;
78 if (from < trace->ds.begin)
79 return -1;
81 if (trace->ds.end < to)
82 return -1;
84 if (!trace->ds.size)
85 return -1;
87 /* Now to the test itself. */
88 for (at = from; (void *)at < to; at += trace->ds.size) {
89 struct bts_struct bts;
90 unsigned long index;
91 int error;
93 if (((void *)at - trace->ds.begin) % trace->ds.size) {
94 printk(KERN_CONT
95 "read from non-integer index...");
96 return -1;
98 index = ((void *)at - trace->ds.begin) / trace->ds.size;
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;
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;
120 return 0;
123 int ds_selftest_bts(void)
125 const struct bts_trace *trace;
126 struct bts_tracer *tracer;
127 int error = 0;
128 void *top;
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);
137 tracer = NULL;
139 printk(KERN_CONT
140 "initialization failed (err: %d)...", error);
141 goto out;
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);
151 if (error < 0)
152 goto out;
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);
168 if (error < 0)
169 goto out;
172 * Let's read the trace again.
173 * Since we suspended tracing, we should get the same result.
175 top = trace->ds.top;
177 trace = ds_read_bts(tracer);
178 error = ds_selftest_bts_consistency(trace);
179 if (error < 0)
180 goto out;
182 if (top != trace->ds.top) {
183 printk(KERN_CONT "suspend not working...");
184 error = -1;
185 goto out;
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);
195 if (error < 0)
196 goto out;
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.
205 printk(KERN_CONT
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);
217 } else {
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,
223 top, trace->ds.top);
225 if (error < 0)
226 goto out;
228 error = 0;
230 /* The final test: release the tracer while tracing is suspended. */
231 out:
232 ds_release_bts(tracer);
234 printk(KERN_CONT "%s.\n", (error ? "failed" : "passed"));
236 return error;
239 int ds_selftest_pebs(void)
241 return 0;