static void bts_trace_init_cpu(int cpu) { per_cpu(tracer, cpu) = ds_request_bts_cpu(cpu, per_cpu(buffer, cpu), BTS_BUFFER_SIZE, NULL, (size_t)-1, BTS_KERNEL); if (IS_ERR(per_cpu(tracer, cpu))) per_cpu(tracer, cpu) = NULL; }
static int ds_selftest_bts_bad_request_cpu(int cpu, void *buffer) { struct bts_tracer *tracer; int error; /* Try to request cpu tracing while task tracing is active. */ tracer = ds_request_bts_cpu(cpu, buffer, BUFFER_SIZE, NULL, (size_t)-1, BTS_KERNEL); error = PTR_ERR(tracer); if (!IS_ERR(tracer)) { ds_release_bts(tracer); error = 0; } if (error != -EPERM) printk(KERN_CONT "cpu/task tracing overlap..."); return error ? 0 : -1; }
int ds_selftest_bts(void) { struct ds_selftest_bts_conf conf; unsigned char buffer[BUFFER_SIZE], *small_buffer; unsigned long irq; int cpu; printk(KERN_INFO "[ds] bts selftest..."); conf.error = 0; small_buffer = (unsigned char *)ALIGN((unsigned long)buffer, 8) + 8; get_online_cpus(); for_each_online_cpu(cpu) { conf.suspend = ds_suspend_bts_wrap; conf.resume = ds_resume_bts_wrap; conf.tracer = ds_request_bts_cpu(cpu, buffer, BUFFER_SIZE, NULL, (size_t)-1, BTS_KERNEL); ds_selftest_bts_cpu(&conf); if (conf.error >= 0) conf.error = ds_selftest_bts_bad_request_task(buffer); ds_release_bts(conf.tracer); if (conf.error < 0) goto out; conf.suspend = ds_suspend_bts_noirq; conf.resume = ds_resume_bts_noirq; conf.tracer = ds_request_bts_cpu(cpu, buffer, BUFFER_SIZE, NULL, (size_t)-1, BTS_KERNEL); smp_call_function_single(cpu, ds_selftest_bts_cpu, &conf, 1); if (conf.error >= 0) { conf.error = ds_selftest_bts_bad_release_noirq(cpu, conf.tracer); /* We must not release the tracer twice. */ if (conf.error < 0) conf.tracer = NULL; } if (conf.error >= 0) conf.error = ds_selftest_bts_bad_request_task(buffer); smp_call_function_single(cpu, ds_release_bts_noirq_wrap, conf.tracer, 1); if (conf.error < 0) goto out; } conf.suspend = ds_suspend_bts_wrap; conf.resume = ds_resume_bts_wrap; conf.tracer = ds_request_bts_task(current, buffer, BUFFER_SIZE, NULL, (size_t)-1, BTS_KERNEL); ds_selftest_bts_cpu(&conf); if (conf.error >= 0) conf.error = ds_selftest_bts_bad_request_cpu(0, buffer); ds_release_bts(conf.tracer); if (conf.error < 0) goto out; conf.suspend = ds_suspend_bts_noirq; conf.resume = ds_resume_bts_noirq; conf.tracer = ds_request_bts_task(current, small_buffer, SMALL_BUFFER_SIZE, NULL, (size_t)-1, BTS_KERNEL); local_irq_save(irq); ds_selftest_bts_cpu(&conf); if (conf.error >= 0) conf.error = ds_selftest_bts_bad_request_cpu(0, buffer); ds_release_bts_noirq(conf.tracer); local_irq_restore(irq); if (conf.error < 0) goto out; conf.error = 0; out: put_online_cpus(); printk(KERN_CONT "%s.\n", (conf.error ? "failed" : "passed")); return conf.error; }