mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Babu Moger <babu.moger@amd.com>
To: <tony.luck@intel.com>, <reinette.chatre@intel.com>,
	<ben.horgan@arm.com>, <Dave.Martin@arm.com>,
	<james.morse@arm.com>, <bp@alien8.de>
Cc: <babu.moger@amd.com>, <corbet@lwn.net>,
	<skhan@linuxfoundation.org>, <rdunlap@infradead.org>,
	<x86@kernel.org>, <fustini@kernel.org>, <tglx@kernel.org>,
	<mingo@redhat.com>, <dave.hansen@linux.intel.com>,
	<hpa@zytor.com>, <fenghuay@nvidia.com>, <rppt@kernel.org>,
	<arnd@arndb.de>, <kmehltretter@gmail.com>,
	<dapeng1.mi@linux.intel.com>, <elver@google.com>,
	<enelsonmoore@gmail.com>, <jlayton@kernel.org>,
	<seanjc@google.com>, <ewanhai-oc@zhaoxin.com>,
	<binbin.wu@linux.intel.com>, <nikunj@amd.com>,
	<ashish.kalra@amd.com>, <peterz@infradead.org>,
	<superm1@kernel.org>, <thomas.lendacky@amd.com>,
	<prathyushi.nangia@amd.com>, <kim.phillips@amd.com>,
	<ricardo.neri-calderon@linux.intel.com>, <darwi@linutronix.de>,
	<linux-doc@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>
Subject: [PATCH v7 15/19] fs/resctrl: Extend info/kernel_mode to configure the kernel mode
Date: Wed, 11 Nov 2026 16:44:08 -0600	[thread overview]
Message-ID: <f2ad1989facce953f3ffe1b8687ae4fcf8629a26.1794437052.git.babu.moger@amd.com> (raw)
In-Reply-To: <cover.1794437052.git.babu.moger@amd.com>

Kernel mode support allows the CPU's CLOSID and/or RMID associations to
change during the transition from user mode to kernel mode. The resctrl
file info/kernel_mode lists the current kernel mode configuration.

Extend info/kernel_mode with write support so user space can configure the
active kernel mode. Validate kernel mode configuration before activation.
Restrict backing groups to shareable mode so the kernel can use the group's
CLOSID and/or RMID, which are shared with the group's tasks.

Document the interface in Documentation/filesystems/resctrl.rst.

Signed-off-by: Babu Moger <babu.moger@amd.com>
---
v7: Refactored rdtgroup_kmode_global_activate and rdtgroup_kmode_global_deactivate().
    Removed resctrl_kmode_switch().
    Refactored resctrl_kmode_parse_group().
    Handled the "group=" as the last parameter.

v6: Use flattened resctrl_kmode and global_enable_per_cpu. Omitted
    parameters keep the values shown by reading the file. Drop the
    ctrl=inherit;mon=inherit no-op. Parse options with strsep(), as the
    other resctrl writers do, and split validation out of the write path.
    https://lore.kernel.org/lkml/3bc39dd7-b7b0-4203-a493-0bd872fdc644@intel.com/

v5: Adapt to the resctrl_kcfg caps and active split. Accept
    assign_global_enable_per_cpu:ctrl=;mon=;group=<ctrl>/<mon>/ writes.
    Treat both ctrl=inherit and mon=inherit as a no-op. Use group=// for
    the default control group. Show associated kmode files through
    resctrl_hidden_files_set_visible().
    Added kmode check in rdtgroup_locksetup_enter(), rdtgroup_mode_write()
    and rdtgroup_rename().
    Simplify kernel-doc for write and activate helpers.

v4: Validate input before tearing down the active association so failures
    retain the previous association. Allow assign_mon on CTRL_MON and MON
    groups; require a control group when control assignment is inherit.

v3: New patch to make info/kernel_mode writable.
---
 Documentation/filesystems/resctrl.rst |  40 ++++
 fs/resctrl/rdtgroup.c                 | 274 +++++++++++++++++++++++++-
 2 files changed, 313 insertions(+), 1 deletion(-)

diff --git a/Documentation/filesystems/resctrl.rst b/Documentation/filesystems/resctrl.rst
index e57361dd342e..1a1877222624 100644
--- a/Documentation/filesystems/resctrl.rst
+++ b/Documentation/filesystems/resctrl.rst
@@ -608,6 +608,46 @@ The top level of the "info" directory contains the following file(s):
 		[inherit_user]
 		global_enable_per_cpu:ctrl=assign;mon=assign;group=//
 
