/*
 * Stop tracing on the current cpu.
 * The argument is ignored.
 *
 * pre: bts_tracer_lock must be locked.
 */
static void bts_trace_stop_cpu(void *arg)
{
	if (this_tracer) {
		ds_release_bts(this_tracer);
		this_tracer = NULL;
	}
}
Example #2
0
static int __cpuinit bts_hotcpu_handler(struct notifier_block *nfb,
				     unsigned long action, void *hcpu)
{
	int cpu = (long)hcpu;

	switch (action) {
	case CPU_ONLINE:
	case CPU_DOWN_FAILED:
		/* The notification is sent with interrupts enabled. */
		if (trace_hw_branches_enabled) {
			bts_trace_init_cpu(cpu);

			if (trace_hw_branches_suspended &&
			    likely(per_cpu(hwb_tracer, cpu)))
                ds_suspend_bts(per_cpu(hwb_tracer, cpu));
		}
		break;

	case CPU_DOWN_PREPARE:
		/* The notification is sent with interrupts enabled. */
            if (likely(per_cpu(hwb_tracer, cpu))) {
                ds_release_bts(per_cpu(hwb_tracer, cpu));
                per_cpu(hwb_tracer, cpu) = NULL;
		}
	}

	return NOTIFY_DONE;
}
/*
 * Start tracing on the current cpu.
 * The argument is ignored.
 *
 * pre: bts_tracer_lock must be locked.
 */
static void bts_trace_start_cpu(void *arg)
{
	if (this_tracer)
		ds_release_bts(this_tracer);

	this_tracer =
		ds_request_bts(/* task = */ NULL, this_buffer, SIZEOF_BTS,
			       /* ovfl = */ NULL, /* th = */ (size_t)-1,
			       BTS_KERNEL);
	if (IS_ERR(this_tracer)) {
		this_tracer = NULL;
		return;
	}
}
Example #4
0
static void bts_trace_reset(struct trace_array *tr)
{
	int cpu;

	get_online_cpus();
	for_each_online_cpu(cpu) {
		if (likely(per_cpu(hwb_tracer, cpu))) {
            ds_release_bts(per_cpu(hwb_tracer, cpu));
            per_cpu(hwb_tracer, cpu) = NULL;
		}
	}
	trace_hw_branches_enabled = 0;
	trace_hw_branches_suspended = 0;
	put_online_cpus();
}
Example #5
0
static int ds_selftest_bts_bad_request_task(void *buffer)
{
	struct bts_tracer *tracer;
	int error;

	/* Try to request cpu tracing while task tracing is active. */
	tracer = ds_request_bts_task(current, buffer, BUFFER_SIZE, NULL,
				    (size_t)-1, BTS_KERNEL);
	error = PTR_ERR(tracer);
	if (!IS_ERR(tracer)) {
		error = 0;
		ds_release_bts(tracer);
	}

	if (error != -EPERM)
		printk(KERN_CONT "task/cpu tracing overlap...");

	return error ? 0 : -1;
}
Example #6
0
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;
}