// SPDX-License-Identifier: GPL-2.0
/*
 * Preempt / IRQ disable delay thread to test latency tracers
 *
 * Copyright (C) 2018 Joel Fernandes (Google) <joel@joelfernandes.org>
 */

#include <linux/trace_clock.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/completion.h>

static ulong delay = 100;
static char test_mode[12] = "irq";
static uint burst_size = 1;
static int  cpu_affinity = -1;

module_param_named(delay, delay, ulong, 0444);
module_param_string(test_mode, test_mode, 12, 0444);
module_param_named(burst_size, burst_size, uint, 0444);
module_param_named(cpu_affinity, cpu_affinity, int, 0444);
MODULE_PARM_DESC(delay, "Period in microseconds (100 us default)");
MODULE_PARM_DESC(test_mode, "Mode of the test such as preempt, irq, or alternate (default irq)");
MODULE_PARM_DESC(burst_size, "The size of a burst (default 1)");
MODULE_PARM_DESC(cpu_affinity, "Cpu num test is running on");

static struct completion done;

static void busy_wait(ulong time)
{
	u64 start, end;

	start = trace_clock_local();

	do {
		end = trace_clock_local();
		if (kthread_should_stop())
			break;
	} while ((end - start) < (time * 1000));
}

static __always_inline void irqoff_test(void)
{
	unsigned long flags;

	local_irq_save(flags);
	busy_wait(delay);
	local_irq_restore(flags);
}

static __always_inline void preemptoff_test(void)
{
	preempt_disable();
	busy_wait(delay);
	preempt_enable();
}

static void execute_preemptirqtest(int idx)
{
	if (!strcmp(test_mode, "irq"))
		irqoff_test();
	else if (!strcmp(test_mode, "preempt"))
		preemptoff_test();
	else if (!strcmp(test_mode, "alternate")) {
		if (idx % 2 == 0)
			irqoff_test();
		else
			preemptoff_test();
	}
}

#define DECLARE_TESTFN(POSTFIX)				\
	static void preemptirqtest_##POSTFIX(int idx)	\
	{						\
		execute_preemptirqtest(idx);		\
	}						\

/*
 * We create 10 different functions, so that we can get 10 different
 * backtraces.
 */
DECLARE_TESTFN(0)
DECLARE_TESTFN(1)
DECLARE_TESTFN(2)
DECLARE_TESTFN(3)
DECLARE_TESTFN(4)
DECLARE_TESTFN(5)
DECLARE_TESTFN(6)
DECLARE_TESTFN(7)
DECLARE_TESTFN(8)
DECLARE_TESTFN(9)

static void (*testfuncs[])(int)  = {
	preemptirqtest_0,
	preemptirqtest_1,
	preemptirqtest_2,
	preemptirqtest_3,
	preemptirqtest_4,
	preemptirqtest_5,
	preemptirqtest_6,
	preemptirqtest_7,
	preemptirqtest_8,
	preemptirqtest_9,
};

#define NR_TEST_FUNCS ARRAY_SIZE(testfuncs)

static int preemptirq_delay_run(void *data)
{
	int i;
	int s = MIN(burst_size, NR_TEST_FUNCS);
	struct cpumask cpu_mask;

	if (cpu_affinity > -1) {
		cpumask_clear(&cpu_mask);
		cpumask_set_cpu(cpu_affinity, &cpu_mask);
		if (set_cpus_allowed_ptr(current, &cpu_mask))
			pr_err("cpu_affinity:%d, failed\n", cpu_affinity);
	}

	for (i = 0; i < s; i++)
		(testfuncs[i])(i);

	complete(&done);

	set_current_state(TASK_INTERRUPTIBLE);
	while (!kthread_should_stop()) {
		schedule();
		set_current_state(TASK_INTERRUPTIBLE);
	}

	__set_current_state(TASK_RUNNING);

	return 0;
}

static int preemptirq_run_test(void)
{
	struct task_struct *task;
	char task_name[50];

	init_completion(&done);

	snprintf(task_name, sizeof(task_name), "%s_test", test_mode);
	task =  kthread_run(preemptirq_delay_run, NULL, task_name);
	if (IS_ERR(task))
		return PTR_ERR(task);
	if (task) {
		wait_for_completion(&done);
		kthread_stop(task);
	}
	return 0;
}


static ssize_t trigger_store(struct kobject *kobj, struct kobj_attribute *attr,
			 const char *buf, size_t count)
{
	ssize_t ret;

	ret = preemptirq_run_test();
	if (ret)
		return ret;
	return count;
}

static struct kobj_attribute trigger_attribute =
	__ATTR(trigger, 0200, NULL, trigger_store);

static struct attribute *attrs[] = {
	&trigger_attribute.attr,
	NULL,
};

static struct attribute_group attr_group = {
	.attrs = attrs,
};

static struct kobject *preemptirq_delay_kobj;

static int __init preemptirq_delay_init(void)
{
	int retval;

	retval = preemptirq_run_test();
	if (retval != 0)
		return retval;

	preemptirq_delay_kobj = kobject_create_and_add("preemptirq_delay_test",
						       kernel_kobj);
	if (!preemptirq_delay_kobj)
		return -ENOMEM;

	retval = sysfs_create_group(preemptirq_delay_kobj, &attr_group);
	if (retval)
		kobject_put(preemptirq_delay_kobj);

	return retval;
}

static void __exit preemptirq_delay_exit(void)
{
	kobject_put(preemptirq_delay_kobj);
}

module_init(preemptirq_delay_init)
module_exit(preemptirq_delay_exit)
MODULE_DESCRIPTION("Preempt / IRQ disable delay thread to test latency tracers");
MODULE_LICENSE("GPL v2");