+	Writes use the same line format as reads, without square brackets and
+	with a trailing newline. Errors are reported in "info/last_cmd_status".
+
+	"inherit_user":
+		Written without parameters.
+
+	"global_enable_per_cpu":
+		"ctrl=", "mon=", and "group=" are optional.
+
+		An omitted "ctrl=", "mon=" and "group=" keeps the default values.
+
+		If "mon=inherit", or monitoring is unsupported, "group=" must
+		reference a CTRL_MON group.
+
+		The "ctrl=inherit" together with "mon=inherit" is rejected.
+
+		A MON group requires "mon=assign".
+
+		"group=" must be the last parameter. The group must be in shareable mode.
+
+		Selecting a new kernel mode, parameter, or group replaces the active
+		mode and updates "kmode_cpus" to include all online CPUs.
+
+		Empty values are rejected.
+
+		Example::
+
+			# mkdir ctrl1
+			# echo "global_enable_per_cpu:ctrl=assign;mon=assign;group=ctrl1//" \
+				> info/kernel_mode
+
+			# cat info/kernel_mode
+			inherit_user
+			[global_enable_per_cpu:ctrl=assign;mon=assign;group=ctrl1//]
+
+			# echo "inherit_user" > info/kernel_mode
+			# cat info/kernel_mode
+			[inherit_user]
+			global_enable_per_cpu:ctrl=assign;mon=assign;group=//
+
 Resource alloc and monitor groups
 =================================
 
diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index 97d99406de00..872755532fb4 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -1201,6 +1201,277 @@ static void rdtgroup_kmode_global_deactivate(struct rdtgroup *rdtgrp)
 	resctrl_kmode.mon = KMODE_ASSIGN;
 }
 
