Commit 76d12132 authored by Joel Fernandes's avatar Joel Fernandes Committed by Peter Zijlstra
Browse files

sched/debug: Add support to change sched_ext server params



When a sched_ext server is loaded, tasks in the fair class are
automatically moved to the sched_ext class. Add support to modify the
ext server parameters similar to how the fair server parameters are
modified.

Re-use common code between ext and fair servers as needed.

Co-developed-by: default avatarAndrea Righi <arighi@nvidia.com>
Signed-off-by: default avatarAndrea Righi <arighi@nvidia.com>
Signed-off-by: default avatarJoel Fernandes <joelagnelf@nvidia.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: default avatarJuri Lelli <juri.lelli@redhat.com>
Tested-by: default avatarChristian Loehle <christian.loehle@arm.com>
Link: https://patch.msgid.link/20260126100050.3854740-6-arighi@nvidia.com
parent cd959a35
Loading
Loading
Loading
Loading
+133 −24
Original line number Diff line number Diff line
@@ -330,14 +330,16 @@ enum dl_param {
	DL_PERIOD,
};

static unsigned long fair_server_period_max = (1UL << 22) * NSEC_PER_USEC; /* ~4 seconds */
static unsigned long fair_server_period_min = (100) * NSEC_PER_USEC;     /* 100 us */
static unsigned long dl_server_period_max = (1UL << 22) * NSEC_PER_USEC; /* ~4 seconds */
static unsigned long dl_server_period_min = (100) * NSEC_PER_USEC;     /* 100 us */

static ssize_t sched_fair_server_write(struct file *filp, const char __user *ubuf,
				       size_t cnt, loff_t *ppos, enum dl_param param)
