| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 1 | /* | 
|  | 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 Metzger | de79f54 | 2009-04-03 16:43:40 +0200 | [diff] [blame] | 13 | #include <linux/smp.h> | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 14 | #include <linux/cpu.h> | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 15 |  | 
|  | 16 | #include <asm/ds.h> | 
|  | 17 |  | 
|  | 18 |  | 
| Markus Metzger | 150f516 | 2009-04-03 16:43:51 +0200 | [diff] [blame] | 19 | #define BUFFER_SIZE		521	/* Intentionally chose an odd size. */ | 
|  | 20 | #define SMALL_BUFFER_SIZE	24	/* A single bts entry. */ | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 21 |  | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 22 | struct ds_selftest_bts_conf { | 
|  | 23 | struct bts_tracer *tracer; | 
|  | 24 | int error; | 
|  | 25 | int (*suspend)(struct bts_tracer *); | 
|  | 26 | int (*resume)(struct bts_tracer *); | 
|  | 27 | }; | 
|  | 28 |  | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 29 | static int ds_selftest_bts_consistency(const struct bts_trace *trace) | 
|  | 30 | { | 
|  | 31 | int error = 0; | 
|  | 32 |  | 
|  | 33 | if (!trace) { | 
|  | 34 | printk(KERN_CONT "failed to access trace..."); | 
|  | 35 | /* Bail out. Other tests are pointless. */ | 
|  | 36 | return -1; | 
|  | 37 | } | 
|  | 38 |  | 
|  | 39 | if (!trace->read) { | 
|  | 40 | printk(KERN_CONT "bts read not available..."); | 
|  | 41 | error = -1; | 
|  | 42 | } | 
|  | 43 |  | 
|  | 44 | /* Do some sanity checks on the trace configuration. */ | 
|  | 45 | if (!trace->ds.n) { | 
|  | 46 | printk(KERN_CONT "empty bts buffer..."); | 
|  | 47 | error = -1; | 
|  | 48 | } | 
|  | 49 | if (!trace->ds.size) { | 
|  | 50 | printk(KERN_CONT "bad bts trace setup..."); | 
|  | 51 | error = -1; | 
|  | 52 | } | 
|  | 53 | if (trace->ds.end != | 
|  | 54 | (char *)trace->ds.begin + (trace->ds.n * trace->ds.size)) { | 
|  | 55 | printk(KERN_CONT "bad bts buffer setup..."); | 
|  | 56 | error = -1; | 
|  | 57 | } | 
| Markus Metzger | 84f2011 | 2009-04-03 16:43:43 +0200 | [diff] [blame] | 58 | /* | 
|  | 59 | * We allow top in [begin; end], since its not clear when the | 
|  | 60 | * overflow adjustment happens: after the increment or before the | 
|  | 61 | * write. | 
|  | 62 | */ | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 63 | if ((trace->ds.top < trace->ds.begin) || | 
| Markus Metzger | 84f2011 | 2009-04-03 16:43:43 +0200 | [diff] [blame] | 64 | (trace->ds.end < trace->ds.top)) { | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 65 | printk(KERN_CONT "bts top out of bounds..."); | 
|  | 66 | error = -1; | 
|  | 67 | } | 
|  | 68 |  | 
|  | 69 | return error; | 
|  | 70 | } | 
|  | 71 |  | 
|  | 72 | static int ds_selftest_bts_read(struct bts_tracer *tracer, | 
|  | 73 | const struct bts_trace *trace, | 
|  | 74 | const void *from, const void *to) | 
|  | 75 | { | 
|  | 76 | const unsigned char *at; | 
|  | 77 |  | 
|  | 78 | /* | 
|  | 79 | * Check a few things which do not belong to this test. | 
|  | 80 | * They should be covered by other tests. | 
|  | 81 | */ | 
|  | 82 | if (!trace) | 
|  | 83 | return -1; | 
|  | 84 |  | 
|  | 85 | if (!trace->read) | 
|  | 86 | return -1; | 
|  | 87 |  | 
|  | 88 | if (to < from) | 
|  | 89 | return -1; | 
|  | 90 |  | 
|  | 91 | if (from < trace->ds.begin) | 
|  | 92 | return -1; | 
|  | 93 |  | 
|  | 94 | if (trace->ds.end < to) | 
|  | 95 | return -1; | 
|  | 96 |  | 
|  | 97 | if (!trace->ds.size) | 
|  | 98 | return -1; | 
|  | 99 |  | 
|  | 100 | /* Now to the test itself. */ | 
|  | 101 | for (at = from; (void *)at < to; at += trace->ds.size) { | 
|  | 102 | struct bts_struct bts; | 
| Markus Metzger | 353afee | 2009-04-03 16:43:42 +0200 | [diff] [blame] | 103 | unsigned long index; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 104 | int error; | 
|  | 105 |  | 
|  | 106 | if (((void *)at - trace->ds.begin) % trace->ds.size) { | 
|  | 107 | printk(KERN_CONT | 
|  | 108 | "read from non-integer index..."); | 
|  | 109 | return -1; | 
|  | 110 | } | 
|  | 111 | index = ((void *)at - trace->ds.begin) / trace->ds.size; | 
|  | 112 |  | 
|  | 113 | memset(&bts, 0, sizeof(bts)); | 
|  | 114 | error = trace->read(tracer, at, &bts); | 
|  | 115 | if (error < 0) { | 
|  | 116 | printk(KERN_CONT | 
|  | 117 | "error reading bts trace at [%lu] (0x%p)...", | 
|  | 118 | index, at); | 
|  | 119 | return error; | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 | switch (bts.qualifier) { | 
|  | 123 | case BTS_BRANCH: | 
|  | 124 | break; | 
|  | 125 | default: | 
|  | 126 | printk(KERN_CONT | 
|  | 127 | "unexpected bts entry %llu at [%lu] (0x%p)...", | 
|  | 128 | bts.qualifier, index, at); | 
|  | 129 | return -1; | 
|  | 130 | } | 
|  | 131 | } | 
|  | 132 |  | 
|  | 133 | return 0; | 
|  | 134 | } | 
|  | 135 |  | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 136 | static void ds_selftest_bts_cpu(void *arg) | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 137 | { | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 138 | struct ds_selftest_bts_conf *conf = arg; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 139 | const struct bts_trace *trace; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 140 | void *top; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 141 |  | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 142 | if (IS_ERR(conf->tracer)) { | 
|  | 143 | conf->error = PTR_ERR(conf->tracer); | 
|  | 144 | conf->tracer = NULL; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 145 |  | 
|  | 146 | printk(KERN_CONT | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 147 | "initialization failed (err: %d)...", conf->error); | 
|  | 148 | return; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 149 | } | 
|  | 150 |  | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 151 | /* We should meanwhile have enough trace. */ | 
|  | 152 | conf->error = conf->suspend(conf->tracer); | 
|  | 153 | if (conf->error < 0) | 
|  | 154 | return; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 155 |  | 
|  | 156 | /* Let's see if we can access the trace. */ | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 157 | trace = ds_read_bts(conf->tracer); | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 158 |  | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 159 | conf->error = ds_selftest_bts_consistency(trace); | 
|  | 160 | if (conf->error < 0) | 
|  | 161 | return; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 162 |  | 
|  | 163 | /* If everything went well, we should have a few trace entries. */ | 
|  | 164 | if (trace->ds.top == trace->ds.begin) { | 
|  | 165 | /* | 
|  | 166 | * It is possible but highly unlikely that we got a | 
|  | 167 | * buffer overflow and end up at exactly the same | 
|  | 168 | * position we started from. | 
|  | 169 | * Let's issue a warning, but continue. | 
|  | 170 | */ | 
|  | 171 | printk(KERN_CONT "no trace/overflow..."); | 
|  | 172 | } | 
|  | 173 |  | 
|  | 174 | /* Let's try to read the trace we collected. */ | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 175 | conf->error = | 
|  | 176 | ds_selftest_bts_read(conf->tracer, trace, | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 177 | trace->ds.begin, trace->ds.top); | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 178 | if (conf->error < 0) | 
|  | 179 | return; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 180 |  | 
|  | 181 | /* | 
|  | 182 | * Let's read the trace again. | 
|  | 183 | * Since we suspended tracing, we should get the same result. | 
|  | 184 | */ | 
|  | 185 | top = trace->ds.top; | 
|  | 186 |  | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 187 | trace = ds_read_bts(conf->tracer); | 
|  | 188 | conf->error = ds_selftest_bts_consistency(trace); | 
|  | 189 | if (conf->error < 0) | 
|  | 190 | return; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 191 |  | 
|  | 192 | if (top != trace->ds.top) { | 
|  | 193 | printk(KERN_CONT "suspend not working..."); | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 194 | conf->error = -1; | 
|  | 195 | return; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 196 | } | 
|  | 197 |  | 
|  | 198 | /* Let's collect some more trace - see if resume is working. */ | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 199 | conf->error = conf->resume(conf->tracer); | 
|  | 200 | if (conf->error < 0) | 
|  | 201 | return; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 202 |  | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 203 | conf->error = conf->suspend(conf->tracer); | 
|  | 204 | if (conf->error < 0) | 
|  | 205 | return; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 206 |  | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 207 | trace = ds_read_bts(conf->tracer); | 
|  | 208 |  | 
|  | 209 | conf->error = ds_selftest_bts_consistency(trace); | 
|  | 210 | if (conf->error < 0) | 
|  | 211 | return; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 212 |  | 
|  | 213 | if (trace->ds.top == top) { | 
|  | 214 | /* | 
|  | 215 | * It is possible but highly unlikely that we got a | 
|  | 216 | * buffer overflow and end up at exactly the same | 
|  | 217 | * position we started from. | 
|  | 218 | * Let's issue a warning and check the full trace. | 
|  | 219 | */ | 
|  | 220 | printk(KERN_CONT | 
|  | 221 | "no resume progress/overflow..."); | 
|  | 222 |  | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 223 | conf->error = | 
|  | 224 | ds_selftest_bts_read(conf->tracer, trace, | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 225 | trace->ds.begin, trace->ds.end); | 
|  | 226 | } else if (trace->ds.top < top) { | 
|  | 227 | /* | 
|  | 228 | * We had a buffer overflow - the entire buffer should | 
|  | 229 | * contain trace records. | 
|  | 230 | */ | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 231 | conf->error = | 
|  | 232 | ds_selftest_bts_read(conf->tracer, trace, | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 233 | trace->ds.begin, trace->ds.end); | 
|  | 234 | } else { | 
|  | 235 | /* | 
|  | 236 | * It is quite likely that the buffer did not overflow. | 
|  | 237 | * Let's just check the delta trace. | 
|  | 238 | */ | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 239 | conf->error = | 
|  | 240 | ds_selftest_bts_read(conf->tracer, trace, top, | 
|  | 241 | trace->ds.top); | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 242 | } | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 243 | if (conf->error < 0) | 
|  | 244 | return; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 245 |  | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 246 | conf->error = 0; | 
|  | 247 | } | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 248 |  | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 249 | static int ds_suspend_bts_wrap(struct bts_tracer *tracer) | 
|  | 250 | { | 
|  | 251 | ds_suspend_bts(tracer); | 
|  | 252 | return 0; | 
|  | 253 | } | 
|  | 254 |  | 
|  | 255 | static int ds_resume_bts_wrap(struct bts_tracer *tracer) | 
|  | 256 | { | 
|  | 257 | ds_resume_bts(tracer); | 
|  | 258 | return 0; | 
|  | 259 | } | 
|  | 260 |  | 
|  | 261 | static void ds_release_bts_noirq_wrap(void *tracer) | 
|  | 262 | { | 
|  | 263 | (void)ds_release_bts_noirq(tracer); | 
|  | 264 | } | 
|  | 265 |  | 
|  | 266 | static int ds_selftest_bts_bad_release_noirq(int cpu, | 
|  | 267 | struct bts_tracer *tracer) | 
|  | 268 | { | 
|  | 269 | int error = -EPERM; | 
|  | 270 |  | 
|  | 271 | /* Try to release the tracer on the wrong cpu. */ | 
|  | 272 | get_cpu(); | 
|  | 273 | if (cpu != smp_processor_id()) { | 
|  | 274 | error = ds_release_bts_noirq(tracer); | 
|  | 275 | if (error != -EPERM) | 
|  | 276 | printk(KERN_CONT "release on wrong cpu..."); | 
|  | 277 | } | 
|  | 278 | put_cpu(); | 
|  | 279 |  | 
|  | 280 | return error ? 0 : -1; | 
|  | 281 | } | 
|  | 282 |  | 
| Markus Metzger | 3a68eef | 2009-04-03 16:43:45 +0200 | [diff] [blame] | 283 | static int ds_selftest_bts_bad_request_cpu(int cpu, void *buffer) | 
|  | 284 | { | 
|  | 285 | struct bts_tracer *tracer; | 
|  | 286 | int error; | 
|  | 287 |  | 
|  | 288 | /* Try to request cpu tracing while task tracing is active. */ | 
|  | 289 | tracer = ds_request_bts_cpu(cpu, buffer, BUFFER_SIZE, NULL, | 
|  | 290 | (size_t)-1, BTS_KERNEL); | 
|  | 291 | error = PTR_ERR(tracer); | 
|  | 292 | if (!IS_ERR(tracer)) { | 
|  | 293 | ds_release_bts(tracer); | 
|  | 294 | error = 0; | 
|  | 295 | } | 
|  | 296 |  | 
|  | 297 | if (error != -EPERM) | 
|  | 298 | printk(KERN_CONT "cpu/task tracing overlap..."); | 
|  | 299 |  | 
|  | 300 | return error ? 0 : -1; | 
|  | 301 | } | 
|  | 302 |  | 
|  | 303 | static int ds_selftest_bts_bad_request_task(void *buffer) | 
|  | 304 | { | 
|  | 305 | struct bts_tracer *tracer; | 
|  | 306 | int error; | 
|  | 307 |  | 
|  | 308 | /* Try to request cpu tracing while task tracing is active. */ | 
|  | 309 | tracer = ds_request_bts_task(current, buffer, BUFFER_SIZE, NULL, | 
|  | 310 | (size_t)-1, BTS_KERNEL); | 
|  | 311 | error = PTR_ERR(tracer); | 
|  | 312 | if (!IS_ERR(tracer)) { | 
|  | 313 | error = 0; | 
|  | 314 | ds_release_bts(tracer); | 
|  | 315 | } | 
|  | 316 |  | 
|  | 317 | if (error != -EPERM) | 
|  | 318 | printk(KERN_CONT "task/cpu tracing overlap..."); | 
|  | 319 |  | 
|  | 320 | return error ? 0 : -1; | 
|  | 321 | } | 
|  | 322 |  | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 323 | int ds_selftest_bts(void) | 
|  | 324 | { | 
|  | 325 | struct ds_selftest_bts_conf conf; | 
| Markus Metzger | 782cc5a | 2009-04-24 09:43:09 +0200 | [diff] [blame] | 326 | unsigned char buffer[BUFFER_SIZE], *small_buffer; | 
| Markus Metzger | 3a68eef | 2009-04-03 16:43:45 +0200 | [diff] [blame] | 327 | unsigned long irq; | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 328 | int cpu; | 
|  | 329 |  | 
|  | 330 | printk(KERN_INFO "[ds] bts selftest..."); | 
|  | 331 | conf.error = 0; | 
|  | 332 |  | 
| Markus Metzger | 782cc5a | 2009-04-24 09:43:09 +0200 | [diff] [blame] | 333 | small_buffer = (unsigned char *)ALIGN((unsigned long)buffer, 8) + 8; | 
|  | 334 |  | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 335 | get_online_cpus(); | 
|  | 336 | for_each_online_cpu(cpu) { | 
|  | 337 | conf.suspend = ds_suspend_bts_wrap; | 
|  | 338 | conf.resume = ds_resume_bts_wrap; | 
|  | 339 | conf.tracer = | 
|  | 340 | ds_request_bts_cpu(cpu, buffer, BUFFER_SIZE, | 
|  | 341 | NULL, (size_t)-1, BTS_KERNEL); | 
|  | 342 | ds_selftest_bts_cpu(&conf); | 
| Markus Metzger | 3a68eef | 2009-04-03 16:43:45 +0200 | [diff] [blame] | 343 | if (conf.error >= 0) | 
|  | 344 | conf.error = ds_selftest_bts_bad_request_task(buffer); | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 345 | ds_release_bts(conf.tracer); | 
|  | 346 | if (conf.error < 0) | 
|  | 347 | goto out; | 
|  | 348 |  | 
|  | 349 | conf.suspend = ds_suspend_bts_noirq; | 
|  | 350 | conf.resume = ds_resume_bts_noirq; | 
|  | 351 | conf.tracer = | 
|  | 352 | ds_request_bts_cpu(cpu, buffer, BUFFER_SIZE, | 
|  | 353 | NULL, (size_t)-1, BTS_KERNEL); | 
|  | 354 | smp_call_function_single(cpu, ds_selftest_bts_cpu, &conf, 1); | 
|  | 355 | if (conf.error >= 0) { | 
|  | 356 | conf.error = | 
|  | 357 | ds_selftest_bts_bad_release_noirq(cpu, | 
|  | 358 | conf.tracer); | 
|  | 359 | /* We must not release the tracer twice. */ | 
|  | 360 | if (conf.error < 0) | 
|  | 361 | conf.tracer = NULL; | 
|  | 362 | } | 
| Markus Metzger | 3a68eef | 2009-04-03 16:43:45 +0200 | [diff] [blame] | 363 | if (conf.error >= 0) | 
|  | 364 | conf.error = ds_selftest_bts_bad_request_task(buffer); | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 365 | smp_call_function_single(cpu, ds_release_bts_noirq_wrap, | 
|  | 366 | conf.tracer, 1); | 
|  | 367 | if (conf.error < 0) | 
|  | 368 | goto out; | 
|  | 369 | } | 
|  | 370 |  | 
| Markus Metzger | 3a68eef | 2009-04-03 16:43:45 +0200 | [diff] [blame] | 371 | conf.suspend = ds_suspend_bts_wrap; | 
|  | 372 | conf.resume = ds_resume_bts_wrap; | 
|  | 373 | conf.tracer = | 
|  | 374 | ds_request_bts_task(current, buffer, BUFFER_SIZE, | 
|  | 375 | NULL, (size_t)-1, BTS_KERNEL); | 
|  | 376 | ds_selftest_bts_cpu(&conf); | 
|  | 377 | if (conf.error >= 0) | 
|  | 378 | conf.error = ds_selftest_bts_bad_request_cpu(0, buffer); | 
|  | 379 | ds_release_bts(conf.tracer); | 
|  | 380 | if (conf.error < 0) | 
|  | 381 | goto out; | 
|  | 382 |  | 
|  | 383 | conf.suspend = ds_suspend_bts_noirq; | 
|  | 384 | conf.resume = ds_resume_bts_noirq; | 
|  | 385 | conf.tracer = | 
| Markus Metzger | 782cc5a | 2009-04-24 09:43:09 +0200 | [diff] [blame] | 386 | ds_request_bts_task(current, small_buffer, SMALL_BUFFER_SIZE, | 
| Markus Metzger | 3a68eef | 2009-04-03 16:43:45 +0200 | [diff] [blame] | 387 | NULL, (size_t)-1, BTS_KERNEL); | 
|  | 388 | local_irq_save(irq); | 
|  | 389 | ds_selftest_bts_cpu(&conf); | 
|  | 390 | if (conf.error >= 0) | 
|  | 391 | conf.error = ds_selftest_bts_bad_request_cpu(0, buffer); | 
|  | 392 | ds_release_bts_noirq(conf.tracer); | 
|  | 393 | local_irq_restore(irq); | 
|  | 394 | if (conf.error < 0) | 
|  | 395 | goto out; | 
|  | 396 |  | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 397 | conf.error = 0; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 398 | out: | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 399 | put_online_cpus(); | 
|  | 400 | printk(KERN_CONT "%s.\n", (conf.error ? "failed" : "passed")); | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 401 |  | 
| Markus Metzger | 01f6569 | 2009-04-03 16:43:44 +0200 | [diff] [blame] | 402 | return conf.error; | 
| Markus Metzger | 8a327f6 | 2009-03-13 10:45:07 +0100 | [diff] [blame] | 403 | } | 
|  | 404 |  | 
|  | 405 | int ds_selftest_pebs(void) | 
|  | 406 | { | 
|  | 407 | return 0; | 
|  | 408 | } |