+/* Program @rdtgrp on every online CPU and show its kmode_cpus files. */
+static void rdtgroup_kmode_global_activate(struct rdtgroup *rdtgrp,
+					   enum resctrl_kernel_mode mode,
+					   enum kmode_state ctrl,
+					   enum kmode_state mon)
+{
+	resctrl_kmode.active = mode;
+	resctrl_kmode.ctrl = ctrl;
+	resctrl_kmode.mon = mon;
+	resctrl_kmode.rdtgrp = rdtgrp;
+
+	cpumask_copy(&rdtgrp->kmode_cpu_mask, cpu_online_mask);
+	resctrl_configure_kmode_global(&rdtgrp->kmode_cpu_mask, rdtgrp, true);
+}
+
+static int resctrl_kmode_parse_state(char *val, enum kmode_state *state)
+{
+	if (!strcmp(val, "assign")) {
+		*state = KMODE_ASSIGN;
+		return 0;
+	}
+	if (!strcmp(val, "inherit")) {
+		*state = KMODE_INHERIT;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+/*
+ * group is "<CTRL_MON>/" or "<CTRL_MON>/<MON>/". The MON component is
+ * optional: mon=inherit and systems without monitoring do not require it.
+ * An empty name selects the default CTRL_MON group. Names are not trimmed;
+ * "/" cannot appear in a resource group name.
+ */
+static int resctrl_kmode_parse_group(char *group, struct rdtgroup **rdtgrp)
+{
+	struct rdtgroup *rdtg, *parent = &rdtgroup_default;
+	char *mon = NULL, *slash;
+	size_t len;
+
+	len = strlen(group);
+	if (!len || group[len - 1] != '/') {
+		rdt_last_cmd_puts("Group must be <CTRL_MON>/ or <CTRL_MON>/<MON>/\n");
+		return -EINVAL;
+	}
+	group[len - 1] = '\0';
+
+	slash = strchr(group, '/');
+	if (slash) {
+		*slash = '\0';
+		mon = slash + 1;
+		if (strchr(mon, '/')) {
+			rdt_last_cmd_puts("Group must be <CTRL_MON>/ or <CTRL_MON>/<MON>/\n");
+			return -EINVAL;
+		}
+	}
+
+	if (group[0] != '\0') {
+		parent = NULL;
+		list_for_each_entry(rdtg, &rdt_all_groups, rdtgroup_list) {
+			if (!strcmp(rdt_kn_name(rdtg->kn), group)) {
+				parent = rdtg;
+				break;
+			}
+		}
+	}
+	if (!parent)
+		goto not_found;
+
+	if (!mon || mon[0] == '\0') {
+		*rdtgrp = parent;
+		return 0;
+	}
+
+	list_for_each_entry(rdtg, &parent->mon.crdtgrp_list, mon.crdtgrp_list) {
+		if (!strcmp(rdt_kn_name(rdtg->kn), mon)) {
+			*rdtgrp = rdtg;
+			return 0;
+		}
+	}
+
+not_found:
+	rdt_last_cmd_puts("Group not found\n");
+	return -EINVAL;
+}
+
+static int resctrl_kmode_parse_parameters(char *params, enum kmode_state *ctrl,
+					  enum kmode_state *mon,
+					  struct rdtgroup **rdtgrp)
+{
+	char *key, *tok;
+
+	while ((tok = strsep(&params, ";"))) {
+		key = strsep(&tok, "=");
+		if (!tok) {
+			if (strim(key)[0] == '\0')
+				continue;
+			rdt_last_cmd_puts("Missing '=' in kernel mode parameter\n");
+			return -EINVAL;
+		}
+		key = strim(key);
+		if (key[0] == '\0') {
+			rdt_last_cmd_puts("Empty kernel mode parameters\n");
+			return -EINVAL;
+		}
+
+		/*
+		 * group= is the last parameter and may contain ';'.
+		 * Restore it if stripped.
+		 */
+		if (!strcmp(key, "group") && params)
+			params[-1] = ';';
+
+		tok = strim(tok);
+		if (tok[0] == '\0') {
+			rdt_last_cmd_puts("Empty kernel mode parameters\n");
+			return -EINVAL;
+		}
+
+		if (!strcmp(key, "group"))
+			return resctrl_kmode_parse_group(tok, rdtgrp);
+
+		if (!strcmp(key, "ctrl")) {
+			if (!resctrl_arch_alloc_capable()) {
+				rdt_last_cmd_puts("ctrl= is not supported\n");
+				return -EINVAL;
+			}
+			if (resctrl_kmode_parse_state(tok, ctrl)) {
+				rdt_last_cmd_puts("Invalid ctrl= parameter\n");
+				return -EINVAL;
+			}
+		} else if (!strcmp(key, "mon")) {
+			if (!resctrl_arch_mon_capable()) {
+				rdt_last_cmd_puts("mon= is not supported\n");
+				return -EINVAL;
+			}
+			if (resctrl_kmode_parse_state(tok, mon)) {
+				rdt_last_cmd_puts("Invalid mon= parameter\n");
+				return -EINVAL;
+			}
+		} else {
+			rdt_last_cmd_puts("Unsupported kernel mode parameter\n");
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int resctrl_kmode_global_validate(struct rdtgroup *rdtgrp,
+					 enum kmode_state ctrl,
+					 enum kmode_state mon)
+{
+	if (ctrl == KMODE_ASSIGN && !resctrl_arch_alloc_capable()) {
+		rdt_last_cmd_puts("ctrl=assign is not supported\n");
+		return -EINVAL;
+	}
+	if (mon == KMODE_ASSIGN && !resctrl_arch_mon_capable()) {
+		rdt_last_cmd_puts("mon=assign is not supported\n");
+		return -EINVAL;
+	}
+	if (mon == KMODE_INHERIT && rdtgrp->type == RDTMON_GROUP) {
+		rdt_last_cmd_puts("A monitor group requires mon=assign parameter\n");
+		return -EINVAL;
+	}
+	if (rdtgrp->mode != RDT_MODE_SHAREABLE) {
+		rdt_last_cmd_puts("The group is not in shareable mode\n");
+		return -EINVAL;
+	}
+	if (rdtgrp->type == RDTMON_GROUP &&
+	    rdtgrp->mon.parent->mode != RDT_MODE_SHAREABLE) {
+		rdt_last_cmd_puts("The parent group is not in shareable mode\n");
+		return -EINVAL;
+	}
+	if (ctrl == KMODE_INHERIT && mon == KMODE_INHERIT) {
+		rdt_last_cmd_puts("ctrl=inherit and mon=inherit is not supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * resctrl_kernel_mode_write() - Set the active kernel mode
+ * @of:		kernfs open file
+ * @buf:	Kernel mode line written by user space
+ * @nbytes:	length of @buf
+ * @off:	unused
+ *
+ * Return: @nbytes on success, negative errno on error.
+ */
+static ssize_t resctrl_kernel_mode_write(struct kernfs_open_file *of,
+					 char *buf, size_t nbytes, loff_t off)
+{
+	enum resctrl_kernel_mode mode;
+	enum kmode_state ctrl, mon;
+	char *mode_str, *params;
+	struct rdtgroup *rdtgrp;
+	int ret = 0;
+
+	if (!info_kn_lock(of->kn))
+		return -ENOENT;
+
+	rdt_last_cmd_clear();
+
+	if (nbytes == 0 || buf[nbytes - 1] != '\n') {
+		rdt_last_cmd_puts("kernel_mode: Invalid input\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+	buf[nbytes - 1] = '\0';
+
+	mode_str = strsep(&buf, ":");
+	mode_str = strim(mode_str);
+	params = buf;
+
+	for (mode = 0; mode < RESCTRL_NUM_KERNEL_MODES; mode++) {
+		if (!strcmp(mode_str, resctrl_kmode_str[mode]))
+			break;
+	}
+	if (mode == RESCTRL_NUM_KERNEL_MODES) {
+		rdt_last_cmd_puts("Unknown kernel mode\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+	if (!test_bit(mode, resctrl_kmode.supported)) {
+		rdt_last_cmd_puts("Kernel mode not available\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	if (mode == RESCTRL_INHERIT_USER) {
+		/* "inherit_user" does not support parameters */
+		if (params && strim(params)[0] != '\0') {
+			rdt_last_cmd_puts("Unsupported parameter\n");
+			ret = -EINVAL;
+			goto out_unlock;
+		}
+		if (resctrl_kmode.active == RESCTRL_GLOBAL_ENABLE_PER_CPU)
+			rdtgroup_kmode_global_deactivate(resctrl_kmode.rdtgrp);
+		goto out_unlock;
+	}
+
+	/* Initialize the default values */
+	ctrl = resctrl_arch_alloc_capable() ? KMODE_ASSIGN : KMODE_INHERIT;
+	mon = resctrl_arch_mon_capable() ? KMODE_ASSIGN : KMODE_INHERIT;
+	rdtgrp = &rdtgroup_default;
+
+	if (params) {
+		ret = resctrl_kmode_parse_parameters(params, &ctrl, &mon, &rdtgrp);
+		if (ret)
+			goto out_unlock;
+	}
+
+	ret = resctrl_kmode_global_validate(rdtgrp, ctrl, mon);
+	if (ret)
+		goto out_unlock;
+
+	if (resctrl_kmode.active == mode && resctrl_kmode.rdtgrp == rdtgrp &&
+	    resctrl_kmode.ctrl == ctrl && resctrl_kmode.mon == mon)
+		goto out_unlock;
+
+	if (resctrl_kmode.active == RESCTRL_GLOBAL_ENABLE_PER_CPU)
+		rdtgroup_kmode_global_deactivate(resctrl_kmode.rdtgrp);
+
+	rdtgroup_kmode_global_activate(rdtgrp, mode, ctrl, mon);
+
+out_unlock:
+	info_kn_unlock(of->kn);
+	return ret ?: nbytes;
+}
+
 void *rdt_kn_parent_priv(struct kernfs_node *kn)
 {
 	/*
@@ -2188,9 +2459,10 @@ static struct rftype res_common_files[] = {
 	},
 	{
 		.name		= "kernel_mode",
-		.mode		= 0444,
+		.mode		= 0644,
 		.kf_ops		= &rdtgroup_kf_single_ops,
 		.seq_show	= resctrl_kernel_mode_show,
+		.write		= resctrl_kernel_mode_write,
 		.fflags		= RFTYPE_TOP_INFO,
 	},
 	{
-- 
2.43.0


  parent reply	other threads:[~2026-11-11 22:47 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-11 22:43 [PATCH v7 00/19] x86,fs/resctrl: Add kernel-mode (e.g., PLZA) support to the resctrl subsystem Babu Moger
2026-11-11 22:43 ` [PATCH v7 01/19] x86/cpufeatures: Support Privilege Level Zero Association (PLZA) Babu Moger
2026-11-11 22:43 ` [PATCH v7 02/19] x86/resctrl: Add PLZA support to command-line options Babu Moger
2026-11-11 22:43 ` [PATCH v7 03/19] x86/resctrl: Add PLZA MSR definition and field layout Babu Moger
2026-11-11 22:43 ` [PATCH v7 04/19] fs/resctrl: Introduce kernel mode enum Babu Moger
2026-11-11 22:43 ` [PATCH v7 05/19] arm,x86,fs/resctrl: Introduce arch hook to program global per-CPU kernel mode Babu Moger
2026-11-11 22:43 ` [PATCH v7 06/19] fs/resctrl: Introduce data structures for kernel mode configuration Babu Moger
2026-11-11 22:44 ` [PATCH v7 07/19] fs/resctrl: Introduce resctrl_set_kmode_support() to register supported modes Babu Moger
2026-11-11 22:44 ` [PATCH v7 08/19] x86/resctrl: Register RESCTRL_GLOBAL_ENABLE_PER_CPU when PLZA is available Babu Moger
2026-11-11 22:44 ` [PATCH v7 09/19] fs/resctrl: Rearrange top-level files in info directory Babu Moger
2026-11-11 22:44 ` [PATCH v7 10/19] fs/resctrl: Add interface to display kernel mode status Babu Moger
2026-11-11 22:44 ` [PATCH v7 11/19] fs/resctrl: Add support for hidden resource group files Babu Moger
2026-11-11 22:44 ` [PATCH v7 12/19] fs/resctrl: Introduce kmode_cpus/kmode_cpus_list per rdtgroup Babu Moger
2026-11-11 22:44 ` [PATCH v7 13/19] x86,fs/resctrl: Add CPU hotplug support for kernel mode Babu Moger
2026-11-11 22:44 ` [PATCH v7 14/19] fs/resctrl: Deactivate kernel mode when the group is removed Babu Moger
2026-11-11 22:44 ` Babu Moger [this message]
2026-11-11 22:44 ` [PATCH v7 16/19] fs/resctrl: Reject mode changes for groups backing kernel mode Babu Moger
2026-11-11 22:44 ` [PATCH v7 17/19] fs/resctrl: Control visibility of global per-CPU kernel mode group files Babu Moger
2026-11-11 22:44 ` [PATCH v7 18/19] fs/resctrl: Allow userspace to write kmode_cpus/kmode_cpus_list Babu Moger
2026-11-11 22:44 ` [PATCH v7 19/19] fs/resctrl: Add kernel mode documentation and examples Babu Moger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f2ad1989facce953f3ffe1b8687ae4fcf8629a26.1794437052.git.babu.moger@amd.com \
    --to=babu.moger@amd.com \
    --cc=Dave.Martin@arm.com \
    --cc=arnd@arndb.de \
    --cc=ashish.kalra@amd.com \
    --cc=ben.horgan@arm.com \
    --cc=binbin.wu@linux.intel.com \
    --cc=bp@alien8.de \
    --cc=corbet@lwn.net \
    --cc=dapeng1.mi@linux.intel.com \
    --cc=darwi@linutronix.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=elver@google.com \
    --cc=enelsonmoore@gmail.com \
    --cc=ewanhai-oc@zhaoxin.com \
    --cc=fenghuay@nvidia.com \
    --cc=fustini@kernel.org \
    --cc=hpa@zytor.com \
    --cc=james.morse@arm.com \
    --cc=jlayton@kernel.org \
    --cc=kim.phillips@amd.com \
    --cc=kmehltretter@gmail.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=nikunj@amd.com \
    --cc=peterz@infradead.org \
    --cc=prathyushi.nangia@amd.com \
    --cc=rdunlap@infradead.org \
    --cc=reinette.chatre@intel.com \
    --cc=ricardo.neri-calderon@linux.intel.com \
    --cc=rppt@kernel.org \
    --cc=seanjc@google.com \
    --cc=skhan@linuxfoundation.org \
    --cc=superm1@kernel.org \
    --cc=tglx@kernel.org \
    --cc=thomas.lendacky@amd.com \
    --cc=tony.luck@intel.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®