static ssize_t sched_server_write_common(struct file *filp, const char __user *ubuf,
					 size_t cnt, loff_t *ppos, enum dl_param param,
					 void *server)
{
	long cpu = (long) ((struct seq_file *) filp->private_data)->private;
	struct rq *rq = cpu_rq(cpu);
	struct sched_dl_entity *dl_se = (struct sched_dl_entity *)server;
	u64 runtime, period;
	int retval = 0;
	size_t err;
@@ -350,8 +352,8 @@ static ssize_t sched_fair_server_write(struct file *filp, const char __user *ubu
	scoped_guard (rq_lock_irqsave, rq) {
		bool is_active;

		runtime  = rq->fair_server.dl_runtime;
		period = rq->fair_server.dl_period;
		runtime = dl_se->dl_runtime;
		period = dl_se->dl_period;

		switch (param) {
		case DL_RUNTIME:
@@ -367,25 +369,25 @@ static ssize_t sched_fair_server_write(struct file *filp, const char __user *ubu
		}

		if (runtime > period ||
		    period > fair_server_period_max ||
		    period < fair_server_period_min) {
		    period > dl_server_period_max ||
		    period < dl_server_period_min) {
			return  -EINVAL;
		}

		is_active = dl_server_active(&rq->fair_server);
		is_active = dl_server_active(dl_se);
		if (is_active) {
			update_rq_clock(rq);
			dl_server_stop(&rq->fair_server);
			dl_server_stop(dl_se);
		}

		retval = dl_server_apply_params(&rq->fair_server, runtime, period, 0);
		retval = dl_server_apply_params(dl_se, runtime, period, 0);

		if (!runtime)
			printk_deferred("Fair server disabled in CPU %d, system may crash due to starvation.\n",
					cpu_of(rq));
			printk_deferred("%s server disabled in CPU %d, system may crash due to starvation.\n",
					server == &rq->fair_server ? "Fair" : "Ext", cpu_of(rq));

		if (is_active && runtime)
			dl_server_start(&rq->fair_server);
			dl_server_start(dl_se);

		if (retval < 0)
			return retval;
@@ -395,36 +397,42 @@ static ssize_t sched_fair_server_write(struct file *filp, const char __user *ubu
	return cnt;
}

static size_t sched_fair_server_show(struct seq_file *m, void *v, enum dl_param param)
static size_t sched_server_show_common(struct seq_file *m, void *v, enum dl_param param,
				       void *server)
{
	unsigned long cpu = (unsigned long) m->private;
	struct rq *rq = cpu_rq(cpu);
	struct sched_dl_entity *dl_se = (struct sched_dl_entity *)server;
	u64 value;

	switch (param) {
	case DL_RUNTIME:
		value = rq->fair_server.dl_runtime;
		value = dl_se->dl_runtime;
		break;
	case DL_PERIOD:
		value = rq->fair_server.dl_period;
		value = dl_se->dl_period;
		break;
	}

	seq_printf(m, "%llu\n", value);
	return 0;

}

static ssize_t
sched_fair_server_runtime_write(struct file *filp, const char __user *ubuf,
				size_t cnt, loff_t *ppos)
{
	return sched_fair_server_write(filp, ubuf, cnt, ppos, DL_RUNTIME);
	long cpu = (long) ((struct seq_file *) filp->private_data)->private;
	struct rq *rq = cpu_rq(cpu);

	return sched_server_write_common(filp, ubuf, cnt, ppos, DL_RUNTIME,
					&rq->fair_server);
}

static int sched_fair_server_runtime_show(struct seq_file *m, void *v)
{
	return sched_fair_server_show(m, v, DL_RUNTIME);
	unsigned long cpu = (unsigned long) m->private;
	struct rq *rq = cpu_rq(cpu);

	return sched_server_show_common(m, v, DL_RUNTIME, &rq->fair_server);
}

static int sched_fair_server_runtime_open(struct inode *inode, struct file *filp)
@@ -440,16 +448,57 @@ static const struct file_operations fair_server_runtime_fops = {
	.release	= single_release,
};

#ifdef CONFIG_SCHED_CLASS_EXT
static ssize_t
sched_ext_server_runtime_write(struct file *filp, const char __user *ubuf,
			       size_t cnt, loff_t *ppos)
{
	long cpu = (long) ((struct seq_file *) filp->private_data)->private;
	struct rq *rq = cpu_rq(cpu);

	return sched_server_write_common(filp, ubuf, cnt, ppos, DL_RUNTIME,
					&rq->ext_server);
}

static int sched_ext_server_runtime_show(struct seq_file *m, void *v)
{
	unsigned long cpu = (unsigned long) m->private;
	struct rq *rq = cpu_rq(cpu);

	return sched_server_show_common(m, v, DL_RUNTIME, &rq->ext_server);
}

static int sched_ext_server_runtime_open(struct inode *inode, struct file *filp)
{
	return single_open(filp, sched_ext_server_runtime_show, inode->i_private);
}

static const struct file_operations ext_server_runtime_fops = {
	.open		= sched_ext_server_runtime_open,
	.write		= sched_ext_server_runtime_write,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= single_release,
};
#endif /* CONFIG_SCHED_CLASS_EXT */

static ssize_t
sched_fair_server_period_write(struct file *filp, const char __user *ubuf,
			       size_t cnt, loff_t *ppos)
{
	return sched_fair_server_write(filp, ubuf, cnt, ppos, DL_PERIOD);
	long cpu = (long) ((struct seq_file *) filp->private_data)->private;
	struct rq *rq = cpu_rq(cpu);

	return sched_server_write_common(filp, ubuf, cnt, ppos, DL_PERIOD,
					&rq->fair_server);
}

static int sched_fair_server_period_show(struct seq_file *m, void *v)
{
	return sched_fair_server_show(m, v, DL_PERIOD);
	unsigned long cpu = (unsigned long) m->private;
	struct rq *rq = cpu_rq(cpu);

	return sched_server_show_common(m, v, DL_PERIOD, &rq->fair_server);
}

static int sched_fair_server_period_open(struct inode *inode, struct file *filp)
@@ -465,6 +514,40 @@ static const struct file_operations fair_server_period_fops = {
	.release	= single_release,
};

#ifdef CONFIG_SCHED_CLASS_EXT
static ssize_t
sched_ext_server_period_write(struct file *filp, const char __user *ubuf,
			      size_t cnt, loff_t *ppos)
{
	long cpu = (long) ((struct seq_file *) filp->private_data)->private;
	struct rq *rq = cpu_rq(cpu);

	return sched_server_write_common(filp, ubuf, cnt, ppos, DL_PERIOD,
					&rq->ext_server);
}

static int sched_ext_server_period_show(struct seq_file *m, void *v)
{
	unsigned long cpu = (unsigned long) m->private;
	struct rq *rq = cpu_rq(cpu);

	return sched_server_show_common(m, v, DL_PERIOD, &rq->ext_server);
}

static int sched_ext_server_period_open(struct inode *inode, struct file *filp)
{
	return single_open(filp, sched_ext_server_period_show, inode->i_private);
}

static const struct file_operations ext_server_period_fops = {
	.open		= sched_ext_server_period_open,
	.write		= sched_ext_server_period_write,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= single_release,
};
#endif /* CONFIG_SCHED_CLASS_EXT */

static struct dentry *debugfs_sched;

static void debugfs_fair_server_init(void)
@@ -488,6 +571,29 @@ static void debugfs_fair_server_init(void)
	}
}

#ifdef CONFIG_SCHED_CLASS_EXT
static void debugfs_ext_server_init(void)
{
	struct dentry *d_ext;
	unsigned long cpu;

	d_ext = debugfs_create_dir("ext_server", debugfs_sched);
	if (!d_ext)
		return;

	for_each_possible_cpu(cpu) {
		struct dentry *d_cpu;
		char buf[32];

		snprintf(buf, sizeof(buf), "cpu%lu", cpu);
		d_cpu = debugfs_create_dir(buf, d_ext);

		debugfs_create_file("runtime", 0644, d_cpu, (void *) cpu, &ext_server_runtime_fops);
		debugfs_create_file("period", 0644, d_cpu, (void *) cpu, &ext_server_period_fops);
	}
}
#endif /* CONFIG_SCHED_CLASS_EXT */

static __init int sched_init_debug(void)
{
	struct dentry __maybe_unused *numa;
@@ -526,6 +632,9 @@ static __init int sched_init_debug(void)
	debugfs_create_file("debug", 0444, debugfs_sched, NULL, &sched_debug_fops);

	debugfs_fair_server_init();
#ifdef CONFIG_SCHED_CLASS_EXT
	debugfs_ext_server_init();
#endif

	return 0;
}