Skip to contentSkip to conversation

x86/resctrl: Add kernel-mode (e.g., PLZA) support to the resctrl subsystem

PATCH RESEND Superseded Babu Moger 5 participants 79 messages Jul 7 – Aug 14

Subsystems (4)

v4 of 7 Superseded Latest is v7 →

lore
Share & tools
lore

Babu Moger

author reviewer
#0 lore raw

v4 cover x86/resctrl: Add kernel-mode (e.g., PLZA) support to the resctrl subsystem

Hi All,

Had some problem sending the patches earlier. Resending it again.

This series adds support for AMD's Privilege-Level Zero Association (PLZA) so kernel work can be assigned to a resctrl group, and wires it up through a small generic "kernel mode" (kmode) layer in fs/resctrl so future architectures can plug in without touching core resctrl.

The features are documented in:

AMD64 Zen6 Platform Quality of Service (PQOS) Extensions, Publication # 69193 Revision 1.00, Issue Date March 2026

available at https://bugzilla.kernel.org/show_bug.cgi?id=206537

The patches are based on top of commit (tip/master v7.2-rc2):

f705c6728b35 Merge branch into tip/master: 'x86/msr'

Background
==========

Customers have identified an issue while using the QoS resource Control feature. If a memory bandwidth associated with a CLOSID is aggressively throttled, and it moves into Kernel mode, the Kernel operations are also aggressively throttled. This can stall forward progress and eventually degrade overall system performance.

Privilege-Level Zero Association (PLZA) allows the user to specify a CLOSID and/or RMID for execution at Privilege Level Zero. When PLZA is enabled on a CPU, kernel work at PL0 uses the CLOSID and/or RMID from MSR PQR_PLZA_ASSOC; otherwise, the CPU uses the CLOSID and RMID from PQR_ASSOC.

Design
======

A new sysfs file, info/kernel_mode, holds the global policy for resource allocation and monitoring of kernel work and the resource group (when applicable) associated with the policy. Reads list the supported modes and the currently active binding; writes change the policy or rebind to a different group. Look at the thread below for design discussion.
https://lore.kernel.org/lkml/[email protected]/

Per-rdtgroup files kmode_cpus and kmode_cpus_list scope the binding to a subset of online CPUs without unbind/rebind churn. They are visible only on the group that is currently the active kernel-mode binding.

The arch hook, resctrl_arch_configure_kmode keep the fs/resctrl layer arch-neutral.

Introduced resctrl_set_kmode_support() so architecture code can register supported kernel-mode policies during resctrl initialization.

Only AMD PLZA is wired up here; Intel and ARM can add their own support later by implementing the hooks.

Examples
========

(See Documentation/filesystems/resctrl.rst, "kernel_mode", "kmode_cpus", and "Examples on working with kernel_mode", for the full UAPI.)

# Mount resctrl

  # mount -t resctrl resctrl /sys/fs/resctrl
  # cd /sys/fs/resctrl

# Read the supported modes. The active mode is bracketed for display

  # only.  Inactive global-assign modes report ":group=uninitialized".
  # cat info/kernel_mode
  [inherit_ctrl_and_mon]
  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
  global_assign_ctrl_assign_mon_per_cpu:group=uninitialized

# Create a CTRL_MON group and bind kernel-mode allocation to it.

  # mkdir ctrl1
  # echo "global_assign_ctrl_inherit_mon_per_cpu:group=ctrl1//" \
          > info/kernel_mode
  # cat info/kernel_mode
  inherit_ctrl_and_mon
  [global_assign_ctrl_inherit_mon_per_cpu:group=ctrl1//]
  global_assign_ctrl_assign_mon_per_cpu:group=uninitialized
  # kmode_cpus and kmode_cpus_list are visible only on the bound group.
  # ls ctrl1/kmode_cpus*
  ctrl1/kmode_cpus  ctrl1/kmode_cpus_list

# Restrict the binding to a CPU subset; the write is incremental.

  # echo 0-3 > ctrl1/kmode_cpus_list
  # cat ctrl1/kmode_cpus
  f
  # cat ctrl1/kmode_cpus_list
  0-3

# Return to the default inherit mode.

  # echo "inherit_ctrl_and_mon" > info/kernel_mode
  # cat info/kernel_mode
  [inherit_ctrl_and_mon]
  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
  global_assign_ctrl_assign_mon_per_cpu:group=uninitialized

Tested on AMD with PLZA; the generic bits build clean on x86 without PLZA support and are no-ops at runtime.

Layout
======

01-03 x86: PLZA CPU feature, command-line option, and MSR/data-structure
plumbing.
04-07 fs/resctrl + x86: kmode data structures, arch hooks, supported-mode
initialization, and PLZA policy advertisement.
08 fs/resctrl: info/kernel_mode read-only introspection.
09-10 fs/resctrl: per-rdtgroup kmode_cpus[_list] exposure and reset of
the binding when the bound rdtgroup is removed.

  11     fs/resctrl: program kernel-mode binding when a CPU comes online.
  12     resctrl: hide kmode_cpus[_list] on groups not bound to kernel-mode.
  13-14  fs/resctrl: info/kernel_mode write and incremental kmode_cpus[_list]

writes.
15 fs/resctrl: documentation and end-to-end examples.

Changelog
=========
v4:
- Reorder and split the series into 15 patches: separate read-only info/kernel_mode display (08) from the write path (13); add hotplug support when a CPU comes online (11); add an end-to-end documentation/examples patch (15).

- Introduced resctrl_set_kmode_support() so architecture code can register supported kernel-mode policies during resctrl initialization.

- info/kernel_mode UAPI: inactive global-assign modes report ":group=uninitialized" (not ":group=none"); the inherit mode has no ":group=" suffix; square brackets mark the active mode on read only and must not be included when writing.

- info/kernel_mode write: validate group type (assign_mon may bind an RDTMON_GROUP or RDTCTRL_GROUP; inherit_mon only RDTCTRL_GROUP); run fail paths before tearing down the active binding so errors retain the old binding; reset any active global-assign binding before reprogramming when rebinding.

- kmode_cpus / kmode_cpus_list: writable with incremental enable/disable deltas; empty masks are allowed; offline CPUs and writes through stale file descriptors (opened before an info/kernel_mode change) are rejected; pseudo-locked and pseudo-lock-setup groups are rejected.

- Hotplug: newly online CPUs are added to the bound group's kmode_cpu_mask and programmed when a global-assign policy is active.

- Documentation updated alongside the UAPI changes, including an "Examples on working with kernel_mode" walk-through.

v3:
- Generalise the layer beyond AMD: rename "PLZA mode" to "kernel mode" (kmode) in code, sysfs, and Documentation. The public interface is now info/kernel_mode and per-group kmode_cpus[_list].
- info/kernel_mode UAPI cleanups: designated initialisers + static_assert for the mode-name table; strim() the input; clearer error messages via last_cmd_status.
- kmode_cpus / kmode_cpus_list: expose read-only, gate visibility on the bound group, and allow incremental writes.
- Reset the binding when the bound rdtgroup is removed, instead of leaving stale state.
- Kerneldoc/comment cleanups across the series.

v2:
- Similar to RFC with a new proposal; interface names were not final.
- Separated Global Bandwidth Enforcement (GLBE) from PLZA; this series only adds PLZA support.
- Used "kmode" instead of "PLZA" in the generic layer.

Previous versions:
v3: https://lore.kernel.org/lkml/[email protected]/
v2: https://lore.kernel.org/lkml/[email protected]/
v1: https://lore.kernel.org/lkml/[email protected]/

Babu Moger (15):
x86/resctrl: Support Privilege Level Zero Association (PLZA) x86/resctrl: Add PLZA support to command-line options x86/resctrl: Add data structures and definitions for PLZA
configuration
fs/resctrl: Introduce kernel mode (kmode) data structures x86,fs/resctrl: Introduce architecture hooks to program kernel-mode fs/resctrl: Introduce resctrl_set_kmode_support() to initialize
supported modes
x86/resctrl: Expose the supported PLZA kernel-mode policies during
init
fs/resctrl: Add interface to display supported and active kernel-mode
policy
fs/resctrl: Introduce kmode_cpus/kmode_cpus_list per rdtgroup fs/resctrl: Reset the kernel-mode binding when an rdtgroup is removed fs/resctrl: Program kernel-mode binding when CPU comes online fs/resctrl: Hide kmode_cpus[_list] on groups not bound to kernel-mode fs/resctrl: Add interface to modify kernel-mode via info/kernel_mode fs/resctrl: Allow user space to write kmode_cpus/kmode_cpus_list fs/resctrl: Add documentation on kernel_mode with example

 .../admin-guide/kernel-parameters.txt         |   2 +-
 Documentation/filesystems/resctrl.rst         | 195 ++++++
 arch/x86/include/asm/cpufeatures.h            |   1 +
 arch/x86/include/asm/msr-index.h              |   1 +
 arch/x86/kernel/cpu/resctrl/core.c            |   8 +
 arch/x86/kernel/cpu/resctrl/ctrlmondata.c     |  36 +
 arch/x86/kernel/cpu/resctrl/internal.h        |  37 +
 arch/x86/kernel/cpu/scattered.c               |   1 +
 drivers/resctrl/mpam_resctrl.c                |   5 +
 fs/resctrl/internal.h                         |  16 +
 fs/resctrl/rdtgroup.c                         | 663 ++++++++++++++++++
 include/linux/resctrl.h                       |  56 ++
 12 files changed, 1020 insertions(+), 1 deletion(-)
Signature · 1 line
2.43.0
author reviewer
#1 lore raw

PATCH RESEND v4 1/15 x86/resctrl: Support Privilege Level Zero Association (PLZA)

Customers have identified an issue while using the QoS resource control feature. If memory bandwidth associated with a CLOSID is aggressively throttled, and a task with that CLOSID moves into kernel mode, the kernel operations are also aggressively throttled. This can stall forward progress and eventually degrade overall system performance.

AMD hardware supports a feature Privilege Level Zero Association (PLZA), which allows the CPU's CLOSID association to be changed during the transition from user mode to kernel mode. This allows the kernel to run using a different CLOSID than user space, which can improve system performance in certain scenarios.

The feature is detected via CPUID_Fn80000020_EBX_x00 [Bit 9]:
Privilege Level Zero Association (PLZA).

The PLZA feature details are documented in [1] available from [2].

[1] AMD64 Zen6 Platform Quality of Service (PQOS) Extensions:

    Publication # 69193 Revision: 1.00, Issue Date: March 2026

---
v4: Split the patch into 2. This patch only handles x86 changes.
Re-wrote the changelog along the ABMC changes.

v3: Code did not change. Patch order changed.
Added documentation link.

v2: Rebased on top of the latest tip.

---
 arch/x86/include/asm/cpufeatures.h | 1 +
 arch/x86/kernel/cpu/scattered.c    | 1 +
 2 files changed, 2 insertions(+)
arch/x86/include/asm/cpufeatures.h +1 -0
index 1b4a48bff18f..bf6fc71f87fa 100644
@@ -517,6 +517,7 @@
 						      * and purposes if CLEAR_CPU_BUF_VM is set).
 						      */
 #define X86_FEATURE_X2AVIC_EXT		(21*32+20) /* AMD SVM x2AVIC support for 4k vCPUs */
+#define X86_FEATURE_PLZA		(21*32+21) /* Privilege Level Zero Association */
 
 /*
  * BUG word(s)
arch/x86/kernel/cpu/scattered.c +1 -0
index 937129ce6a96..1fa4d5aef17e 100644
@@ -61,6 +61,7 @@ static const struct cpuid_bit cpuid_bits[] = {
 	{ X86_FEATURE_BMEC,			CPUID_EBX,  3, 0x80000020, 0 },
 	{ X86_FEATURE_ABMC,			CPUID_EBX,  5, 0x80000020, 0 },
 	{ X86_FEATURE_SDCIAE,			CPUID_EBX,  6, 0x80000020, 0 },
+	{ X86_FEATURE_PLZA,			CPUID_EBX,  9, 0x80000020, 0 },
 	{ X86_FEATURE_TSA_SQ_NO,		CPUID_ECX,  1, 0x80000021, 0 },
 	{ X86_FEATURE_TSA_L1_NO,		CPUID_ECX,  2, 0x80000021, 0 },
 	{ X86_FEATURE_AMD_WORKLOAD_CLASS,	CPUID_EAX, 22, 0x80000021, 0 },
Signature · 1 line
2.43.0
maintainer Acked-by on v4 1/15
#2 lore raw

Re: [RESEND PATCH v4 01/15] x86/resctrl: Support Privilege Level Zero Association (PLZA)

Quoted 1 line · Babu Moger

Customers have identified an issue while using the QoS resource control

Please drop the "customers" speak from kernel code.

Quoted 25 lines

feature. If memory bandwidth associated with a CLOSID is aggressively throttled, and a task with that CLOSID moves into kernel mode, the kernel operations are also aggressively throttled. This can stall forward progress and eventually degrade overall system performance.

AMD hardware supports a feature Privilege Level Zero Association (PLZA), which allows the CPU's CLOSID association to be changed during the transition from user mode to kernel mode. This allows the kernel to run using a different CLOSID than user space, which can improve system performance in certain scenarios.

The feature is detected via CPUID_Fn80000020_EBX_x00 [Bit 9]:
Privilege Level Zero Association (PLZA).

The PLZA feature details are documented in [1] available from [2].

[1] AMD64 Zen6 Platform Quality of Service (PQOS) Extensions:

    Publication # 69193 Revision: 1.00, Issue Date: March 2026

---
v4: Split the patch into 2. This patch only handles x86 changes.
Re-wrote the changelog along the ABMC changes.

Quoted 8 lines

v3: Code did not change. Patch order changed.
Added documentation link.

v2: Rebased on top of the latest tip.

---
 arch/x86/include/asm/cpufeatures.h | 1 +
 arch/x86/kernel/cpu/scattered.c    | 1 +
 2 files changed, 2 insertions(+)

With that addressed:

Signature · 4 lines
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette
author reviewer
#3 lore raw

Re: [RESEND PATCH v4 01/15] x86/resctrl: Support Privilege Level Zero Association (PLZA)

Hi Boris,

Quoted 4 lines · Borislav Petkov
Quoted 1 line · Babu Moger

Customers have identified an issue while using the QoS resource control

Please drop the "customers" speak from kernel code.

Will change the text to:

When memory bandwidth associated with a CLOSID is aggressively
throttled, and a task with that CLOSID moves into kernel mode, the kernel operations are also aggressively throttled. This can stall forward progress and eventually degrade overall system performance.

Quoted 35 lines
Quoted 26 lines

feature. If memory bandwidth associated with a CLOSID is aggressively throttled, and a task with that CLOSID moves into kernel mode, the kernel operations are also aggressively throttled. This can stall forward progress and eventually degrade overall system performance.

AMD hardware supports a feature Privilege Level Zero Association (PLZA), which allows the CPU's CLOSID association to be changed during the transition from user mode to kernel mode. This allows the kernel to run using a different CLOSID than user space, which can improve system performance in certain scenarios.

The feature is detected via CPUID_Fn80000020_EBX_x00 [Bit 9]:
Privilege Level Zero Association (PLZA).

The PLZA feature details are documented in [1] available from [2].

[1] AMD64 Zen6 Platform Quality of Service (PQOS) Extensions:

     Publication # 69193 Revision: 1.00, Issue Date: March 2026

---
v4: Split the patch into 2. This patch only handles x86 changes.
Re-wrote the changelog along the ABMC changes.

Quoted 8 lines

v3: Code did not change. Patch order changed.
Added documentation link.

v2: Rebased on top of the latest tip.

---
  arch/x86/include/asm/cpufeatures.h | 1 +
  arch/x86/kernel/cpu/scattered.c    | 1 +
  2 files changed, 2 insertions(+)
Quoted 4 lines

With that addressed:

Thanks
Babu

maintainer
#4 lore raw

Re: [RESEND PATCH v4 01/15] x86/resctrl: Support Privilege Level Zero Association (PLZA)

Quoted 4 lines · Babu Moger

Will change the text to:

When memory bandwidth associated with a CLOSID is aggressively
throttled, and a task with that CLOSID moves into kernel mode, the kernel operations are also aggressively throttled. This can stall forward progress and eventually degrade overall system performance.

Yes, pls keep it generic.

Thx.

Signature · 1 line
Small device. Typos and formatting crap
author reviewer
#5 lore raw

Re: [RESEND PATCH v4 01/15] x86/resctrl: Support Privilege Level Zero Association (PLZA)

In reply to Babu Moger
Quoted 52 lines · Babu Moger

Customers have identified an issue while using the QoS resource control feature. If memory bandwidth associated with a CLOSID is aggressively throttled, and a task with that CLOSID moves into kernel mode, the kernel operations are also aggressively throttled. This can stall forward progress and eventually degrade overall system performance.

AMD hardware supports a feature Privilege Level Zero Association (PLZA), which allows the CPU's CLOSID association to be changed during the transition from user mode to kernel mode. This allows the kernel to run using a different CLOSID than user space, which can improve system performance in certain scenarios.

The feature is detected via CPUID_Fn80000020_EBX_x00 [Bit 9]:
Privilege Level Zero Association (PLZA).

The PLZA feature details are documented in [1] available from [2].

[1] AMD64 Zen6 Platform Quality of Service (PQOS) Extensions:

     Publication # 69193 Revision: 1.00, Issue Date: March 2026

---
v4: Split the patch into 2. This patch only handles x86 changes.
Re-wrote the changelog along the ABMC changes.

v3: Code did not change. Patch order changed.
Added documentation link.

v2: Rebased on top of the latest tip.

---
  arch/x86/include/asm/cpufeatures.h | 1 +
  arch/x86/kernel/cpu/scattered.c    | 1 +
  2 files changed, 2 insertions(+)
arch/x86/include/asm/cpufeatures.h +1 -0
index 1b4a48bff18f..bf6fc71f87fa 100644
@@ -517,6 +517,7 @@
  						      * and purposes if CLEAR_CPU_BUF_VM is set).
  						      */
  #define X86_FEATURE_X2AVIC_EXT		(21*32+20) /* AMD SVM x2AVIC support for 4k vCPUs */
+#define X86_FEATURE_PLZA		(21*32+21) /* Privilege Level Zero Association */
 
  /*
   * BUG word(s)
arch/x86/kernel/cpu/scattered.c +0 -0
index 937129ce6a96..1fa4d5aef17e 100644

arch/x86/kernel/cpu/scattered.c static const struct cpuid_bit cpuid_bits[] = { · line 67

Quoted 7 lines
arch/x86/kernel/cpu/scattered.c +1 -0
@@ -61,6 +61,7 @@ static const struct cpuid_bit cpuid_bits[] = {
  	{ X86_FEATURE_BMEC,			CPUID_EBX,  3, 0x80000020, 0 },
  	{ X86_FEATURE_ABMC,			CPUID_EBX,  5, 0x80000020, 0 },
  	{ X86_FEATURE_SDCIAE,			CPUID_EBX,  6, 0x80000020, 0 },
+	{ X86_FEATURE_PLZA,			CPUID_EBX,  9, 0x80000020, 0 },
  	{ X86_FEATURE_TSA_SQ_NO,		CPUID_ECX,  1, 0x80000021, 0 },
  	{ X86_FEATURE_TSA_L1_NO,		CPUID_ECX,  2, 0x80000021, 0 },
  	{ X86_FEATURE_AMD_WORKLOAD_CLASS,	CPUID_EAX, 22, 0x80000021, 0 },

Sashiko reported:

--- Patch [1]: [RESEND PATCH v4 01/15] x86/resctrl: Support Privilege Level Zero Association (PLZA) --- commit 0f2aa093b81d7a2e0dc203ce3466562f708898df
Author: Babu Moger <[email protected]>
x86/resctrl: Support Privilege Level Zero Association (PLZA)
This commit adds support for AMD's Privilege Level Zero Association (PLZA)
feature. It detects the feature via CPUID_Fn80000020_EBX_x00 [Bit 9] and
adds the corresponding feature flag to the x86 cpufeatures array.

arch/x86/include/asm/cpufeatures.h line 520

Quoted 9 lines
arch/x86/include/asm/cpufeatures.h +1 -0
index 1b4a48bff18f7..bf6fc71f87fab 100644
@@ -517,6 +517,7 @@
 						      * and purposes if CLEAR_CPU_BUF_VM is set).
 						      */
 #define X86_FEATURE_X2AVIC_EXT		(21*32+20) /* AMD SVM x2AVIC support for 4k vCPUs */
+#define X86_FEATURE_PLZA		(21*32+21) /* Privilege Level Zero Association */

Should this addition also be mirrored in the tools directory copies of cpufeatures.h and kcpuid.csv?
If tools/arch/x86/include/asm/cpufeatures.h is not updated to match, tools like perf can generate build warnings during check-headers.sh verification. Also, without updating tools/arch/x86/kcpuid/cpuid.csv, the kcpuid tool will be unaware of the new PLZA feature bit when users query CPU capabilities.

I thought tools/arch/x86/include/asm/cpufeatures.h would be synced after the changes to arch/x86/include/asm/cpufeatures.h are merged. Has that process changed?

If the expectation is to update tools/arch/x86/include/asm/cpufeatures.h as part of this patch, I can add those changes as well.

Thanks,
Babu

maintainer
#6 lore raw

Re: [RESEND PATCH v4 01/15] x86/resctrl: Support Privilege Level Zero Association (PLZA)

Quoted 56 lines · Babu Moger
Quoted 16 lines
arch/x86/include/asm/cpufeatures.h +1 -0
index 1b4a48bff18f..bf6fc71f87fa 100644
@@ -517,6 +517,7 @@
  						      * and purposes if CLEAR_CPU_BUF_VM is set).
  						      */
  #define X86_FEATURE_X2AVIC_EXT		(21*32+20) /* AMD SVM x2AVIC support for 4k vCPUs */
+#define X86_FEATURE_PLZA		(21*32+21) /* Privilege Level Zero Association */
  /*
   * BUG word(s)
arch/x86/kernel/cpu/scattered.c +0 -0
index 937129ce6a96..1fa4d5aef17e 100644

arch/x86/kernel/cpu/scattered.c static const struct cpuid_bit cpuid_bits[] = { · line 67

Quoted 7 lines
arch/x86/kernel/cpu/scattered.c +1 -0
@@ -61,6 +61,7 @@ static const struct cpuid_bit cpuid_bits[] = {
  	{ X86_FEATURE_BMEC,			CPUID_EBX,  3, 0x80000020, 0 },
  	{ X86_FEATURE_ABMC,			CPUID_EBX,  5, 0x80000020, 0 },
  	{ X86_FEATURE_SDCIAE,			CPUID_EBX,  6, 0x80000020, 0 },
+	{ X86_FEATURE_PLZA,			CPUID_EBX,  9, 0x80000020, 0 },
  	{ X86_FEATURE_TSA_SQ_NO,		CPUID_ECX,  1, 0x80000021, 0 },
  	{ X86_FEATURE_TSA_L1_NO,		CPUID_ECX,  2, 0x80000021, 0 },
  	{ X86_FEATURE_AMD_WORKLOAD_CLASS,	CPUID_EAX, 22, 0x80000021, 0 },

Sashiko reported:

--- Patch [1]: [RESEND PATCH v4 01/15] x86/resctrl: Support Privilege Level Zero Association (PLZA) ---
commit 0f2aa093b81d7a2e0dc203ce3466562f708898df
Author: Babu Moger <[email protected]>
x86/resctrl: Support Privilege Level Zero Association (PLZA) This commit adds support for AMD's Privilege Level Zero Association (PLZA) feature. It detects the feature via CPUID_Fn80000020_EBX_x00 [Bit 9] and adds the corresponding feature flag to the x86 cpufeatures array.

Review

Quoted 1 line
(quoted diff) +0 -0

b/arch/x86/include/asm/cpufeatures.h

arch/x86/include/asm/cpufeatures.h line 519

Quoted 7 lines

index 1b4a48bff18f7..bf6fc71f87fab 100644

arch/x86/include/asm/cpufeatures.h +0 -0
@@ -517,6 +517,7 @@
 						      * and purposes if CLEAR_CPU_BUF_VM is set).
 						      */
 #define X86_FEATURE_X2AVIC_EXT		(21*32+20) /* AMD SVM x2AVIC support for

4k vCPUs */

arch/x86/include/asm/cpufeatures.h line 520

Quoted 1 line
arch/x86/include/asm/cpufeatures.h +1 -0
+#define X86_FEATURE_PLZA		(21*32+21) /* Privilege Level Zero Association

*/
Should this addition also be mirrored in the tools directory copies of cpufeatures.h and kcpuid.csv?
If tools/arch/x86/include/asm/cpufeatures.h is not updated to match, tools like
perf can generate build warnings during check-headers.sh verification. Also, without updating tools/arch/x86/kcpuid/cpuid.csv, the kcpuid tool will be unaware of the new PLZA feature bit when users query CPU capabilities.

Quoted 3 lines

I thought tools/arch/x86/include/asm/cpufeatures.h would be synced after the changes to arch/x86/include/asm/cpufeatures.h are merged. Has that process changed?

I guess that hasn't changed:

tools/include/uapi/README

Let's add those perf tools hackers to confirm.

Quoted 2 lines

If the expectation is to update tools/arch/x86/include/asm/cpufeatures.h as part of this patch, I can add those changes as well.

Signature · 4 lines
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette
#7 lore raw

Re: [RESEND PATCH v4 01/15] x86/resctrl: Support Privilege Level Zero Association (PLZA)

Hello,

Quoted 61 lines · Borislav Petkov
Quoted 56 lines · Babu Moger
Quoted 16 lines
arch/x86/include/asm/cpufeatures.h +1 -0
index 1b4a48bff18f..bf6fc71f87fa 100644
@@ -517,6 +517,7 @@
  						      * and purposes if CLEAR_CPU_BUF_VM is set).
  						      */
  #define X86_FEATURE_X2AVIC_EXT		(21*32+20) /* AMD SVM x2AVIC support for 4k vCPUs */
+#define X86_FEATURE_PLZA		(21*32+21) /* Privilege Level Zero Association */
  /*
   * BUG word(s)
arch/x86/kernel/cpu/scattered.c +0 -0
index 937129ce6a96..1fa4d5aef17e 100644

arch/x86/kernel/cpu/scattered.c static const struct cpuid_bit cpuid_bits[] = { · line 67

Quoted 7 lines
arch/x86/kernel/cpu/scattered.c +1 -0
@@ -61,6 +61,7 @@ static const struct cpuid_bit cpuid_bits[] = {
  	{ X86_FEATURE_BMEC,			CPUID_EBX,  3, 0x80000020, 0 },
  	{ X86_FEATURE_ABMC,			CPUID_EBX,  5, 0x80000020, 0 },
  	{ X86_FEATURE_SDCIAE,			CPUID_EBX,  6, 0x80000020, 0 },
+	{ X86_FEATURE_PLZA,			CPUID_EBX,  9, 0x80000020, 0 },
  	{ X86_FEATURE_TSA_SQ_NO,		CPUID_ECX,  1, 0x80000021, 0 },
  	{ X86_FEATURE_TSA_L1_NO,		CPUID_ECX,  2, 0x80000021, 0 },
  	{ X86_FEATURE_AMD_WORKLOAD_CLASS,	CPUID_EAX, 22, 0x80000021, 0 },

Sashiko reported:

--- Patch [1]: [RESEND PATCH v4 01/15] x86/resctrl: Support Privilege Level Zero Association (PLZA) ---
commit 0f2aa093b81d7a2e0dc203ce3466562f708898df
Author: Babu Moger <[email protected]>
x86/resctrl: Support Privilege Level Zero Association (PLZA) This commit adds support for AMD's Privilege Level Zero Association (PLZA) feature. It detects the feature via CPUID_Fn80000020_EBX_x00 [Bit 9] and adds the corresponding feature flag to the x86 cpufeatures array.

Review

Quoted 1 line
(quoted diff) +0 -0

b/arch/x86/include/asm/cpufeatures.h

arch/x86/include/asm/cpufeatures.h line 519

Quoted 7 lines

index 1b4a48bff18f7..bf6fc71f87fab 100644

arch/x86/include/asm/cpufeatures.h +0 -0
@@ -517,6 +517,7 @@
 						      * and purposes if CLEAR_CPU_BUF_VM is set).
 						      */
 #define X86_FEATURE_X2AVIC_EXT		(21*32+20) /* AMD SVM x2AVIC support for

4k vCPUs */

arch/x86/include/asm/cpufeatures.h line 520

Quoted 1 line
arch/x86/include/asm/cpufeatures.h +1 -0
+#define X86_FEATURE_PLZA		(21*32+21) /* Privilege Level Zero Association

*/
Should this addition also be mirrored in the tools directory copies of cpufeatures.h and kcpuid.csv?
If tools/arch/x86/include/asm/cpufeatures.h is not updated to match, tools like
perf can generate build warnings during check-headers.sh verification. Also, without updating tools/arch/x86/kcpuid/cpuid.csv, the kcpuid tool will be unaware of the new PLZA feature bit when users query CPU capabilities.

Quoted 3 lines

I thought tools/arch/x86/include/asm/cpufeatures.h would be synced after the changes to arch/x86/include/asm/cpufeatures.h are merged. Has that process changed?

Quoted 5 lines

I guess that hasn't changed:

tools/include/uapi/README

Let's add those perf tools hackers to confirm.

Well.. it's changed as Linus wanted to not update the headers for trivial changes. The script is still there but it's not running automatically. For perf, we used to check ioctl and other user-visible changes for system call tracing. And some headers moved to the tools/perf/trace/beauty/include directory to sync separately.

I think the headers will be sync-ed less frequently. So you may need to update the header for tooling changes manually.

Thanks,
Namhyung

maintainer
#8 lore raw

Re: [RESEND PATCH v4 01/15] x86/resctrl: Support Privilege Level Zero Association (PLZA)

Hey Namhyung,

Quoted 8 lines · Namhyung Kim

Well.. it's changed as Linus wanted to not update the headers for trivial changes. The script is still there but it's not running automatically. For perf, we used to check ioctl and other user-visible changes for system call tracing. And some headers moved to the tools/perf/trace/beauty/include directory to sync separately.

I think the headers will be sync-ed less frequently. So you may need to update the header for tooling changes manually.

I'm reading this as, we should not touch cpufeatures.h in tools/ and let you guys decide when you actually need bits from it? In the sense: only when you really need bits from it, you'll update it and other, unrelated bits which are not needed, can remain different...

Or?

Signature · 4 lines
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette
#9 lore raw

Re: [RESEND PATCH v4 01/15] x86/resctrl: Support Privilege Level Zero Association (PLZA)

Hi Boris,

Quoted 12 lines · Borislav Petkov

Hey Namhyung,

Quoted 8 lines · Namhyung Kim

Well.. it's changed as Linus wanted to not update the headers for trivial changes. The script is still there but it's not running automatically. For perf, we used to check ioctl and other user-visible changes for system call tracing. And some headers moved to the tools/perf/trace/beauty/include directory to sync separately.

I think the headers will be sync-ed less frequently. So you may need to update the header for tooling changes manually.

Quoted 6 lines

I'm reading this as, we should not touch cpufeatures.h in tools/ and let you guys decide when you actually need bits from it? In the sense: only when you really need bits from it, you'll update it and other, unrelated bits which are not needed, can remain different...

Or?

No, it's perfectly fine to update any tooling headers if you need it. It should be up to you whether you update the whole file or just needed bits. Just expect us to do it less frequently. :)

Thanks,
Namhyung

maintainer
#10 lore raw

Re: [RESEND PATCH v4 01/15] x86/resctrl: Support Privilege Level Zero Association (PLZA)

Quoted 3 lines · Namhyung Kim

No, it's perfectly fine to update any tooling headers if you need it. It should be up to you whether you update the whole file or just needed bits. Just expect us to do it less frequently. :)

Right, so my angle was to perhaps update it when we touch it anyway so that you guys don't have to touch it. I don't see a need to update the tools/ cpufeatures.h header when we touch the main one, for example.

And since the goal is not to update the tools/ headers without a concrete reason for tools/'s sake, we should simply leave them out and you guys can pick whatever bits you need, when you need them.

Yeah, I think that makes sense.

Thx.

Signature · 4 lines
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette
maintainer
#11 lore raw

Re: [RESEND PATCH v4 01/15] x86/resctrl: Support Privilege Level Zero Association (PLZA)

In reply to Babu Moger

Hi Babu,

Could you please switch subject prefix to be "x86/cpufeatures:"?

Quoted 11 lines · Babu Moger

Customers have identified an issue while using the QoS resource control feature. If memory bandwidth associated with a CLOSID is aggressively throttled, and a task with that CLOSID moves into kernel mode, the kernel operations are also aggressively throttled. This can stall forward progress and eventually degrade overall system performance.

AMD hardware supports a feature Privilege Level Zero Association (PLZA), which allows the CPU's CLOSID association to be changed during the transition from user mode to kernel mode. This allows the kernel to run using a different CLOSID than user space, which can improve system performance in certain scenarios.

How should user interpret "in certain scenarios"? Could the scenarios be highlighted ... or maybe just drop this since it is already preceded with "can improve system performance".

This description implies that PLZA is a feature that is only related to memory bandwidth allocation where it can be beneficial. As I understand the feature impacts all allocation features concurrently, including cache allocation where it should be used with care?

If the goal is to describe all the feature capabilities then it may be worth a mention of the impact/usage related to monitoring?

Quoted 11 lines

The feature is detected via CPUID_Fn80000020_EBX_x00 [Bit 9]:
Privilege Level Zero Association (PLZA).

The PLZA feature details are documented in [1] available from [2].

[1] AMD64 Zen6 Platform Quality of Service (PQOS) Extensions:

    Publication # 69193 Revision: 1.00, Issue Date: March 2026

Please follow "Ordering of commit tags" found in Documentation/process/maintainer-tip.rst.

Reinette

author reviewer
#12 lore raw

Re: [RESEND PATCH v4 01/15] x86/resctrl: Support Privilege Level Zero Association (PLZA)

Hi Reinette,

Quoted 3 lines · Reinette Chatre

Hi Babu,

Could you please switch subject prefix to be "x86/cpufeatures:"?

Yes.

Quoted 14 lines · Babu Moger
Quoted 11 lines

Customers have identified an issue while using the QoS resource control feature. If memory bandwidth associated with a CLOSID is aggressively throttled, and a task with that CLOSID moves into kernel mode, the kernel operations are also aggressively throttled. This can stall forward progress and eventually degrade overall system performance.

AMD hardware supports a feature Privilege Level Zero Association (PLZA), which allows the CPU's CLOSID association to be changed during the transition from user mode to kernel mode. This allows the kernel to run using a different CLOSID than user space, which can improve system performance in certain scenarios.

Quoted 3 lines

How should user interpret "in certain scenarios"? Could the scenarios be highlighted ... or maybe just drop this since it is already preceded with "can improve system performance".

Will remove "in certain scenarios".

Quoted 5 lines

This description implies that PLZA is a feature that is only related to memory bandwidth allocation where it can be beneficial. As I understand the feature impacts all allocation features concurrently, including cache allocation where it should be used with care?

Yes. Let me add text about CAT.

Quoted 3 lines

If the goal is to describe all the feature capabilities then it may be worth a mention of the impact/usage related to monitoring?

Yes. Need to mention monitoring also.

Quoted 7 lines
Quoted 7 lines

The feature is detected via CPUID_Fn80000020_EBX_x00 [Bit 9]:
Privilege Level Zero Association (PLZA).

The PLZA feature details are documented in [1] available from [2].

Quoted 8 lines
Quoted 5 lines

[1] AMD64 Zen6 Platform Quality of Service (PQOS) Extensions:

     Publication # 69193 Revision: 1.00, Issue Date: March 2026

Please follow "Ordering of commit tags" found in Documentation/process/maintainer-tip.rst.

Yes. Link should be the last one.

Thanks
Babu

author reviewer
#13 lore raw

PATCH RESEND v4 2/15 x86/resctrl: Add PLZA support to command-line options

In reply to Babu Moger

Add a kernel command-line parameter to enable or disable the exposure of the PLZA (Privilege Level Zero Association) feature to resctrl.

This allows administrators to control PLZA visibility at boot time via the rdt= option (e.g. rdt=plza or rdt=!plza).

---
v4: Split the patch 1 from v3 into 2 patches.
This patch contains changes for resctrl subsystem.

---
 Documentation/admin-guide/kernel-parameters.txt | 2 +-
 Documentation/filesystems/resctrl.rst           | 1 +
 arch/x86/kernel/cpu/resctrl/core.c              | 2 ++
 3 files changed, 4 insertions(+), 1 deletion(-)
Documentation/admin-guide/kernel-parameters.txt +1 -1
index b5493a7f8f22..1de27055cb32 100644
@@ -6401,7 +6401,7 @@ Kernel parameters
 	rdt=		[HW,X86,RDT]
 			Turn on/off individual RDT features. List is:
 			cmt, mbmtotal, mbmlocal, l3cat, l3cdp, l2cat, l2cdp,
-			mba, smba, bmec, abmc, sdciae, energy[:guid],
+			mba, smba, bmec, abmc, sdciae, plza, energy[:guid],
 			perf[:guid].
 			E.g. to turn on cmt and turn off mba use:
 				rdt=cmt,!mba
Documentation/filesystems/resctrl.rst +1 -0
index e4b66af55ffb..f3e941404967 100644
@@ -28,6 +28,7 @@ SMBA (Slow Memory Bandwidth Allocation)				""
 BMEC (Bandwidth Monitoring Event Configuration)			""
 ABMC (Assignable Bandwidth Monitoring Counters)			""
 SDCIAE (Smart Data Cache Injection Allocation Enforcement)	""
+PLZA (Privilege Level Zero Association)				""
 =============================================================== ================================
 
 Historically, new features were made visible by default in /proc/cpuinfo. This
arch/x86/kernel/cpu/resctrl/core.c +2 -0
index f452e8ce4cef..27e09cded829 100644
@@ -803,6 +803,7 @@ enum {
 	RDT_FLAG_BMEC,
 	RDT_FLAG_ABMC,
 	RDT_FLAG_SDCIAE,
+	RDT_FLAG_PLZA,
 };
 
 #define RDT_OPT(idx, n, f)	\
@@ -830,6 +831,7 @@ static struct rdt_options rdt_options[]  __ro_after_init = {
 	RDT_OPT(RDT_FLAG_BMEC,	    "bmec",	X86_FEATURE_BMEC),
 	RDT_OPT(RDT_FLAG_ABMC,	    "abmc",	X86_FEATURE_ABMC),
 	RDT_OPT(RDT_FLAG_SDCIAE,    "sdciae",	X86_FEATURE_SDCIAE),
+	RDT_OPT(RDT_FLAG_PLZA,	    "plza",	X86_FEATURE_PLZA),
 };
 #define NUM_RDT_OPTIONS ARRAY_SIZE(rdt_options)
 
Signature · 1 line
2.43.0
author reviewer
#14 lore raw

Re: [RESEND PATCH v4 02/15] x86/resctrl: Add PLZA support to command-line options

Quoted 54 lines · Babu Moger

Add a kernel command-line parameter to enable or disable the exposure of the PLZA (Privilege Level Zero Association) feature to resctrl.

This allows administrators to control PLZA visibility at boot time via the rdt= option (e.g. rdt=plza or rdt=!plza).

---
v4: Split the patch 1 from v3 into 2 patches.
This patch contains changes for resctrl subsystem.

---
  Documentation/admin-guide/kernel-parameters.txt | 2 +-
  Documentation/filesystems/resctrl.rst           | 1 +
  arch/x86/kernel/cpu/resctrl/core.c              | 2 ++
  3 files changed, 4 insertions(+), 1 deletion(-)
Documentation/admin-guide/kernel-parameters.txt +1 -1
index b5493a7f8f22..1de27055cb32 100644
@@ -6401,7 +6401,7 @@ Kernel parameters
  	rdt=		[HW,X86,RDT]
  			Turn on/off individual RDT features. List is:
  			cmt, mbmtotal, mbmlocal, l3cat, l3cdp, l2cat, l2cdp,
-			mba, smba, bmec, abmc, sdciae, energy[:guid],
+			mba, smba, bmec, abmc, sdciae, plza, energy[:guid],
  			perf[:guid].
  			E.g. to turn on cmt and turn off mba use:
  				rdt=cmt,!mba
Documentation/filesystems/resctrl.rst +1 -0
index e4b66af55ffb..f3e941404967 100644
@@ -28,6 +28,7 @@ SMBA (Slow Memory Bandwidth Allocation)				""
  BMEC (Bandwidth Monitoring Event Configuration)			""
  ABMC (Assignable Bandwidth Monitoring Counters)			""
  SDCIAE (Smart Data Cache Injection Allocation Enforcement)	""
+PLZA (Privilege Level Zero Association)				""
  =============================================================== ================================
 
  Historically, new features were made visible by default in /proc/cpuinfo. This
arch/x86/kernel/cpu/resctrl/core.c +1 -0
index f452e8ce4cef..27e09cded829 100644
@@ -803,6 +803,7 @@ enum {
  	RDT_FLAG_BMEC,
  	RDT_FLAG_ABMC,
  	RDT_FLAG_SDCIAE,
+	RDT_FLAG_PLZA,
  };
 
  #define RDT_OPT(idx, n, f)	\

arch/x86/kernel/cpu/resctrl/core.c static struct rdt_options rdt_options[] __ro_after_init = { · line 837

Quoted 7 lines
arch/x86/kernel/cpu/resctrl/core.c +1 -0
@@ -830,6 +831,7 @@ static struct rdt_options rdt_options[]  __ro_after_init = {
  	RDT_OPT(RDT_FLAG_BMEC,	    "bmec",	X86_FEATURE_BMEC),
  	RDT_OPT(RDT_FLAG_ABMC,	    "abmc",	X86_FEATURE_ABMC),
  	RDT_OPT(RDT_FLAG_SDCIAE,    "sdciae",	X86_FEATURE_SDCIAE),
+	RDT_OPT(RDT_FLAG_PLZA,	    "plza",	X86_FEATURE_PLZA),
  };
  #define NUM_RDT_OPTIONS ARRAY_SIZE(rdt_options)
 

Sashiko reported:

https://sashiko.dev/#/patchset/cover.1783461016.git.babu.moger%40amd.com?part=2
===================================================================
Is X86_FEATURE_PLZA actually evaluated anywhere in the resctrl subsystem? The commit message indicates this allows administrators to control PLZA visibility, but it appears there are no checks for this flag (e.g., using rdt_cpu_has(X86_FEATURE_PLZA)) in this patch or within the subsystem initialization logic to act on the administrator's input.
Does this implementation actually configure the hardware and expose the feature, or is there a missing patch in this series that evaluates this flag?
======================================================================

This flag is passed to rdt_set_options and can be enabled or disabled using the rdt= boot parameter.

This comment can be ignored.

Thanks
Babu

maintainer
#15 lore raw

Re: [RESEND PATCH v4 02/15] x86/resctrl: Add PLZA support to command-line options

In reply to Babu Moger

Hi Babu,

Quoted 5 lines · Babu Moger

Add a kernel command-line parameter to enable or disable the exposure of the PLZA (Privilege Level Zero Association) feature to resctrl.

This allows administrators to control PLZA visibility at boot time via the rdt= option (e.g. rdt=plza or rdt=!plza).

nit: Since this provides examples of the only two supported usages it may be helpful to make clear when these options are required since users should not need to always boot with rdt=plza to use this feature.

Reinette

author reviewer
#16 lore raw

Re: [RESEND PATCH v4 02/15] x86/resctrl: Add PLZA support to command-line options

Hi Reinette,

Quoted 6 lines · Reinette Chatre

Hi Babu,

Quoted 3 lines · Babu Moger

Add a kernel command-line parameter to enable or disable the exposure of the PLZA (Privilege Level Zero Association) feature to resctrl.

Quoted 7 lines
Quoted 2 lines

This allows administrators to control PLZA visibility at boot time via the rdt= option (e.g. rdt=plza or rdt=!plza).

nit: Since this provides examples of the only two supported usages it may be helpful to make clear when these options are required since users should not need to always boot with rdt=plza to use this feature.

Will add text:

On systems that support PLZA, resctrl exposes kernel-mode PLZA control by default without requiring any explicit rdt= option. The rdt=!plza parameter can be used to disable PLZA exposure to resctrl, while rdt=plza explicitly enables it.

Thanks
Babu

author reviewer
#17 lore raw

PATCH RESEND v4 3/15 x86/resctrl: Add data structures and definitions for PLZA configuration

In reply to Babu Moger

Privilege Level Zero Association (PLZA) allows the kernel to use a different CLOSID (and optionally RMID) than user mode on entry to kernel mode. The CLOSID/RMID association is programmed per CPU via MSR_IA32_PQR_PLZA_ASSOC (0xc00003fc), using RMID/CLOSID values and their respective enable bits.

Add the MSR definition and union msr_pqr_plza_assoc to represent the MSR bitfield layout used by subsequent PLZA programming.

---
v4: Re-wrote the changelog and code comment.

v3: No code changes. Patch order changed. Improved changelog.

v2: No changes. Just rebasing on top of the latest tip branch.

---
 arch/x86/include/asm/msr-index.h       |  1 +
 arch/x86/kernel/cpu/resctrl/internal.h | 37 ++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)
arch/x86/include/asm/msr-index.h +1 -0
index 18c4be75e927..2503451a95fe 100644
@@ -1292,6 +1292,7 @@
 /* - AMD: */
 #define MSR_IA32_MBA_BW_BASE		0xc0000200
 #define MSR_IA32_SMBA_BW_BASE		0xc0000280
+#define MSR_IA32_PQR_PLZA_ASSOC		0xc00003fc
 #define MSR_IA32_L3_QOS_ABMC_CFG	0xc00003fd
 #define MSR_IA32_L3_QOS_EXT_CFG		0xc00003ff
 #define MSR_IA32_EVT_CFG_BASE		0xc0000400
arch/x86/kernel/cpu/resctrl/internal.h +37 -0
index e3cfa0c10e92..020ebc2c8a1f 100644
@@ -222,6 +222,43 @@ union l3_qos_abmc_cfg {
 	unsigned long full;
 };
 
+/*
+ * Privilege Level Zero Association (PLZA) is configured by writing to
+ * MSR_IA32_PQR_PLZA_ASSOC. The MSR must be programmed on every CPU in
+ * the QoS domain. Each domain supports only one PLZA CLOSID and/or RMID
+ * association. All fields other than PLZA_EN must hold the same value
+ * across the domain for consistent operation.
+ *
+ * When PLZA_EN is set, the CLOSID/RMID association used at CPL 0 is
+ * taken from MSR_IA32_PQR_PLZA_ASSOC instead of MSR_IA32_PQR_ASSOC.
+ *
+ * @rmid		: RMID associated with PLZA.
+ * @reserved1		: Reserved.
+ * @rmid_en		: Enable RMID association for PLZA.
+ * @closid		: CLOSID associated with PLZA.
+ * @reserved2		: Reserved.
+ * @closid_en		: Enable CLOSID association for PLZA.
+ * @reserved3		: Reserved.
+ * @plza_en		: Enable PLZA. When enabled, PLZA applies to the
+ *			  given CPU. When PLZA is disabled for a CPU, the
+ *			  CLOSID and RMID association defined in the
+ *			  PQR_ASSOC MSR applies, regardless of the CPU's
+ *			  privilege level.
+ */
+union msr_pqr_plza_assoc {
+	struct {
+		unsigned long rmid	:12,
+			      reserved1	:19,
+			      rmid_en	: 1,
+			      closid	: 4,
+			      reserved2	:11,
+			      closid_en	: 1,
+			      reserved3	:15,
+			      plza_en	: 1;
+	} split;
+	unsigned long full;
+};
+
 void rdt_ctrl_update(void *arg);
 
 int rdt_get_l3_mon_config(struct rdt_resource *r);
Signature · 1 line
2.43.0
author reviewer
#18 lore raw

Re: [RESEND PATCH v4 03/15] x86/resctrl: Add data structures and definitions for PLZA configuration

Quoted 68 lines · Babu Moger

Privilege Level Zero Association (PLZA) allows the kernel to use a different CLOSID (and optionally RMID) than user mode on entry to kernel mode. The CLOSID/RMID association is programmed per CPU via MSR_IA32_PQR_PLZA_ASSOC (0xc00003fc), using RMID/CLOSID values and their respective enable bits.

Add the MSR definition and union msr_pqr_plza_assoc to represent the MSR bitfield layout used by subsequent PLZA programming.

---
v4: Re-wrote the changelog and code comment.

v3: No code changes. Patch order changed. Improved changelog.

v2: No changes. Just rebasing on top of the latest tip branch.

---
  arch/x86/include/asm/msr-index.h       |  1 +
  arch/x86/kernel/cpu/resctrl/internal.h | 37 ++++++++++++++++++++++++++
  2 files changed, 38 insertions(+)
arch/x86/include/asm/msr-index.h +1 -0
index 18c4be75e927..2503451a95fe 100644
@@ -1292,6 +1292,7 @@
  /* - AMD: */
  #define MSR_IA32_MBA_BW_BASE		0xc0000200
  #define MSR_IA32_SMBA_BW_BASE		0xc0000280
+#define MSR_IA32_PQR_PLZA_ASSOC		0xc00003fc
  #define MSR_IA32_L3_QOS_ABMC_CFG	0xc00003fd
  #define MSR_IA32_L3_QOS_EXT_CFG		0xc00003ff
  #define MSR_IA32_EVT_CFG_BASE		0xc0000400
arch/x86/kernel/cpu/resctrl/internal.h +27 -0
index e3cfa0c10e92..020ebc2c8a1f 100644
@@ -222,6 +222,43 @@ union l3_qos_abmc_cfg {
  	unsigned long full;
  };
 
+/*
+ * Privilege Level Zero Association (PLZA) is configured by writing to
+ * MSR_IA32_PQR_PLZA_ASSOC. The MSR must be programmed on every CPU in
+ * the QoS domain. Each domain supports only one PLZA CLOSID and/or RMID
+ * association. All fields other than PLZA_EN must hold the same value
+ * across the domain for consistent operation.
+ *
+ * When PLZA_EN is set, the CLOSID/RMID association used at CPL 0 is
+ * taken from MSR_IA32_PQR_PLZA_ASSOC instead of MSR_IA32_PQR_ASSOC.
+ *
+ * @rmid		: RMID associated with PLZA.
+ * @reserved1		: Reserved.
+ * @rmid_en		: Enable RMID association for PLZA.
+ * @closid		: CLOSID associated with PLZA.
+ * @reserved2		: Reserved.
+ * @closid_en		: Enable CLOSID association for PLZA.
+ * @reserved3		: Reserved.
+ * @plza_en		: Enable PLZA. When enabled, PLZA applies to the
+ *			  given CPU. When PLZA is disabled for a CPU, the
+ *			  CLOSID and RMID association defined in the
+ *			  PQR_ASSOC MSR applies, regardless of the CPU's
+ *			  privilege level.
+ */
+union msr_pqr_plza_assoc {
+	struct {
+		unsigned long rmid	:12,
+			      reserved1	:19,

arch/x86/kernel/cpu/resctrl/internal.h union l3_qos_abmc_cfg { · line 261

Quoted 10 lines
arch/x86/kernel/cpu/resctrl/internal.h +10 -0
+			      rmid_en	: 1,
+			      closid	: 4,
+			      reserved2	:11,
+			      closid_en	: 1,
+			      reserved3	:15,
+			      plza_en	: 1;
+	} split;
+	unsigned long full;
+};
+

Sashiko reported:

https://sashiko.dev/#/patchset/cover.1783461016.git.babu.moger%40amd.com?part=3

Quoted 2 lines

This is a pre-existing issue, but does this union truncate data on 32-> bit x86 builds? On 32-bit kernels, unsigned long is 32 bits, but the bitfields sum to 64 bits.

Will change the union to use 'u64' type for 'unsigned long'.

It also reported problem with "l3_qos_abmc_cfg".

Will fix that as well.

thanks
Babu

maintainer
#19 lore raw

Re: [RESEND PATCH v4 03/15] x86/resctrl: Add data structures and definitions for PLZA configuration

In reply to Babu Moger

Hi Babu,

Quoted 3 lines · Babu Moger

Privilege Level Zero Association (PLZA) allows the kernel to use a different CLOSID (and optionally RMID) than user mode on entry to kernel mode. The CLOSID/RMID association is programmed per CPU via

CLOSID is also optional, no? I am not able to recall now why this is not made optional in this implementation though. Could you please remind me and add it to the changelog for next time?

Quoted 49 lines

MSR_IA32_PQR_PLZA_ASSOC (0xc00003fc), using RMID/CLOSID values and their respective enable bits.

Add the MSR definition and union msr_pqr_plza_assoc to represent the MSR bitfield layout used by subsequent PLZA programming.

---
v4: Re-wrote the changelog and code comment.

v3: No code changes. Patch order changed. Improved changelog.

v2: No changes. Just rebasing on top of the latest tip branch.

---
 arch/x86/include/asm/msr-index.h       |  1 +
 arch/x86/kernel/cpu/resctrl/internal.h | 37 ++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)
arch/x86/include/asm/msr-index.h +1 -0
index 18c4be75e927..2503451a95fe 100644
@@ -1292,6 +1292,7 @@
 /* - AMD: */
 #define MSR_IA32_MBA_BW_BASE		0xc0000200
 #define MSR_IA32_SMBA_BW_BASE		0xc0000280
+#define MSR_IA32_PQR_PLZA_ASSOC		0xc00003fc
 #define MSR_IA32_L3_QOS_ABMC_CFG	0xc00003fd
 #define MSR_IA32_L3_QOS_EXT_CFG		0xc00003ff
 #define MSR_IA32_EVT_CFG_BASE		0xc0000400
arch/x86/kernel/cpu/resctrl/internal.h +11 -0
index e3cfa0c10e92..020ebc2c8a1f 100644
@@ -222,6 +222,43 @@ union l3_qos_abmc_cfg {
 	unsigned long full;
 };
 
+/*
+ * Privilege Level Zero Association (PLZA) is configured by writing to
+ * MSR_IA32_PQR_PLZA_ASSOC. The MSR must be programmed on every CPU in
+ * the QoS domain. Each domain supports only one PLZA CLOSID and/or RMID
+ * association. All fields other than PLZA_EN must hold the same value
+ * across the domain for consistent operation.
+ *
+ * When PLZA_EN is set, the CLOSID/RMID association used at CPL 0 is
+ * taken from MSR_IA32_PQR_PLZA_ASSOC instead of MSR_IA32_PQR_ASSOC.
+ *
+ * @rmid		: RMID associated with PLZA.

arch/x86/kernel/cpu/resctrl/internal.h union l3_qos_abmc_cfg { · line 245

Quoted 10 lines
arch/x86/kernel/cpu/resctrl/internal.h +10 -0
+ * @reserved1		: Reserved.
+ * @rmid_en		: Enable RMID association for PLZA.
+ * @closid		: CLOSID associated with PLZA.
+ * @reserved2		: Reserved.
+ * @closid_en		: Enable CLOSID association for PLZA.
+ * @reserved3		: Reserved.
+ * @plza_en		: Enable PLZA. When enabled, PLZA applies to the
+ *			  given CPU. When PLZA is disabled for a CPU, the
+ *			  CLOSID and RMID association defined in the
+ *			  PQR_ASSOC MSR applies, regardless of the CPU's

To support grep: "the PQR_ASSOC MSR" -> "MSR_IA32_PQR_ASSOC"

arch/x86/kernel/cpu/resctrl/internal.h union l3_qos_abmc_cfg { · line 246

Quoted 1 line
arch/x86/kernel/cpu/resctrl/internal.h +1 -0
+ *			  privilege level.

Could this also please highlight the relationship between plza_en, rmid_en, and closid_en? For example, if I understand correctly, when "rmid_en" is 0 then RMID is taken from MSR_IA32_PQR_ASSOC, similarly, when "closid_en" is 0 then CLOSID is taken from MSR_IA32_PQR_ASSOC. Thus, plza_en could be 1, but if both "rmid_en" and "closid_en" are 0 then, the same behavior results as described for plza_en == 0: "CLOSID and RMID association defined in MSR_IA32_PQR_ASSOC applies, regardless of the CPU's privilege level".

Quoted 8 lines
arch/x86/kernel/cpu/resctrl/internal.h +8 -0
+ */
+union msr_pqr_plza_assoc {
+	struct {
+		unsigned long rmid	:12,
+			      reserved1	:19,
+			      rmid_en	: 1,
+			      closid	: 4,
+			      reserved2	:11,

arch/x86/kernel/cpu/resctrl/internal.h union l3_qos_abmc_cfg { · line 264

Quoted 10 lines
arch/x86/kernel/cpu/resctrl/internal.h +7 -0
+			      closid_en	: 1,
+			      reserved3	:15,
+			      plza_en	: 1;
+	} split;
+	unsigned long full;
+};
+
 void rdt_ctrl_update(void *arg);
 
 int rdt_get_l3_mon_config(struct rdt_resource *r);

Reinette

author reviewer
#20 lore raw

Re: [RESEND PATCH v4 03/15] x86/resctrl: Add data structures and definitions for PLZA configuration

Hi Reinette,

Quoted 10 lines · Reinette Chatre

Hi Babu,

Quoted 3 lines · Babu Moger

Privilege Level Zero Association (PLZA) allows the kernel to use a different CLOSID (and optionally RMID) than user mode on entry to kernel mode. The CLOSID/RMID association is programmed per CPU via

CLOSID is also optional, no? I am not able to recall now why this is not made optional in this implementation though. Could you please remind me and add it to the changelog for next time?

Yes, CLOSID is optional as well. Since PLZA was primarily focused on allocation, I hadn't considered that use case initially. However, there may be scenarios where a user wants to monitor kernel activity without affecting or changing the existing allocation configuration. That would introduce an additional operating mode(See below).

INHERIT_CTRL_AND_MON:
Kernel work inherits the allocation and monitoring from the user space task. On x86 this means that kernel work shares the same CLOSID and RMID as the user space task. This matches today's resctrl behavior.

GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU:
Kernel work uses a globally assigned allocation while monitoring is inherited from the user space task. On x86 this means a CLOSID is assigned for kernel work and the RMID is inherited from the user space task. Default scope is all online CPUs; a subset may be selected via the resctrl group interface. A CTRL_MON group is bound to this mode.

GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU:
Kernel work uses globally assigned allocation and monitoring. On x86 this means both CLOSID and RMID are assigned for kernel work. Default scope is all online CPUs; a subset may be selected via the resctrl group interface. A CTRL_MON or MON group is bound to this mode.

GLOBAL_INHERIT_CTRL_ASSIGN_MON_PER_CPU: <--- New mode
Kernel work inherits the allocation from user task and monitoring is globally assigned for kernel work. On x86 this means that kernel work shares the same CLOSID as user task and kernel work user globally assigned RMID. A MON group is bound to this mode.

I will add these changes.

Quoted 54 lines
Quoted 54 lines

MSR_IA32_PQR_PLZA_ASSOC (0xc00003fc), using RMID/CLOSID values and their respective enable bits.

Add the MSR definition and union msr_pqr_plza_assoc to represent the MSR bitfield layout used by subsequent PLZA programming.

---
v4: Re-wrote the changelog and code comment.

v3: No code changes. Patch order changed. Improved changelog.

v2: No changes. Just rebasing on top of the latest tip branch.

---
  arch/x86/include/asm/msr-index.h       |  1 +
  arch/x86/kernel/cpu/resctrl/internal.h | 37 ++++++++++++++++++++++++++
  2 files changed, 38 insertions(+)
arch/x86/include/asm/msr-index.h +1 -0
index 18c4be75e927..2503451a95fe 100644
@@ -1292,6 +1292,7 @@
  /* - AMD: */
  #define MSR_IA32_MBA_BW_BASE		0xc0000200
  #define MSR_IA32_SMBA_BW_BASE		0xc0000280
+#define MSR_IA32_PQR_PLZA_ASSOC		0xc00003fc
  #define MSR_IA32_L3_QOS_ABMC_CFG	0xc00003fd
  #define MSR_IA32_L3_QOS_EXT_CFG		0xc00003ff
  #define MSR_IA32_EVT_CFG_BASE		0xc0000400
arch/x86/kernel/cpu/resctrl/internal.h +15 -0
index e3cfa0c10e92..020ebc2c8a1f 100644
@@ -222,6 +222,43 @@ union l3_qos_abmc_cfg {
  	unsigned long full;
  };
 
+/*
+ * Privilege Level Zero Association (PLZA) is configured by writing to
+ * MSR_IA32_PQR_PLZA_ASSOC. The MSR must be programmed on every CPU in
+ * the QoS domain. Each domain supports only one PLZA CLOSID and/or RMID
+ * association. All fields other than PLZA_EN must hold the same value
+ * across the domain for consistent operation.
+ *
+ * When PLZA_EN is set, the CLOSID/RMID association used at CPL 0 is
+ * taken from MSR_IA32_PQR_PLZA_ASSOC instead of MSR_IA32_PQR_ASSOC.
+ *
+ * @rmid		: RMID associated with PLZA.
+ * @reserved1		: Reserved.
+ * @rmid_en		: Enable RMID association for PLZA.
+ * @closid		: CLOSID associated with PLZA.
+ * @reserved2		: Reserved.
Quoted 8 lines

arch/x86/kernel/cpu/resctrl/internal.h union l3_qos_abmc_cfg { · line 245

Quoted 6 lines
arch/x86/kernel/cpu/resctrl/internal.h +6 -0
+ * @closid_en		: Enable CLOSID association for PLZA.
+ * @reserved3		: Reserved.
+ * @plza_en		: Enable PLZA. When enabled, PLZA applies to the
+ *			  given CPU. When PLZA is disabled for a CPU, the
+ *			  CLOSID and RMID association defined in the
+ *			  PQR_ASSOC MSR applies, regardless of the CPU's

To support grep: "the PQR_ASSOC MSR" -> "MSR_IA32_PQR_ASSOC"

Sure.

Quoted 10 lines

arch/x86/kernel/cpu/resctrl/internal.h union l3_qos_abmc_cfg { · line 246

Quoted 2 lines
arch/x86/kernel/cpu/resctrl/internal.h +1 -0
+ *			  privilege level.

Could this also please highlight the relationship between plza_en, rmid_en, and closid_en? For example, if I understand correctly, when "rmid_en" is 0 then RMID is taken from MSR_IA32_PQR_ASSOC, similarly, when "closid_en" is 0 then CLOSID is taken from MSR_IA32_PQR_ASSOC. Thus, plza_en could be 1, but if both "rmid_en" and "closid_en" are 0 then, the same behavior results as described for plza_en == 0: "CLOSID and RMID association defined in MSR_IA32_PQR_ASSOC applies, regardless of the CPU's privilege level".

Sure. Will add that note as well.

Thanks
Babu

maintainer
#21 lore raw

Re: [RESEND PATCH v4 03/15] x86/resctrl: Add data structures and definitions for PLZA configuration

Hi Babu,

Quoted 11 lines · Babu Moger
Quoted 8 lines · Reinette Chatre
Quoted 3 lines · Babu Moger

Privilege Level Zero Association (PLZA) allows the kernel to use a different CLOSID (and optionally RMID) than user mode on entry to kernel mode. The CLOSID/RMID association is programmed per CPU via

CLOSID is also optional, no? I am not able to recall now why this is not made optional in this implementation though. Could you please remind me and add it to the changelog for next time?

Quoted 5 lines

Yes, CLOSID is optional as well. Since PLZA was primarily focused on allocation, I hadn't considered that use case initially. However, there may be scenarios where a user wants to monitor kernel activity without affecting or changing the existing allocation configuration. That would introduce an additional operating mode(See below).

ok.

I think doing so will simplify supporting the different modes across systems that may not support allocation or monitoring.

Quoted 18 lines

INHERIT_CTRL_AND_MON:
Kernel work inherits the allocation and monitoring from the user space task. On x86 this means that kernel work shares the same CLOSID and RMID as the user space task. This matches today's resctrl behavior.

GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU:
Kernel work uses a globally assigned allocation while monitoring is inherited from the user space task. On x86 this means a CLOSID is assigned for kernel work and the RMID is inherited from the user space task. Default scope is all online CPUs; a subset may be selected via the resctrl group interface. A CTRL_MON group is bound to this mode.

GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU:
Kernel work uses globally assigned allocation and monitoring. On x86 this means both CLOSID and RMID are assigned for kernel work. Default scope is all online CPUs; a subset may be selected via the resctrl group interface. A CTRL_MON or MON group is bound to this mode.

Quoted 5 lines

GLOBAL_INHERIT_CTRL_ASSIGN_MON_PER_CPU:   <--- New mode Kernel work inherits the allocation from user task and monitoring is globally assigned for kernel work. On x86 this means that kernel work shares the same CLOSID as user task and kernel work user globally assigned RMID. A MON group is bound to this mode.

I provided comments about this text in following patch. Apart from that, I think a CTRL_MON or MON group could be assigned to this mode?

Thank you.

Reinette

#22 lore raw

Re: [RESEND PATCH v4 03/15] x86/resctrl: Add data structures and definitions for PLZA configuration

Hi Reinette,

Quoted 20 lines · Reinette Chatre

Hi Babu,

Quoted 11 lines · Babu Moger
Quoted 8 lines · Reinette Chatre
Quoted 3 lines · Babu Moger

Privilege Level Zero Association (PLZA) allows the kernel to use a different CLOSID (and optionally RMID) than user mode on entry to kernel mode. The CLOSID/RMID association is programmed per CPU via

CLOSID is also optional, no? I am not able to recall now why this is not made optional in this implementation though. Could you please remind me and add it to the changelog for next time?

Quoted 5 lines

Yes, CLOSID is optional as well. Since PLZA was primarily focused on allocation, I hadn't considered that use case initially. However, there may be scenarios where a user wants to monitor kernel activity without affecting or changing the existing allocation configuration. That would introduce an additional operating mode(See below).

Quoted 4 lines

ok.

I think doing so will simplify supporting the different modes across systems that may not support allocation or monitoring.

Ack.

Quoted 18 lines
Quoted 18 lines

INHERIT_CTRL_AND_MON:
Kernel work inherits the allocation and monitoring from the user space task. On x86 this means that kernel work shares the same CLOSID and RMID as the user space task. This matches today's resctrl behavior.

GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU:
Kernel work uses a globally assigned allocation while monitoring is inherited from the user space task. On x86 this means a CLOSID is assigned for kernel work and the RMID is inherited from the user space task. Default scope is all online CPUs; a subset may be selected via the resctrl group interface. A CTRL_MON group is bound to this mode.

GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU:
Kernel work uses globally assigned allocation and monitoring. On x86 this means both CLOSID and RMID are assigned for kernel work. Default scope is all online CPUs; a subset may be selected via the resctrl group interface. A CTRL_MON or MON group is bound to this mode.

Quoted 9 lines
Quoted 5 lines

GLOBAL_INHERIT_CTRL_ASSIGN_MON_PER_CPU:   <--- New mode Kernel work inherits the allocation from user task and monitoring is globally assigned for kernel work. On x86 this means that kernel work shares the same CLOSID as user task and kernel work user globally assigned RMID. A MON group is bound to this mode.

I provided comments about this text in following patch. Apart from that, I think a CTRL_MON or MON group could be assigned to this mode?

Yes. It can be CTRL_MON or MON group.

thanks
Babu

author reviewer
#23 lore raw

PATCH RESEND v4 4/15 fs/resctrl: Introduce kernel mode (kmode) data structures

In reply to Babu Moger

Kernel-mode traffic can use a different allocation and monitoring context than the originating user task. On x86, Privilege Level Zero Association (PLZA) enables the kernel to switch to a different CLOSID (and optionally RMID) when entering kernel mode.

Architectures need a common way to name kernel-mode policies before resctrl can report what is active or what the platform supports.

Introduce enum resctrl_kernel_mode:
- INHERIT_CTRL_AND_MON: Kernel work inherits allocation and monitoring from the user task (current behavior).
- GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU: Assign allocation for kernel work; inherit monitoring from the user task.
- GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU: Assign a dedicated allocation and monitoring for kernel work.

---
v4: Updated the changelog to be generic as possible.
Moved the enum resctrl_kernel_mode to include/linux/resctrl.h. Updated the code comments to be generic.
Removed resctrl_kmode_cfg from the code. This definition can be fs specific only and architectures dont need to know. Changed enum name to resctrl_kernel_mode from resctrl_kernel_modes.

v3: Removed resctrl_kmode definition.
Changed the kernel mode definitions to enum resctrl_kernel_modes. Used BIT() to set/test the features.
Added details to changelog.

v2: New patch to handle PLZA interfaces with /sys/fs/resctrl/info/ directory.

    https://lore.kernel.org/lkml/[email protected]/
---
 include/linux/resctrl.h | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)
include/linux/resctrl.h +31 -0
index 73ff522448a0..c7abed51cd5f 100644
@@ -703,6 +703,37 @@ int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable);
  */
 bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r);
 
+/**
+ * enum resctrl_kernel_mode - Kernel-mode control and monitor association
+ *			      policy.
+ *
+ * @INHERIT_CTRL_AND_MON:
+ *	Kernel work inherits the allocation and monitoring from the user space
+ *	task. On x86 this means that kernel work shares the same CLOSID and
+ *	RMID as the user space task. This matches today's resctrl behavior.
+ *
+ * @GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU:
+ *	Kernel work uses a globally assigned allocation while monitoring is
+ *	inherited from the user space task. On x86 this means a CLOSID is
+ *	assigned for kernel work and the RMID is inherited from the user space
+ *	task. Default scope is all online CPUs; a subset may be selected via
+ *	the resctrl group interface. A CTRL_MON group is bound to this mode.
+ *
+ * @GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU:
+ *	Kernel work uses globally assigned allocation and monitoring. On x86
+ *	this means both CLOSID and RMID are assigned for kernel work. Default
+ *	scope is all online CPUs; a subset may be selected via the resctrl
+ *	group interface. A CTRL_MON or MON group is bound to this mode.
+ */
+enum resctrl_kernel_mode {
+	INHERIT_CTRL_AND_MON,
+	GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU,
+	GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU,
+	RESCTRL_KMODE_LAST = GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU,
+};
+
+#define RESCTRL_NUM_KERNEL_MODES (RESCTRL_KMODE_LAST + 1)
+
 extern unsigned int resctrl_rmid_realloc_threshold;
 extern unsigned int resctrl_rmid_realloc_limit;
 
Signature · 1 line
2.43.0
author reviewer
#24 lore raw

Re: [RESEND PATCH v4 04/15] fs/resctrl: Introduce kernel mode (kmode) data structures

Quoted 68 lines · Babu Moger

Kernel-mode traffic can use a different allocation and monitoring context than the originating user task. On x86, Privilege Level Zero Association (PLZA) enables the kernel to switch to a different CLOSID (and optionally RMID) when entering kernel mode.

Architectures need a common way to name kernel-mode policies before resctrl can report what is active or what the platform supports.

Introduce enum resctrl_kernel_mode:
- INHERIT_CTRL_AND_MON: Kernel work inherits allocation and monitoring from the user task (current behavior).
- GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU: Assign allocation for kernel work; inherit monitoring from the user task.
- GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU: Assign a dedicated allocation and monitoring for kernel work.

---
v4: Updated the changelog to be generic as possible.
Moved the enum resctrl_kernel_mode to include/linux/resctrl.h. Updated the code comments to be generic.
Removed resctrl_kmode_cfg from the code. This definition can be fs specific only and architectures dont need to know. Changed enum name to resctrl_kernel_mode from resctrl_kernel_modes.

v3: Removed resctrl_kmode definition.
Changed the kernel mode definitions to enum resctrl_kernel_modes. Used BIT() to set/test the features.
Added details to changelog.

v2: New patch to handle PLZA interfaces with /sys/fs/resctrl/info/ directory.

     https://lore.kernel.org/lkml/[email protected]/
---
  include/linux/resctrl.h | 31 +++++++++++++++++++++++++++++++
  1 file changed, 31 insertions(+)
include/linux/resctrl.h +24 -0
index 73ff522448a0..c7abed51cd5f 100644
@@ -703,6 +703,37 @@ int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable);
   */
  bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r);
 
+/**
+ * enum resctrl_kernel_mode - Kernel-mode control and monitor association
+ *			      policy.
+ *
+ * @INHERIT_CTRL_AND_MON:
+ *	Kernel work inherits the allocation and monitoring from the user space
+ *	task. On x86 this means that kernel work shares the same CLOSID and
+ *	RMID as the user space task. This matches today's resctrl behavior.
+ *
+ * @GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU:
+ *	Kernel work uses a globally assigned allocation while monitoring is
+ *	inherited from the user space task. On x86 this means a CLOSID is
+ *	assigned for kernel work and the RMID is inherited from the user space
+ *	task. Default scope is all online CPUs; a subset may be selected via
+ *	the resctrl group interface. A CTRL_MON group is bound to this mode.
+ *
+ * @GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU:
+ *	Kernel work uses globally assigned allocation and monitoring. On x86
+ *	this means both CLOSID and RMID are assigned for kernel work. Default
+ *	scope is all online CPUs; a subset may be selected via the resctrl
+ *	group interface. A CTRL_MON or MON group is bound to this mode.
+ */
+enum resctrl_kernel_mode {
+	INHERIT_CTRL_AND_MON,

include/linux/resctrl.h int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable); · line 739

Quoted 10 lines
include/linux/resctrl.h +7 -0
+	GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU,
+	GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU,
+	RESCTRL_KMODE_LAST = GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU,
+};
+
+#define RESCTRL_NUM_KERNEL_MODES (RESCTRL_KMODE_LAST + 1)
+
  extern unsigned int resctrl_rmid_realloc_threshold;
  extern unsigned int resctrl_rmid_realloc_limit;
 

Sashiko reported:

https://sashiko.dev/#/patchset/cover.1783461016.git.babu.moger%40amd.com?part=4

--- Patch [4]: [RESEND PATCH v4 04/15] fs/resctrl: Introduce kernel mode (kmode) data structures --- commit 1114f46dcb9c990326351e5e6fea6cb114024be3
Author: Babu Moger <[email protected]>
fs/resctrl: Introduce kernel mode (kmode) data structures
This commit introduces the resctrl_kernel_mode enum to define policies for allocating and monitoring contexts for kernel-mode traffic. It enables the
kernel to either inherit contexts from the user task or use globally assigned allocations.

Quoted 4 lines
include/linux/resctrl.h +0 -0
index 73ff522448a02..c7abed51cd5f0 100644

[ ... ]

include/linux/resctrl.h int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable); · line 733

Quoted 6 lines
include/linux/resctrl.h +6 -0
+enum resctrl_kernel_mode {
+	INHERIT_CTRL_AND_MON,
+	GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU,
+	GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU,
+	RESCTRL_KMODE_LAST = GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU,
+};

This isn't a bug, but does this risk polluting the global kernel namespace? The enumerators INHERIT_CTRL_AND_MON, GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU, and GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU are defined in a globally included kernel header without a subsystem-specific prefix.
Should these be prefixed with something like RESCTRL_ (similar to RESCTRL_KMODE_LAST) to prevent potential name collisions with other kernel code?

Yes, agreed. These names need another look. They are quite long, and we should try to shorten them without losing their meaning or context.

I'm looking for suggestions as well.

Can this be something like:

enum sysfs
KMODE_INHERIT_CTRL_MON "inherit_ctrl_mon" KMODE_ASSIGN_CTRL_INHERIT_MON "assign_ctrl_inherit_mon" KMODE_ASSIGN_CTRL_MON "assign_ctrl_mon"

CPU scope is already handled by kmode_cpus.

Thanks
Babu

maintainer
#25 lore raw

Re: [RESEND PATCH v4 04/15] fs/resctrl: Introduce kernel mode (kmode) data structures

In reply to Babu Moger

Hi Babu,

Quoted 6 lines · Babu Moger

Kernel-mode traffic can use a different allocation and monitoring context than the originating user task. On x86, Privilege Level Zero Association (PLZA) enables the kernel to switch to a different CLOSID (and optionally RMID) when entering kernel mode.

Architectures need a common way to name kernel-mode policies before resctrl

Please pick one term and stick with it. While reading through this series I have come across "kernel-mode policies", "kernel-mode binding", "kernel-mode configuration", and "kernel-mode association". Is the distinction even needed? Could all of these just instead be: "kernel mode"?

Quoted 5 lines

can report what is active or what the platform supports.

Introduce enum resctrl_kernel_mode:
- INHERIT_CTRL_AND_MON: Kernel work inherits allocation and monitoring from the user task (current behavior).

The issue with this "combination" mode becomes obvious in patch 7. I also see that sashiko hinted at this issue but I am not able to see from your response what the plan is to address this. As highlighted by patch 7 and sashiko the "allocation" and "monitoring" features of a system are independent - a system need not support/enable both. This should be easy to reproduce by, for example, booting a system with needed rdt= options disabling allocation or monitoring features.

I think it will be unexpected to a user on an allocation-only system to see interface like:

 # cat info/kernel_mode
  [inherit_ctrl_and_mon]
  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
  global_assign_ctrl_assign_mon_per_cpu:group=uninitialized

Should it not rather be, for example:

 # cat info/kernel_mode
  [inherit_ctrl]
  global_assign_ctrl_per_cpu:group=uninitialized

Similarly the user input would not need to provide a monitor group when system only supports allocation.

Quoted 2 lines

- GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU: Assign allocation for kernel work; inherit monitoring from the user task.

I am not able to parse "Assign allocation for kernel work"

Quoted 5 lines

- GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU: Assign a dedicated allocation and monitoring for kernel work.

---

...

Quoted 5 lines
include/linux/resctrl.h +0 -0
index 73ff522448a0..c7abed51cd5f 100644

include/linux/resctrl.h int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable); · line 711

Quoted 9 lines
include/linux/resctrl.h +6 -0
@@ -703,6 +703,37 @@ int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable);
  */
 bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r);
 
+/**
+ * enum resctrl_kernel_mode - Kernel-mode control and monitor association
+ *			      policy.
+ *
+ * @INHERIT_CTRL_AND_MON:
+ *	Kernel work inherits the allocation and monitoring from the user space

"inherits the allocation and monitoring" is very vague. I think it will help to make things clear if this is described as the control and monitor groups being assigned.

include/linux/resctrl.h int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable); · line 713

Quoted 2 lines
include/linux/resctrl.h +2 -0
+ *	task. On x86 this means that kernel work shares the same CLOSID and
+ *	RMID as the user space task. This matches today's resctrl behavior.

"This matches today's resctrl behavior." - This cannot be expected to age well and can be dropped.

include/linux/resctrl.h int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable); · line 717

Quoted 4 lines
include/linux/resctrl.h +4 -0
+ *
+ * @GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU:
+ *	Kernel work uses a globally assigned allocation while monitoring is
+ *	inherited from the user space task. On x86 this means a CLOSID is

(same comment as above)

include/linux/resctrl.h int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable); · line 723

Quoted 6 lines
include/linux/resctrl.h +6 -0
+ *	assigned for kernel work and the RMID is inherited from the user space
+ *	task. Default scope is all online CPUs; a subset may be selected via
+ *	the resctrl group interface. A CTRL_MON group is bound to this mode.
+ *
+ * @GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU:
+ *	Kernel work uses globally assigned allocation and monitoring. On x86

(same comment as above)

include/linux/resctrl.h int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable); · line 732

Quoted 9 lines
include/linux/resctrl.h +9 -0
+ *	this means both CLOSID and RMID are assigned for kernel work. Default
+ *	scope is all online CPUs; a subset may be selected via the resctrl
+ *	group interface. A CTRL_MON or MON group is bound to this mode.
+ */
+enum resctrl_kernel_mode {
+	INHERIT_CTRL_AND_MON,
+	GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU,
+	GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU,
+	RESCTRL_KMODE_LAST = GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU,

Please drop comma on a terminator line.

include/linux/resctrl.h int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable); · line 739

Quoted 7 lines
include/linux/resctrl.h +4 -0
+};
+
+#define RESCTRL_NUM_KERNEL_MODES (RESCTRL_KMODE_LAST + 1)
+
 extern unsigned int resctrl_rmid_realloc_threshold;
 extern unsigned int resctrl_rmid_realloc_limit;
 

Reinette

#26 lore raw

Re: [RESEND PATCH v4 04/15] fs/resctrl: Introduce kernel mode (kmode) data structures

Hi Reinette,

Quoted 8 lines · Reinette Chatre

Hi Babu,

Quoted 5 lines · Babu Moger

Kernel-mode traffic can use a different allocation and monitoring context than the originating user task. On x86, Privilege Level Zero Association (PLZA) enables the kernel to switch to a different CLOSID (and optionally RMID) when entering kernel mode.

Quoted 6 lines
Quoted 1 line

Architectures need a common way to name kernel-mode policies before resctrl

Please pick one term and stick with it. While reading through this series I have come across "kernel-mode policies", "kernel-mode binding", "kernel-mode configuration", and "kernel-mode association". Is the distinction even needed? Could all of these just instead be: "kernel mode"?

Sure.

Quoted 23 lines
Quoted 6 lines

can report what is active or what the platform supports.

Introduce enum resctrl_kernel_mode:
- INHERIT_CTRL_AND_MON: Kernel work inherits allocation and monitoring from the user task (current behavior).

The issue with this "combination" mode becomes obvious in patch 7. I also see that sashiko hinted at this issue but I am not able to see from your response what the plan is to address this. As highlighted by patch 7 and sashiko the "allocation" and "monitoring" features of a system are independent - a system need not support/enable both. This should be easy to reproduce by, for example, booting a system with needed rdt= options disabling allocation or monitoring features.

I think it will be unexpected to a user on an allocation-only system to see interface like:

  # cat info/kernel_mode
   [inherit_ctrl_and_mon]
   global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
   global_assign_ctrl_assign_mon_per_cpu:group=uninitialized
Quoted 7 lines

Should it not rather be, for example:

  # cat info/kernel_mode
   [inherit_ctrl]
   global_assign_ctrl_per_cpu:group=uninitialized

Similarly the user input would not need to provide a monitor group when system only supports allocation.

Ok. Yea. We need to separate control and monitor separately.

How about something like this?

 # cat info/kernel_mode
   [ctrl=inherit,mon=inherit]
   ctrl=assign,mon=inherit:group=uninitialized
   ctrl=assign,mon=assign:group=uninitialized
   ctrl=inherit,mon=assign:group=uninitialized

If allocation(ctrl) is only supported.

 # cat info/kernel_mode
   [ctrl=inherit]
   ctrl=assign:group=uninitialized

If monitor (mon) is only supported.

 # cat info/kernel_mode
   [mon=inherit]
   mon=assign:group=uninitialized
Quoted 5 lines
Quoted 3 lines

- GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU: Assign allocation for kernel work; inherit monitoring from the user task.

I am not able to parse "Assign allocation for kernel work"

Will change it. Explaining in control and monitor groups terms will be better.

Quoted 18 lines
Quoted 7 lines

- GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU: Assign a dedicated allocation and monitoring for kernel work.

---

...

Quoted 8 lines
include/linux/resctrl.h +0 -0
index 73ff522448a0..c7abed51cd5f 100644
@@ -703,6 +703,37 @@ int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable);
   */
  bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r);
 
Quoted 11 lines

include/linux/resctrl.h int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable); · line 711

Quoted 6 lines
include/linux/resctrl.h +6 -0
+/**
+ * enum resctrl_kernel_mode - Kernel-mode control and monitor association
+ *			      policy.
+ *
+ * @INHERIT_CTRL_AND_MON:
+ *	Kernel work inherits the allocation and monitoring from the user space

"inherits the allocation and monitoring" is very vague. I think it will help to make things clear if this is described as the control and monitor groups being assigned.

Sure.

Quoted 5 lines

include/linux/resctrl.h int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable); · line 713

Quoted 2 lines
include/linux/resctrl.h +2 -0
+ *	task. On x86 this means that kernel work shares the same CLOSID and
+ *	RMID as the user space task. This matches today's resctrl behavior.

"This matches today's resctrl behavior." - This cannot be expected to age well and can be dropped.

Will change.

Quoted 7 lines

include/linux/resctrl.h int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable); · line 717

Quoted 5 lines
include/linux/resctrl.h +4 -0
+ *
+ * @GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU:
+ *	Kernel work uses a globally assigned allocation while monitoring is
+ *	inherited from the user space task. On x86 this means a CLOSID is

(same comment as above)

ack.

Quoted 9 lines

include/linux/resctrl.h int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable); · line 723

Quoted 7 lines
include/linux/resctrl.h +6 -0
+ *	assigned for kernel work and the RMID is inherited from the user space
+ *	task. Default scope is all online CPUs; a subset may be selected via
+ *	the resctrl group interface. A CTRL_MON group is bound to this mode.
+ *
+ * @GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU:
+ *	Kernel work uses globally assigned allocation and monitoring. On x86

(same comment as above)

Ack.

Quoted 12 lines

include/linux/resctrl.h int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable); · line 732

Quoted 10 lines
include/linux/resctrl.h +9 -0
+ *	this means both CLOSID and RMID are assigned for kernel work. Default
+ *	scope is all online CPUs; a subset may be selected via the resctrl
+ *	group interface. A CTRL_MON or MON group is bound to this mode.
+ */
+enum resctrl_kernel_mode {
+	INHERIT_CTRL_AND_MON,
+	GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU,
+	GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU,
+	RESCTRL_KMODE_LAST = GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU,

Please drop comma on a terminator line.

Sure.

Thanks
Babu

maintainer
#27 lore raw

Re: [RESEND PATCH v4 04/15] fs/resctrl: Introduce kernel mode (kmode) data structures

Hi Babu,

Quoted 50 lines · Babu
Quoted 24 lines · Reinette Chatre
Quoted 5 lines · Babu Moger

can report what is active or what the platform supports.

Introduce enum resctrl_kernel_mode:
   - INHERIT_CTRL_AND_MON: Kernel work inherits allocation and monitoring from the user task (current behavior).

The issue with this "combination" mode becomes obvious in patch 7. I also see that sashiko hinted at this issue but I am not able to see from your response what the plan is to address this. As highlighted by patch 7 and sashiko the "allocation" and "monitoring" features of a system are independent - a system need not support/enable both. This should be easy to reproduce by, for example, booting a system with needed rdt= options disabling allocation or monitoring features.

I think it will be unexpected to a user on an allocation-only system to see interface like:

  # cat info/kernel_mode
   [inherit_ctrl_and_mon]
   global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
   global_assign_ctrl_assign_mon_per_cpu:group=uninitialized
Quoted 7 lines

Should it not rather be, for example:

  # cat info/kernel_mode
   [inherit_ctrl]
   global_assign_ctrl_per_cpu:group=uninitialized

Similarly the user input would not need to provide a monitor group when system only supports allocation.

Ok. Yea. We need to separate control and monitor separately.

How about something like this?

 # cat info/kernel_mode
   [ctrl=inherit,mon=inherit]
   ctrl=assign,mon=inherit:group=uninitialized
   ctrl=assign,mon=assign:group=uninitialized
   ctrl=inherit,mon=assign:group=uninitialized

If allocation(ctrl) is only supported.

 # cat info/kernel_mode
   [ctrl=inherit]
   ctrl=assign:group=uninitialized
Quoted 7 lines

If monitor (mon) is only supported.

 # cat info/kernel_mode
   [mon=inherit]
   mon=assign:group=uninitialized

Please always keep in mind all the requirements and use cases we learned about during and after RFC v1 of this work.

For example, we already know that "per group" assignment is something resctrl needs to be ready for. Consider the example in
https://lore.kernel.org/lkml/[email protected]/

There may even be "per task" assignment in the future.

Constraining this feature to PLZA will make it harder to enable the capabilities that we know resctrl need to support in the future.

This is how we originally landed on the "global" assignment distinction
(https://lore.kernel.org/lkml/[email protected]/)
"global assignment" should be kept or replaced with a solution that continues to prepare resctrl for these other capabilities.

I am not able to see how resctrl could support "per group" assignment with the interface you propose above. If I am missing this, please highlight the solution.

resctrl may need to explicitly split kernel mode from kernel mode properties. For example, below shows an "assign_global_enable_per_cpu" as the kernel mode, now with three properties:
- "ctrl" - could be "assign" or "inherit"
- "mon" - could be "assign" or "inherit"
- "group" - required if "ctrl" or "mon" is set to "assign"

   # cat info/kernel_mode
   [inherit]
   assign_global_enable_per_cpu:ctrl=assign;mon=assign;group=uninitialized

When resctrl needs to support "per-group" assignment "kernel_mode" could contain below with supporting documentation noting which per-resource group files will appear when "assign_per_group" is selected that user space can use to manage the assignments.

   # cat info/kernel_mode
   [inherit]
   assign_per_group

I am not asking you to go and implement this. This was just the first idea that came to ming that I am using to highlight that any new proposal needs to keep previous discussions in mind.

Reinette

author reviewer
#28 lore raw

Re: [RESEND PATCH v4 04/15] fs/resctrl: Introduce kernel mode (kmode) data structures

Hi Reinette,

Quoted 61 lines · Reinette Chatre

Hi Babu,

Quoted 50 lines · Babu
Quoted 24 lines · Reinette Chatre
Quoted 5 lines · Babu Moger

can report what is active or what the platform supports.

Introduce enum resctrl_kernel_mode:
   - INHERIT_CTRL_AND_MON: Kernel work inherits allocation and monitoring from the user task (current behavior).

The issue with this "combination" mode becomes obvious in patch 7. I also see that sashiko hinted at this issue but I am not able to see from your response what the plan is to address this. As highlighted by patch 7 and sashiko the "allocation" and "monitoring" features of a system are independent - a system need not support/enable both. This should be easy to reproduce by, for example, booting a system with needed rdt= options disabling allocation or monitoring features.

I think it will be unexpected to a user on an allocation-only system to see interface like:

   # cat info/kernel_mode
    [inherit_ctrl_and_mon]
    global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
    global_assign_ctrl_assign_mon_per_cpu:group=uninitialized
Quoted 7 lines

Should it not rather be, for example:

   # cat info/kernel_mode
    [inherit_ctrl]
    global_assign_ctrl_per_cpu:group=uninitialized

Similarly the user input would not need to provide a monitor group when system only supports allocation.

Ok. Yea. We need to separate control and monitor separately.

How about something like this?

  # cat info/kernel_mode
    [ctrl=inherit,mon=inherit]
    ctrl=assign,mon=inherit:group=uninitialized
    ctrl=assign,mon=assign:group=uninitialized
    ctrl=inherit,mon=assign:group=uninitialized

If allocation(ctrl) is only supported.

  # cat info/kernel_mode
    [ctrl=inherit]
    ctrl=assign:group=uninitialized
Quoted 7 lines

If monitor (mon) is only supported.

  # cat info/kernel_mode
    [mon=inherit]
    mon=assign:group=uninitialized
Quoted 8 lines

Please always keep in mind all the requirements and use cases we learned about during and after RFC v1 of this work.

For example, we already know that "per group" assignment is something resctrl needs to be ready for. Consider the example in
https://lore.kernel.org/lkml/[email protected]/

There may even be "per task" assignment in the future.

Yes. That is correct.

Quoted 8 lines

Constraining this feature to PLZA will make it harder to enable the capabilities that we know resctrl need to support in the future.

This is how we originally landed on the "global" assignment distinction
(https://lore.kernel.org/lkml/[email protected]/)
"global assignment" should be kept or replaced with a solution that continues to prepare resctrl for these other capabilities.

Yes. Makes sense.

Quoted 10 lines

I am not able to see how resctrl could support "per group" assignment with the interface you propose above. If I am missing this, please highlight the solution.

resctrl may need to explicitly split kernel mode from kernel mode properties. For example, below shows an "assign_global_enable_per_cpu" as the kernel mode, now with three properties:
- "ctrl" - could be "assign" or "inherit"
- "mon" - could be "assign" or "inherit"
- "group" - required if "ctrl" or "mon" is set to "assign"

ok.

Quoted 4 lines
    # cat info/kernel_mode
    [inherit]
    assign_global_enable_per_cpu:ctrl=assign;mon=assign;group=uninitialized

Shouldn't this be like below when default is inherit?

# cat info/kernel_mode
[inherit]
assign_global_enable_per_cpu

When the default changes to assign_global_enable_per_cpu:

# cat info/kernel_mode
inherit [assign_global_enable_per_cpu:ctrl=assign;mon=assign;group=ctrl_mon1//]

Display the second mode with properties only when group is associated with it?

# cat info/kernel_mode
inherit
[assign_global_enable_per_cpu:mon=assign;group=ctrl1/mon1/]
Quoted 10 lines

When resctrl needs to support "per-group" assignment "kernel_mode" could contain below with supporting documentation noting which per-resource group files will appear when "assign_per_group" is selected that user space can use to manage the assignments.

    # cat info/kernel_mode
    [inherit]
    assign_per_group

I know it is future. What could be difference between assign_global_enable_per_cpu and assign_per_group?

Thanks

Babu

maintainer
#29 lore raw

Re: [RESEND PATCH v4 04/15] fs/resctrl: Introduce kernel mode (kmode) data structures

Hi Babu,

Quoted 43 lines · Babu Moger
Quoted 8 lines · Reinette Chatre

Please always keep in mind all the requirements and use cases we learned about during and after RFC v1 of this work.

For example, we already know that "per group" assignment is something resctrl needs to be ready for. Consider the example in
https://lore.kernel.org/lkml/[email protected]/

There may even be "per task" assignment in the future.

Yes. That is correct.

Quoted 8 lines

Constraining this feature to PLZA will make it harder to enable the capabilities that we know resctrl need to support in the future.

This is how we originally landed on the "global" assignment distinction
(https://lore.kernel.org/lkml/[email protected]/)
"global assignment" should be kept or replaced with a solution that continues to prepare resctrl for these other capabilities.

Yes. Makes sense.

Quoted 10 lines

I am not able to see how resctrl could support "per group" assignment with the interface you propose above. If I am missing this, please highlight the solution.

resctrl may need to explicitly split kernel mode from kernel mode properties. For example, below shows an "assign_global_enable_per_cpu" as the kernel mode, now with three properties:
- "ctrl" - could be "assign" or "inherit"
- "mon" - could be "assign" or "inherit"
- "group" - required if "ctrl" or "mon" is set to "assign"

ok.

Quoted 4 lines
    # cat info/kernel_mode
    [inherit]
    assign_global_enable_per_cpu:ctrl=assign;mon=assign;group=uninitialized
Quoted 6 lines

Shouldn't this be like below when default is inherit?

# cat info/kernel_mode
[inherit]
assign_global_enable_per_cpu

I think it will be useful to let the interface:
(a) show to user space which properties are available for each supported mode, and
(b) show user space what the default value of those properties will be if they are not set when the associated mode is enabled.

To (b), since the default resource group is used as default when the group is not provided it may be better to use "//" (or just "/", depending on system supporting just one of allocation or monitoring) instead of "uninitialized".

Quoted 7 lines

When the default changes to assign_global_enable_per_cpu:

# cat info/kernel_mode
inherit [assign_global_enable_per_cpu:ctrl=assign;mon=assign;group=ctrl_mon1//]

Display the second mode with properties only when group is associated with it?

Please consider this from user space side. The user needs to enable the mode. How will the user know which properties are available and what the defaults are?

Quoted 12 lines
# cat info/kernel_mode
inherit
[assign_global_enable_per_cpu:mon=assign;group=ctrl1/mon1/]
Quoted 6 lines

When resctrl needs to support "per-group" assignment "kernel_mode" could contain below with supporting documentation noting which per-resource group files will appear when "assign_per_group" is selected that user space can use to manage the assignments.

Quoted 7 lines
Quoted 4 lines
    # cat info/kernel_mode
    [inherit]
    assign_per_group

I know it is future. What could be difference between assign_global_enable_per_cpu and assign_per_group?

Please see https://lore.kernel.org/lkml/[email protected]/

Essentially, in the "assign_per_group" mode the user space resource allocation and monitoring dictates what kernel mode resource allocation and monitoring to use. This cannot support the use case where user wants to monitor all user space and kernel work together in the same monitoring group though, but that is a difficult use case for MPAM anyway and this can be solved by summing monitoring data of user space and kernel groups.

Reinette

author reviewer
#30 lore raw

Re: [RESEND PATCH v4 04/15] fs/resctrl: Introduce kernel mode (kmode) data structures

Hi Reinette,

Quoted 53 lines · Reinette Chatre

Hi Babu,

Quoted 43 lines · Babu Moger
Quoted 8 lines · Reinette Chatre

Please always keep in mind all the requirements and use cases we learned about during and after RFC v1 of this work.

For example, we already know that "per group" assignment is something resctrl needs to be ready for. Consider the example in
https://lore.kernel.org/lkml/[email protected]/

There may even be "per task" assignment in the future.

Yes. That is correct.

Quoted 8 lines

Constraining this feature to PLZA will make it harder to enable the capabilities that we know resctrl need to support in the future.

This is how we originally landed on the "global" assignment distinction
(https://lore.kernel.org/lkml/[email protected]/)
"global assignment" should be kept or replaced with a solution that continues to prepare resctrl for these other capabilities.

Yes. Makes sense.

Quoted 10 lines

I am not able to see how resctrl could support "per group" assignment with the interface you propose above. If I am missing this, please highlight the solution.

resctrl may need to explicitly split kernel mode from kernel mode properties. For example, below shows an "assign_global_enable_per_cpu" as the kernel mode, now with three properties:
- "ctrl" - could be "assign" or "inherit"
- "mon" - could be "assign" or "inherit"
- "group" - required if "ctrl" or "mon" is set to "assign"

ok.

Quoted 4 lines
     # cat info/kernel_mode
     [inherit]
     assign_global_enable_per_cpu:ctrl=assign;mon=assign;group=uninitialized
Quoted 6 lines

Shouldn't this be like below when default is inherit?

# cat info/kernel_mode
[inherit]
assign_global_enable_per_cpu
Quoted 4 lines

I think it will be useful to let the interface:
(a) show to user space which properties are available for each supported mode, and
(b) show user space what the default value of those properties will be if they are not set when the associated mode is enabled.

The "inherit" is the default property if it is not explicitly set. Right?

# cat info/kernel_mode
[inherit]
assign_global_enable_per_cpu:ctrl=inherit;mon=inherit;group=uninitialized

If the intention is to display all supported values for each property, then we should do so consistently for all properties. For example:

# cat info/kernel_mode
[inherit]
assign_global_enable_per_cpu:ctrl=inherit,assign;mon=inherit,assign;group=uninitialized
Quoted 5 lines

To (b), since the default resource group is used as default when the group is not provided it may be better to use "//" (or just "/", depending on system supporting just one of allocation or monitoring) instead of "uninitialized".

To me, showing the default group would be confusing. It could give the impression that only the default group is associated with the [inherit] mode, even when multiple resource groups exist.

Quoted 10 lines
Quoted 7 lines

When the default changes to assign_global_enable_per_cpu:

# cat info/kernel_mode
inherit [assign_global_enable_per_cpu:ctrl=assign;mon=assign;group=ctrl_mon1//]

Display the second mode with properties only when group is associated with it?

Please consider this from user space side. The user needs to enable the mode. How will the user know which properties are available and what the defaults are?

To me, this may not be necessary. This interface is primarily intended for administrators, who are expected to understand the feature and its configuration. The documentation already covers the available modes and their behavior.

Thanks
Babu

maintainer
#31 lore raw

Re: [RESEND PATCH v4 04/15] fs/resctrl: Introduce kernel mode (kmode) data structures

Hi Babu,

Quoted 56 lines · Babu Moger

Hi Reinette,

Quoted 53 lines · Reinette Chatre

Hi Babu,

Quoted 49 lines · Babu Moger
Quoted 8 lines · Reinette Chatre

Please always keep in mind all the requirements and use cases we learned about during and after RFC v1 of this work.

For example, we already know that "per group" assignment is something resctrl needs to be ready for. Consider the example in
https://lore.kernel.org/lkml/[email protected]/

There may even be "per task" assignment in the future.

Yes. That is correct.

Quoted 8 lines

Constraining this feature to PLZA will make it harder to enable the capabilities that we know resctrl need to support in the future.

This is how we originally landed on the "global" assignment distinction
(https://lore.kernel.org/lkml/[email protected]/)
"global assignment" should be kept or replaced with a solution that continues to prepare resctrl for these other capabilities.

Yes. Makes sense.

Quoted 10 lines

I am not able to see how resctrl could support "per group" assignment with the interface you propose above. If I am missing this, please highlight the solution.

resctrl may need to explicitly split kernel mode from kernel mode properties. For example, below shows an "assign_global_enable_per_cpu" as the kernel mode, now with three properties:
- "ctrl" - could be "assign" or "inherit"
- "mon" - could be "assign" or "inherit"
- "group" - required if "ctrl" or "mon" is set to "assign"

ok.

Quoted 4 lines
     # cat info/kernel_mode
     [inherit]
     assign_global_enable_per_cpu:ctrl=assign;mon=assign;group=uninitialized

Shouldn't this be like below when default is inherit?

# cat info/kernel_mode
[inherit]
assign_global_enable_per_cpu
Quoted 6 lines
Quoted 4 lines

I think it will be useful to let the interface:
  (a) show to user space which properties are available for each supported mode, and
  (b) show user space what the default value of those properties will be if they are not set when the associated mode is enabled.

The "inherit" is the default property if it is not explicitly set. Right?

"property" is different from "kernel mode"

Each "kernel mode" can have zero or more properties.
"inherit" is the default "kernel mode", but it could have a better/more descriptive name. For example, "inherit_from_user" or ...?

Quoted 9 lines
# cat info/kernel_mode
[inherit]
assign_global_enable_per_cpu:ctrl=inherit;mon=inherit;group=uninitialized

If the intention is to display all supported values for each property, then we should do so consistently for all properties. For example:

No. The intention is not to display all supported values for properties of the different kernel modes. Just display which properties are supported and what value resctrl would use if the user enables that mode without providing a value for a particular property. There may be properties that could have values for which it will be difficult to provide all supported values.

For example, if "kernel_mode" contains:

      # cat info/kernel_mode
      [inherit]
      assign_global_enable_per_cpu:ctrl=assign;mon=assign;group=//

Then user space knows that if they enable "assign_global_enable_per_cpu" kernel mode without providing any properties then all kernel work will use the default resource group's allocation and monitoring. If that is not what user space wants then they can change the value of only the properties they need to change.

Quoted 7 lines
# cat info/kernel_mode
[inherit]
assign_global_enable_per_cpu:ctrl=inherit,assign;mon=inherit,assign;group=uninitialized
Quoted 1 line
Quoted 8 lines
Quoted 4 lines

To (b), since the default resource group is used as default when the group is not provided it may be better to use "//" (or just "/", depending on system supporting just one of allocation or monitoring) instead of "uninitialized".

To me, showing the default group would be confusing. It could give the impression that only the default group is associated with the [inherit] mode, even when multiple resource groups exist.

I do not see how default group is associated with the "inherit" mode since inherit mode does not have a "group" property?

Quoted 10 lines
Quoted 10 lines
Quoted 9 lines

When the default changes to assign_global_enable_per_cpu:

# cat info/kernel_mode
inherit [assign_global_enable_per_cpu:ctrl=assign;mon=assign;group=ctrl_mon1//]

Display the second mode with properties only when group is associated with it?

Quoted 7 lines
Quoted 2 lines

Please consider this from user space side. The user needs to enable the mode. How will the user know which properties are available and what the defaults are?

To me, this may not be necessary. This interface is primarily intended for administrators, who are expected to understand the feature and its configuration. The documentation already covers the available modes and their behavior.

This can only be true for a static interface of a feature that will never gain more capabilities. We never have that luxury.

Reinette

author reviewer
#32 lore raw

Re: [RESEND PATCH v4 04/15] fs/resctrl: Introduce kernel mode (kmode) data structures

Hi Reinette,

Quoted 64 lines · Reinette Chatre

Hi Babu,

Quoted 61 lines · Babu Moger

Hi Reinette,

Quoted 57 lines · Reinette Chatre

Hi Babu,

Quoted 43 lines · Babu Moger
Quoted 8 lines · Reinette Chatre

Please always keep in mind all the requirements and use cases we learned about during and after RFC v1 of this work.

For example, we already know that "per group" assignment is something resctrl needs to be ready for. Consider the example in
https://lore.kernel.org/lkml/[email protected]/

There may even be "per task" assignment in the future.

Yes. That is correct.

Quoted 8 lines

Constraining this feature to PLZA will make it harder to enable the capabilities that we know resctrl need to support in the future.

This is how we originally landed on the "global" assignment distinction
(https://lore.kernel.org/lkml/[email protected]/)
"global assignment" should be kept or replaced with a solution that continues to prepare resctrl for these other capabilities.

Yes. Makes sense.

Quoted 10 lines

I am not able to see how resctrl could support "per group" assignment with the interface you propose above. If I am missing this, please highlight the solution.

resctrl may need to explicitly split kernel mode from kernel mode properties. For example, below shows an "assign_global_enable_per_cpu" as the kernel mode, now with three properties:
- "ctrl" - could be "assign" or "inherit"
- "mon" - could be "assign" or "inherit"
- "group" - required if "ctrl" or "mon" is set to "assign"

ok.

Quoted 4 lines
      # cat info/kernel_mode
      [inherit]
      assign_global_enable_per_cpu:ctrl=assign;mon=assign;group=uninitialized
Quoted 6 lines

Shouldn't this be like below when default is inherit?

# cat info/kernel_mode
[inherit]
assign_global_enable_per_cpu

I think it will be useful to let the interface:
  (a) show to user space which properties are available for each supported mode, and
  (b) show user space what the default value of those properties will be if they are not set when the associated mode is enabled.

Quoted 7 lines
Quoted 1 line

The "inherit" is the default property if it is not explicitly set. Right?

"property" is different from "kernel mode"

Each "kernel mode" can have zero or more properties.
"inherit" is the default "kernel mode", but it could have a better/more descriptive name. For example, "inherit_from_user" or ...?

Or "user_inherit_kernel" ?

Quoted 18 lines
Quoted 10 lines

# cat info/kernel_mode
[inherit]
assign_global_enable_per_cpu:ctrl=inherit;mon=inherit;group=uninitialized

If the intention is to display all supported values for each property, then we should do so consistently for all properties. For example:

No. The intention is not to display all supported values for properties of the different kernel modes. Just display which properties are supported and what value resctrl would use if the user enables that mode without providing a value for a particular property. There may be properties that could have values for which it will be difficult to provide all supported values.

For example, if "kernel_mode" contains:

Quoted 8 lines
       # cat info/kernel_mode
       [inherit]
       assign_global_enable_per_cpu:ctrl=assign;mon=assign;group=//

Then user space knows that if they enable "assign_global_enable_per_cpu" kernel mode without providing any properties then all kernel work will use the default resource group's allocation and monitoring. If that is not what user space wants then they can change the value of only the properties they need to change.

That sounds reasonable.

When the group is bound to the global mode,

# cat info/kernel_mode
  inherit
  [assign_global_enable_per_cpu:ctrl=assign;group=ctrl1//]
Quoted 14 lines
Quoted 14 lines


# cat info/kernel_mode
[inherit]
assign_global_enable_per_cpu:ctrl=inherit,assign;mon=inherit,assign;group=uninitialized
Quoted 5 lines

To (b), since the default resource group is used as default when the group is not provided it may be better to use "//" (or just "/", depending on system supporting just one of allocation or monitoring) instead of "uninitialized".

Quoted 6 lines
Quoted 3 lines

To me, showing the default group would be confusing. It could give the impression that only the default group is associated with the [inherit] mode, even when multiple resource groups exist.

I do not see how default group is associated with the "inherit" mode since inherit mode does not have a "group" property?

Yes. Got it.

Thanks,
Babu

maintainer
#33 lore raw

Re: [RESEND PATCH v4 04/15] fs/resctrl: Introduce kernel mode (kmode) data structures

Hi Babu,

Quoted 6 lines · Babu Moger
Quoted 5 lines · Reinette Chatre
Quoted 3 lines · Babu Moger

On 8/13/26 10:55, Reinette Chatre wrote:

The "inherit" is the default property if it is not explicitly set. Right?

Quoted 7 lines
Quoted 5 lines

"property" is different from "kernel mode"

Each "kernel mode" can have zero or more properties.
"inherit" is the default "kernel mode", but it could have a better/more descriptive name. For example, "inherit_from_user" or ...?

Or "user_inherit_kernel" ?

nit: to me this sounds as though user space inherits from kernel.

Also keep in mind that the filename is already "kernel_mode" so any text would be interpreted within that context so repeating "kernel" may not be necessary.

Quoted 25 lines
Quoted 16 lines
Quoted 8 lines
# cat info/kernel_mode
[inherit]
assign_global_enable_per_cpu:ctrl=inherit;mon=inherit;group=uninitialized

If the intention is to display all supported values for each property, then we should do so consistently for all properties. For example:

No. The intention is not to display all supported values for properties of the different kernel modes. Just display which properties are supported and what value resctrl would use if the user enables that mode without providing a value for a particular property. There may be properties that could have values for which it will be difficult to provide all supported values.

For example, if "kernel_mode" contains:

Quoted 8 lines
       # cat info/kernel_mode
       [inherit]
       assign_global_enable_per_cpu:ctrl=assign;mon=assign;group=//

Then user space knows that if they enable "assign_global_enable_per_cpu" kernel mode without providing any properties then all kernel work will use the default resource group's allocation and monitoring. If that is not what user space wants then they can change the value of only the properties they need to change.

Quoted 8 lines

That sounds reasonable.

When the group is bound to the global mode,

# cat info/kernel_mode
  inherit
  [assign_global_enable_per_cpu:ctrl=assign;group=ctrl1//]

Looks good to me (while ignoring the "inherit" TBD naming change).

Reinette

#34 lore raw

Re: [RESEND PATCH v4 04/15] fs/resctrl: Introduce kernel mode (kmode) data structures

Hi Reinette,

Quoted 15 lines · Reinette Chatre

Hi Babu,

Quoted 12 lines · Babu Moger
Quoted 10 lines · Reinette Chatre
Quoted 3 lines · Babu Moger

On 8/13/26 10:55, Reinette Chatre wrote:

The "inherit" is the default property if it is not explicitly set. Right?

"property" is different from "kernel mode"

Each "kernel mode" can have zero or more properties.
"inherit" is the default "kernel mode", but it could have a better/more descriptive name. For example, "inherit_from_user" or ...?

Quoted 6 lines
Quoted 1 line

Or "user_inherit_kernel" ?

nit: to me this sounds as though user space inherits from kernel.

Also keep in mind that the filename is already "kernel_mode" so any text would be interpreted within that context so repeating "kernel" may not be necessary.

May be "inherit_user". We can revisit again.

Quoted 29 lines
Quoted 29 lines
Quoted 18 lines
Quoted 10 lines

# cat info/kernel_mode
[inherit]
assign_global_enable_per_cpu:ctrl=inherit;mon=inherit;group=uninitialized

If the intention is to display all supported values for each property, then we should do so consistently for all properties. For example:

No. The intention is not to display all supported values for properties of the different kernel modes. Just display which properties are supported and what value resctrl would use if the user enables that mode without providing a value for a particular property. There may be properties that could have values for which it will be difficult to provide all supported values.

For example, if "kernel_mode" contains:

Quoted 8 lines
        # cat info/kernel_mode
        [inherit]
        assign_global_enable_per_cpu:ctrl=assign;mon=assign;group=//

Then user space knows that if they enable "assign_global_enable_per_cpu" kernel mode without providing any properties then all kernel work will use the default resource group's allocation and monitoring. If that is not what user space wants then they can change the value of only the properties they need to change.

That sounds reasonable.

Quoted 8 lines
Quoted 6 lines

When the group is bound to the global mode,

# cat info/kernel_mode
   inherit
   [assign_global_enable_per_cpu:ctrl=assign;group=ctrl1//]

Looks good to me (while ignoring the "inherit" TBD naming change).

Thanks,
Babu

author reviewer
#35 lore raw

PATCH RESEND v4 5/15 x86,fs/resctrl: Introduce architecture hooks to program kernel-mode

In reply to Babu Moger

Kernel-mode policies defined by enum resctrl_kernel_mode must be applied to each affected CPU whenever a policy is selected or its scope changes. Generic resctrl therefore requires an architecture-specific interface to program allocation and monitoring associations in hardware across a given CPU mask.

Introduce a helper, resctrl_arch_configure_kmode(), to handle kernel-mode programming. On x86/AMD systems, this helper programs the MSR_IA32_PQR_PLZA_ASSOC register on all online CPUs in the specified mask via on_each_cpu_mask(). Also provide a no-op stub for MPAM systems.

Generic resctrl does not invoke this hook yet; it will be used when user space selects a kernel-mode policy or updates the associated CPU set.

---
v4: Added assign_mon parameter in resctrl_arch_configure_kmode() to program the RMID
as discussed in below.
https://lore.kernel.org/lkml/[email protected]/
Changed cpumask type to "const struct cpumask *cpu_mask".
Added MPAM stub to avoid any linking issues when resctrl_arch_configure_kmode() is called from FS layer. Thanks to Qinyun.
Re-wrote the changelog to be generic.
Updated code comments.

v3: Removed task based PLZA implementation so related changes are removed.
Removed handling of rmid_en as it is not required. The group type assigned will be different so the monitoring part is already taken care. Updated the change log with details.
Removed resctrl_arch_set_kmode() as arch only provides the modes supported. It is FS which decided which mode to apply.

v2: Updated the commit message to include the sequence of steps to enable PLZA.
Added mode code comments for clarity.
Added kmode to functin names to be generic.

---
 arch/x86/kernel/cpu/resctrl/ctrlmondata.c | 36 +++++++++++++++++++++++
 drivers/resctrl/mpam_resctrl.c            |  5 ++++
 include/linux/resctrl.h                   | 15 ++++++++++
 3 files changed, 56 insertions(+)
arch/x86/kernel/cpu/resctrl/ctrlmondata.c +36 -0
index b20e705606b8..025f139434f2 100644
@@ -131,3 +131,39 @@ int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable)
 
 	return 0;
 }
+
+static void resctrl_kmode_set_one_amd(void *arg)
+{
+	union msr_pqr_plza_assoc *plza = arg;
+
+	wrmsrq(MSR_IA32_PQR_PLZA_ASSOC, plza->full);
+}
+
+/*
+ * Program Privilege Level Zero Association (PLZA) on @cpu_mask.
+ *
+ * When @enable is true, CPL 0 allocation traffic on the targeted CPUs uses
+ * @closid from MSR_IA32_PQR_PLZA_ASSOC instead of the CLOSID from
+ * MSR_IA32_PQR_ASSOC. Monitoring is redirected to @rmid only when
+ * @assign_mon is true; otherwise kernel-mode monitoring continues to use the
+ * RMID associated with the current task.
+ *
+ * @cpu_mask:	CPUs whose PLZA MSR should be updated.
+ * @closid:	CLOSID to use for kernel-mode allocation when PLZA is enabled.
+ * @rmid:	RMID to use for kernel-mode monitoring when @assign_mon is true.
+ * @assign_mon:	Whether PLZA should provide the kernel-mode RMID.
+ * @enable:	Whether PLZA should provide the kernel-mode association.
+ */
+void resctrl_arch_configure_kmode(const struct cpumask *cpu_mask, u32 closid, u32 rmid,
+				  bool assign_mon, bool enable)
+{
+	union msr_pqr_plza_assoc plza = { 0 };
+
+	plza.split.rmid = rmid;
+	plza.split.rmid_en = assign_mon;
+	plza.split.closid = closid;
+	plza.split.closid_en = 1;
+	plza.split.plza_en = enable;
+
+	on_each_cpu_mask(cpu_mask, resctrl_kmode_set_one_amd, &plza, 1);
+}
drivers/resctrl/mpam_resctrl.c +5 -0
index 226ff6f532fa..630b6cfc0269 100644
@@ -158,6 +158,11 @@ bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r)
 	return false;
 }
 
+void resctrl_arch_configure_kmode(const struct cpumask *cpu_mask, u32 closid,
+				  u32 rmid, bool assign_mon, bool enable)
+{
+}
+
 void resctrl_arch_pre_mount(void)
 {
 }
include/linux/resctrl.h +15 -0
index c7abed51cd5f..47db34dd167e 100644
@@ -734,6 +734,21 @@ enum resctrl_kernel_mode {
 
 #define RESCTRL_NUM_KERNEL_MODES (RESCTRL_KMODE_LAST + 1)
 
+/**
+ * resctrl_arch_configure_kmode() - Program kernel-mode association on CPUs
+ * @cpu_mask:	CPUs to update; the architecture applies the change on the
+ *		online subset of this mask.
+ * @closid:	Allocation class for kernel-mode traffic. On x86 this is the
+ *		CLOSID programmed when allocation is assigned for kernel work.
+ * @rmid:	Monitoring context for kernel-mode traffic. On x86 this is the
+ *		RMID programmed when monitoring is assigned for kernel work.
+ * @assign_mon:	true to assign @rmid for kernel work; false to inherit
+ *		monitoring from the user task.
+ * @enable:	true to enable kernel-mode association on the targeted CPUs.
+ */
+void resctrl_arch_configure_kmode(const struct cpumask *cpu_mask, u32 closid, u32 rmid,
+				  bool assign_mon, bool enable);
+
 extern unsigned int resctrl_rmid_realloc_threshold;
 extern unsigned int resctrl_rmid_realloc_limit;
 
Signature · 1 line
2.43.0
#36 lore raw

Re: [RESEND PATCH v4 05/15] x86,fs/resctrl: Introduce architecture hooks to program kernel-mode

Quoted 47 lines · Babu Moger

Kernel-mode policies defined by enum resctrl_kernel_mode must be applied to each affected CPU whenever a policy is selected or its scope changes. Generic resctrl therefore requires an architecture-specific interface to program allocation and monitoring associations in hardware across a given CPU mask.

Introduce a helper, resctrl_arch_configure_kmode(), to handle kernel-mode programming. On x86/AMD systems, this helper programs the MSR_IA32_PQR_PLZA_ASSOC register on all online CPUs in the specified mask via on_each_cpu_mask(). Also provide a no-op stub for MPAM systems.

Generic resctrl does not invoke this hook yet; it will be used when user space selects a kernel-mode policy or updates the associated CPU set.

---
v4: Added assign_mon parameter in resctrl_arch_configure_kmode() to program the RMID
as discussed in below.
https://lore.kernel.org/lkml/[email protected]/
Changed cpumask type to "const struct cpumask *cpu_mask".
Added MPAM stub to avoid any linking issues when resctrl_arch_configure_kmode() is called from FS layer. Thanks to Qinyun.
Re-wrote the changelog to be generic.
Updated code comments.

v3: Removed task based PLZA implementation so related changes are removed.
Removed handling of rmid_en as it is not required. The group type assigned will be different so the monitoring part is already taken care. Updated the change log with details.
Removed resctrl_arch_set_kmode() as arch only provides the modes supported. It is FS which decided which mode to apply.

v2: Updated the commit message to include the sequence of steps to enable PLZA.
Added mode code comments for clarity.
Added kmode to functin names to be generic.

---
  arch/x86/kernel/cpu/resctrl/ctrlmondata.c | 36 +++++++++++++++++++++++
  drivers/resctrl/mpam_resctrl.c            |  5 ++++
  include/linux/resctrl.h                   | 15 ++++++++++
  3 files changed, 56 insertions(+)
arch/x86/kernel/cpu/resctrl/ctrlmondata.c +0 -0
index b20e705606b8..025f139434f2 100644
@@ -131,3 +131,39 @@ int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable)
 

arch/x86/kernel/cpu/resctrl/ctrlmondata.c int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable) · line 141

Quoted 10 lines
arch/x86/kernel/cpu/resctrl/ctrlmondata.c +8 -0
  	return 0;
  }
+
+static void resctrl_kmode_set_one_amd(void *arg)
+{
+	union msr_pqr_plza_assoc *plza = arg;
+
+	wrmsrq(MSR_IA32_PQR_PLZA_ASSOC, plza->full);
+}
+

Sashiko reported:

https://sashiko.dev/#/patchset/cover.1783461016.git.babu.moger%40amd.com?part=5

--- Patch [5]: [RESEND PATCH v4 05/15] x86,fs/resctrl: Introduce architecture hooks to program kernel-mode --- commit 97958c0d99b7e538d1f8d019e6c63712b44a6289
Author: Babu Moger <[email protected]>
x86,fs/resctrl: Introduce architecture hooks to program kernel-mode

Kernel-mode policies defined by enum resctrl_kernel_mode must be applied to each affected CPU whenever a policy is selected or its scope changes. Generic resctrl therefore requires an architecture-specific interface to program allocation and monitoring associations in hardware across a given CPU mask. This patch introduces resctrl_arch_configure_kmode() to handle this.

Quoted 3 lines
arch/x86/kernel/cpu/resctrl/ctrlmondata.c +0 -0

[ ... ]

arch/x86/kernel/cpu/resctrl/ctrlmondata.c int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable) · line 139

Quoted 5 lines
arch/x86/kernel/cpu/resctrl/ctrlmondata.c +5 -0
+static void resctrl_kmode_set_one_amd(void *arg)
+{
+	union msr_pqr_plza_assoc *plza = arg;
+
+	wrmsrq(MSR_IA32_PQR_PLZA_ASSOC, plza->full);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Will this truncate the upper 32 bits of the MSR on 32-bit x86 builds? It appears that union msr_pqr_plza_assoc in arch/x86/kernel/cpu/resctrl/internal.h uses unsigned long for both the bitfields and the full variable. On 32-bit x86 architectures, unsigned long is 32 bits, which means reading plza->full will truncate the 64-bit value. When this is implicitly zero-extended to u64 and passed to wrmsrq(), the upper 32 bits of the MSR, which contain plza_en, closid_en, and closid, will be overwritten with zeros.

Will change the union msr_pqr_plza_assoc to use u64 instead on unsigned long. It should take care of this.

Thanks
Babu

maintainer
#37 lore raw

Re: [RESEND PATCH v4 05/15] x86,fs/resctrl: Introduce architecture hooks to program kernel-mode

In reply to Babu Moger

Hi Babu,

Quoted 1 line · Babu Moger

Kernel-mode policies defined by enum resctrl_kernel_mode must be applied to

"Kernel-mode policies" -> "Kernel modes"?

Quoted 1 line

each affected CPU whenever a policy is selected or its scope changes.

What is an "affected CPU"?

policy -> "mode"? or rather: "whenever a policy is selected or its scope changes" -> "whenever user space switches the kernel mode or changes which CPUs are associated with the active kernel mode"?

Quoted 8 lines

Generic resctrl therefore requires an architecture-specific interface to program allocation and monitoring associations in hardware across a given CPU mask.

Introduce a helper, resctrl_arch_configure_kmode(), to handle kernel-mode programming. On x86/AMD systems, this helper programs the MSR_IA32_PQR_PLZA_ASSOC register on all online CPUs in the specified mask via on_each_cpu_mask(). Also provide a no-op stub for MPAM systems.

No need to describe the code details, please just make it high level of what the code accomplished as opposed to describing the code self.

Quoted 3 lines

Generic resctrl does not invoke this hook yet; it will be used when user space selects a kernel-mode policy or updates the associated CPU set.

Looking ahead how this arch helper is used it really is a "one size fits all" based on what AMD requires. Specifically, as I see it this architecture helper is called under three very different scenarios:
- A new kernel mode is activated
- CPUs are added/removed from an active kernel mode
- A kernel mode is de-activated.

There is no way for an architecture to distinguish these three scenarios. An architecture that, for example, needs to do some arch-specific init to support a particular mode will not know when it should do this.

This "one size fits all" may be ok for an initial approach until we learn what other architectures require, but the API needs to be clear on when and how architecture can expect it to be called from resctrl fs.

Consider, for example, the API description containing text/contract like:
- If a per-cpu kernel mode is active when user space switches to a new per-cpu kernel mode then resctrl_arch_configure_kmode() will first be called to de-activate the active kernel mode on all CPUs that the kernel mode is active on.
- When user space switches to a new per-cpu kernel mode then resctrl_arch_configure_kmode() is called with cpu_online_mask.
- When user space adds a CPU to an active per-cpu kernel mode ...
- When user space removes a CPU from to an active per-cpu kernel mode ...
- resctrl fs will always provide the same closid, rmid, and "assign_mon" parameters when activating a kernel mode, all interactions (adding/removing CPU) while the kernel mode is active, as well as when de-activating the kernel mode.

Quoted 93 lines

---
v4: Added assign_mon parameter in resctrl_arch_configure_kmode() to program the RMID
as discussed in below.
https://lore.kernel.org/lkml/[email protected]/
Changed cpumask type to "const struct cpumask *cpu_mask".
Added MPAM stub to avoid any linking issues when resctrl_arch_configure_kmode() is called from FS layer. Thanks to Qinyun.
Re-wrote the changelog to be generic.
Updated code comments.

v3: Removed task based PLZA implementation so related changes are removed.
Removed handling of rmid_en as it is not required. The group type assigned will be different so the monitoring part is already taken care. Updated the change log with details.
Removed resctrl_arch_set_kmode() as arch only provides the modes supported. It is FS which decided which mode to apply.

v2: Updated the commit message to include the sequence of steps to enable PLZA.
Added mode code comments for clarity.
Added kmode to functin names to be generic.

---
 arch/x86/kernel/cpu/resctrl/ctrlmondata.c | 36 +++++++++++++++++++++++
 drivers/resctrl/mpam_resctrl.c            |  5 ++++
 include/linux/resctrl.h                   | 15 ++++++++++
 3 files changed, 56 insertions(+)
arch/x86/kernel/cpu/resctrl/ctrlmondata.c +36 -0
index b20e705606b8..025f139434f2 100644
@@ -131,3 +131,39 @@ int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable)
 
 	return 0;
 }
+
+static void resctrl_kmode_set_one_amd(void *arg)
+{
+	union msr_pqr_plza_assoc *plza = arg;
+
+	wrmsrq(MSR_IA32_PQR_PLZA_ASSOC, plza->full);
+}
+
+/*
+ * Program Privilege Level Zero Association (PLZA) on @cpu_mask.
+ *
+ * When @enable is true, CPL 0 allocation traffic on the targeted CPUs uses
+ * @closid from MSR_IA32_PQR_PLZA_ASSOC instead of the CLOSID from
+ * MSR_IA32_PQR_ASSOC. Monitoring is redirected to @rmid only when
+ * @assign_mon is true; otherwise kernel-mode monitoring continues to use the
+ * RMID associated with the current task.
+ *
+ * @cpu_mask:	CPUs whose PLZA MSR should be updated.
+ * @closid:	CLOSID to use for kernel-mode allocation when PLZA is enabled.
+ * @rmid:	RMID to use for kernel-mode monitoring when @assign_mon is true.
+ * @assign_mon:	Whether PLZA should provide the kernel-mode RMID.
+ * @enable:	Whether PLZA should provide the kernel-mode association.
+ */
+void resctrl_arch_configure_kmode(const struct cpumask *cpu_mask, u32 closid, u32 rmid,
+				  bool assign_mon, bool enable)
+{
+	union msr_pqr_plza_assoc plza = { 0 };
+
+	plza.split.rmid = rmid;
+	plza.split.rmid_en = assign_mon;
+	plza.split.closid = closid;
+	plza.split.closid_en = 1;
+	plza.split.plza_en = enable;
+
+	on_each_cpu_mask(cpu_mask, resctrl_kmode_set_one_amd, &plza, 1);
+}
drivers/resctrl/mpam_resctrl.c +5 -0
index 226ff6f532fa..630b6cfc0269 100644
@@ -158,6 +158,11 @@ bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r)
 	return false;
 }
 
+void resctrl_arch_configure_kmode(const struct cpumask *cpu_mask, u32 closid,
+				  u32 rmid, bool assign_mon, bool enable)
+{
+}
+
 void resctrl_arch_pre_mount(void)
 {
 }
include/linux/resctrl.h +0 -0
index c7abed51cd5f..47db34dd167e 100644

include/linux/resctrl.h enum resctrl_kernel_mode { · line 740

Quoted 7 lines
include/linux/resctrl.h +4 -0
@@ -734,6 +734,21 @@ enum resctrl_kernel_mode {
 
 #define RESCTRL_NUM_KERNEL_MODES (RESCTRL_KMODE_LAST + 1)
 
+/**
+ * resctrl_arch_configure_kmode() - Program kernel-mode association on CPUs
+ * @cpu_mask:	CPUs to update; the architecture applies the change on the
+ *		online subset of this mask.

Could architecture not expect cpu_mask to only contain online CPUs ?

include/linux/resctrl.h enum resctrl_kernel_mode { · line 741

Quoted 1 line
include/linux/resctrl.h +1 -0
+ * @closid:	Allocation class for kernel-mode traffic. On x86 this is the

"Allocation class" ? Care should only be taken when using "closid" outside of kernel. Please see all the other examples of arch API in this file that uses closid.

include/linux/resctrl.h enum resctrl_kernel_mode { · line 743

Quoted 2 lines
include/linux/resctrl.h +2 -0
+ *		CLOSID programmed when allocation is assigned for kernel work.
+ * @rmid:	Monitoring context for kernel-mode traffic. On x86 this is the

"Monitoring context" ? At this time it is quite clear to architectures how to do needed mapping.

Some archs will use closid/rmid separately, others will consider them together.

include/linux/resctrl.h enum resctrl_kernel_mode { · line 745

Quoted 2 lines
include/linux/resctrl.h +2 -0
+ *		RMID programmed when monitoring is assigned for kernel work.
+ * @assign_mon:	true to assign @rmid for kernel work; false to inherit

This is where the only distinction is required when considering other architectures. Note that, from user space perspective, it is a monitoring group, potentially identified with both closid/rmid that is assigned, not just an rmid.
This is thus not a request to "assign @rmid for kernel work" but instead something like "kernel work should be monitored by resource group identified by @rmid, or both @closid and @rmid, depending on the architecture"

include/linux/resctrl.h enum resctrl_kernel_mode { · line 747

Quoted 2 lines
include/linux/resctrl.h +2 -0
+ *		monitoring from the user task.
+ * @enable:	true to enable kernel-mode association on the targeted CPUs.

"the targeted CPUs" -> CPUs in @cpu_mask?
Please be explicit what is expected from architecture when "false" is provided.

include/linux/resctrl.h enum resctrl_kernel_mode { · line 754

Quoted 7 lines
include/linux/resctrl.h +4 -0
+ */
+void resctrl_arch_configure_kmode(const struct cpumask *cpu_mask, u32 closid, u32 rmid,
+				  bool assign_mon, bool enable);
+
 extern unsigned int resctrl_rmid_realloc_threshold;
 extern unsigned int resctrl_rmid_realloc_limit;
 

Reinette

#38 lore raw

Re: [RESEND PATCH v4 05/15] x86,fs/resctrl: Introduce architecture hooks to program kernel-mode

Hi Reinette,

Quoted 6 lines · Reinette Chatre

Hi Babu,

Quoted 1 line · Babu Moger

Kernel-mode policies defined by enum resctrl_kernel_mode must be applied to

"Kernel-mode policies" -> "Kernel modes"?

Ack.

Quoted 5 lines
Quoted 2 lines

each affected CPU whenever a policy is selected or its scope changes.

What is an "affected CPU"?

Kernel mode policies defined by enum resctrl_kernel_mode must be applied to each CPU whenever user space changes the kernel mode or modifies the CPUs associated with the active kernel mode.

Quoted 9 lines

policy -> "mode"? or rather: "whenever a policy is selected or its scope changes" -> "whenever user space switches the kernel mode or changes which CPUs are associated with the active kernel mode"?

Quoted 4 lines

Generic resctrl therefore requires an architecture-specific interface to program allocation and monitoring associations in hardware across a given CPU mask.

Quoted 7 lines
Quoted 4 lines

Introduce a helper, resctrl_arch_configure_kmode(), to handle kernel-mode programming. On x86/AMD systems, this helper programs the MSR_IA32_PQR_PLZA_ASSOC register on all online CPUs in the specified mask via on_each_cpu_mask(). Also provide a no-op stub for MPAM systems.

No need to describe the code details, please just make it high level of what the code accomplished as opposed to describing the code self.

ok.

Quoted 12 lines
Quoted 4 lines

Generic resctrl does not invoke this hook yet; it will be used when user space selects a kernel-mode policy or updates the associated CPU set.

Looking ahead how this arch helper is used it really is a "one size fits all" based on what AMD requires. Specifically, as I see it this architecture helper is called under three very different scenarios:
- A new kernel mode is activated
- CPUs are added/removed from an active kernel mode
- A kernel mode is de-activated.

Quoted 7 lines

There is no way for an architecture to distinguish these three scenarios. An architecture that, for example, needs to do some arch-specific init to support a particular mode will not know when it should do this.

This "one size fits all" may be ok for an initial approach until we learn what other architectures require, but the API needs to be clear on when and how architecture can expect it to be called from resctrl fs.

ack.

Quoted 12 lines

Consider, for example, the API description containing text/contract like:
- If a per-cpu kernel mode is active when user space switches to a new per-cpu kernel mode then resctrl_arch_configure_kmode() will first be called to de-activate the active kernel mode on all CPUs that the kernel mode is active on.
- When user space switches to a new per-cpu kernel mode then resctrl_arch_configure_kmode() is called with cpu_online_mask.
- When user space adds a CPU to an active per-cpu kernel mode ...
- When user space removes a CPU from to an active per-cpu kernel mode ...
- resctrl fs will always provide the same closid, rmid, and "assign_mon" parameters when activating a kernel mode, all interactions (adding/removing CPU) while the kernel mode is active, as well as when de-activating the kernel mode.

Will add these texts. Thanks.

Quoted 54 lines
Quoted 54 lines

---
v4: Added assign_mon parameter in resctrl_arch_configure_kmode() to program the RMID
as discussed in below.
https://lore.kernel.org/lkml/[email protected]/
Changed cpumask type to "const struct cpumask *cpu_mask".
Added MPAM stub to avoid any linking issues when resctrl_arch_configure_kmode() is called from FS layer. Thanks to Qinyun.
Re-wrote the changelog to be generic.
Updated code comments.

v3: Removed task based PLZA implementation so related changes are removed.
Removed handling of rmid_en as it is not required. The group type assigned will be different so the monitoring part is already taken care. Updated the change log with details.
Removed resctrl_arch_set_kmode() as arch only provides the modes supported. It is FS which decided which mode to apply.

v2: Updated the commit message to include the sequence of steps to enable PLZA.
Added mode code comments for clarity.
Added kmode to functin names to be generic.

---
  arch/x86/kernel/cpu/resctrl/ctrlmondata.c | 36 +++++++++++++++++++++++
  drivers/resctrl/mpam_resctrl.c            |  5 ++++
  include/linux/resctrl.h                   | 15 ++++++++++
  3 files changed, 56 insertions(+)
arch/x86/kernel/cpu/resctrl/ctrlmondata.c +17 -0
index b20e705606b8..025f139434f2 100644
@@ -131,3 +131,39 @@ int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable)
 
  	return 0;
  }
+
+static void resctrl_kmode_set_one_amd(void *arg)
+{
+	union msr_pqr_plza_assoc *plza = arg;
+
+	wrmsrq(MSR_IA32_PQR_PLZA_ASSOC, plza->full);
+}
+
+/*
+ * Program Privilege Level Zero Association (PLZA) on @cpu_mask.
+ *
+ * When @enable is true, CPL 0 allocation traffic on the targeted CPUs uses
+ * @closid from MSR_IA32_PQR_PLZA_ASSOC instead of the CLOSID from
+ * MSR_IA32_PQR_ASSOC. Monitoring is redirected to @rmid only when
+ * @assign_mon is true; otherwise kernel-mode monitoring continues to use the
+ * RMID associated with the current task.
+ *
Quoted 8 lines

arch/x86/kernel/cpu/resctrl/ctrlmondata.c int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable) · line 158

Quoted 8 lines
arch/x86/kernel/cpu/resctrl/ctrlmondata.c +8 -0
+ * @cpu_mask:	CPUs whose PLZA MSR should be updated.
+ * @closid:	CLOSID to use for kernel-mode allocation when PLZA is enabled.
+ * @rmid:	RMID to use for kernel-mode monitoring when @assign_mon is true.
+ * @assign_mon:	Whether PLZA should provide the kernel-mode RMID.
+ * @enable:	Whether PLZA should provide the kernel-mode association.
+ */
+void resctrl_arch_configure_kmode(const struct cpumask *cpu_mask, u32 closid, u32 rmid,
+				  bool assign_mon, bool enable)

Need to add "assign_ctrl" also.

Quoted 33 lines
Quoted 33 lines
arch/x86/kernel/cpu/resctrl/ctrlmondata.c +11 -0
+{
+	union msr_pqr_plza_assoc plza = { 0 };
+
+	plza.split.rmid = rmid;
+	plza.split.rmid_en = assign_mon;
+	plza.split.closid = closid;
+	plza.split.closid_en = 1;
+	plza.split.plza_en = enable;
+
+	on_each_cpu_mask(cpu_mask, resctrl_kmode_set_one_amd, &plza, 1);
+}
drivers/resctrl/mpam_resctrl.c +5 -0
index 226ff6f532fa..630b6cfc0269 100644
@@ -158,6 +158,11 @@ bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r)
  	return false;
  }
 
+void resctrl_arch_configure_kmode(const struct cpumask *cpu_mask, u32 closid,
+				  u32 rmid, bool assign_mon, bool enable)
+{
+}
+
  void resctrl_arch_pre_mount(void)
  {
  }
include/linux/resctrl.h +0 -0
index c7abed51cd5f..47db34dd167e 100644
@@ -734,6 +734,21 @@ enum resctrl_kernel_mode {
 
Quoted 8 lines

include/linux/resctrl.h enum resctrl_kernel_mode { · line 740

Quoted 6 lines
include/linux/resctrl.h +4 -0
  #define RESCTRL_NUM_KERNEL_MODES (RESCTRL_KMODE_LAST + 1)
 
+/**
+ * resctrl_arch_configure_kmode() - Program kernel-mode association on CPUs
+ * @cpu_mask:	CPUs to update; the architecture applies the change on the
+ *		online subset of this mask.

Could architecture not expect cpu_mask to only contain online CPUs ?

Yes. It should be only online CPUs. Let me change the text little bit.

Quoted 5 lines

include/linux/resctrl.h enum resctrl_kernel_mode { · line 741

Quoted 2 lines
include/linux/resctrl.h +1 -0
+ * @closid:	Allocation class for kernel-mode traffic. On x86 this is the

"Allocation class" ? Care should only be taken when using "closid" outside of kernel. Please see all the other examples of arch API in this file that uses closid.

Sure.

Quoted 8 lines

include/linux/resctrl.h enum resctrl_kernel_mode { · line 743

Quoted 3 lines
include/linux/resctrl.h +2 -0
+ *		CLOSID programmed when allocation is assigned for kernel work.
+ * @rmid:	Monitoring context for kernel-mode traffic. On x86 this is the

"Monitoring context" ? At this time it is quite clear to architectures how to do needed mapping.

Some archs will use closid/rmid separately, others will consider them together.

Yes. Will change based on other text example.

Quoted 10 lines

include/linux/resctrl.h enum resctrl_kernel_mode { · line 745

Quoted 3 lines
include/linux/resctrl.h +2 -0
+ *		RMID programmed when monitoring is assigned for kernel work.
+ * @assign_mon:	true to assign @rmid for kernel work; false to inherit

This is where the only distinction is required when considering other architectures. Note that, from user space perspective, it is a monitoring group, potentially identified with both closid/rmid that is assigned, not just an rmid.
This is thus not a request to "assign @rmid for kernel work" but instead something like "kernel work should be monitored by resource group identified by @rmid, or both @closid and @rmid, depending on the architecture"

Sure.

Quoted 6 lines

include/linux/resctrl.h enum resctrl_kernel_mode { · line 747

Quoted 3 lines
include/linux/resctrl.h +2 -0
+ *		monitoring from the user task.
+ * @enable:	true to enable kernel-mode association on the targeted CPUs.

"the targeted CPUs" -> CPUs in @cpu_mask?
Please be explicit what is expected from architecture when "false" is provided.

Sure. Will add that text.

Thanks
Babu

maintainer
#39 lore raw

Re: [RESEND PATCH v4 05/15] x86,fs/resctrl: Introduce architecture hooks to program kernel-mode

Hi Babu,

Quoted 12 lines · Babu

Hi Reinette,

Quoted 6 lines · Reinette Chatre

Hi Babu,

Quoted 1 line · Babu Moger

Kernel-mode policies defined by enum resctrl_kernel_mode must be applied to

"Kernel-mode policies" -> "Kernel modes"?

Ack.

Quoted 1 line
Quoted 8 lines
Quoted 4 lines
Quoted 1 line

each affected CPU whenever a policy is selected or its scope changes.

What is an "affected CPU"?

Kernel mode policies defined by enum resctrl_kernel_mode must be applied to each CPU whenever user space changes the kernel mode or modifies the CPUs associated with the active kernel mode.

ok, could this thus just be "each CPU"? I find a lot of text in this series use unnecessary adjectives and then makes it worse by using inconsistent adjectives. This makes the text difficult to follow since it is never obvious if the text refers to the same thing as before. Please remove unnecessary words so that the writing becomes concise and easier to follow.

Reinette

author reviewer
#40 lore raw

Re: [RESEND PATCH v4 05/15] x86,fs/resctrl: Introduce architecture hooks to program kernel-mode

Hi Reinette,

Quoted 24 lines · Reinette Chatre

Hi Babu,

Quoted 12 lines · Babu

Hi Reinette,

Quoted 6 lines · Reinette Chatre

Hi Babu,

Quoted 1 line · Babu Moger

Kernel-mode policies defined by enum resctrl_kernel_mode must be applied to

"Kernel-mode policies" -> "Kernel modes"?

Ack.

Quoted 1 line
Quoted 8 lines
Quoted 4 lines
Quoted 1 line

each affected CPU whenever a policy is selected or its scope changes.

What is an "affected CPU"?

Kernel mode policies defined by enum resctrl_kernel_mode must be applied to each CPU whenever user space changes the kernel mode or modifies the CPUs associated with the active kernel mode.

Quoted 5 lines

ok, could this thus just be "each CPU"? I find a lot of text in this series use unnecessary adjectives and then makes it worse by using inconsistent adjectives. This makes the text difficult to follow since it is never obvious if the text refers to the same thing as before. Please remove unnecessary words so that the writing becomes concise and easier to follow.

Ok. Sounds good.

Thanks
Babu

author reviewer
#41 lore raw

PATCH RESEND v4 6/15 fs/resctrl: Introduce resctrl_set_kmode_support() to initialize supported modes

In reply to Babu Moger

Architectures need a way to advertise which kernel-mode resctrl policies they support before generic resctrl exposes those policies through the filesystem.

Add the struct resctrl_kmode_cfg to define the default mode statically, and introduce resctrl_set_kmode_support() so architecture code can register supported kernel-mode policies during resctrl initialization. The INHERIT_CTRL_AND_MON policy is supported by default, so architectures only need to register any additional modes.

---
v4: New patch to initialize supported kernel-mode's.
https://lore.kernel.org/lkml/[email protected]/
Changed the kmode_cur to enum resctrl_kernel_mode in resctrl_kmode_cfg. Moved the resctrl_kmode_cfg to filesystem code.

---
 fs/resctrl/internal.h   | 12 ++++++++++++
 fs/resctrl/rdtgroup.c   | 23 +++++++++++++++++++++++
 include/linux/resctrl.h | 10 ++++++++++
 3 files changed, 45 insertions(+)
fs/resctrl/internal.h +12 -0
index 48af75b9dc85..178126bb2da5 100644
@@ -314,6 +314,18 @@ struct mbm_state {
 	u32	prev_bw;
 };
 
+/**
+ * struct resctrl_kmode_cfg - Kernel-mode policy snapshot from architecture
+ * @kmode:	Bitmap of supported &enum resctrl_kernel_mode values. Each
+ *		supported mode is represented by BIT(mode).
+ * @kmode_cur:	Currently selected kernel-mode policy.
+ * @k_rdtgrp:	Resource group backing global-assign modes when applicable;
+ */
+struct resctrl_kmode_cfg {
+	unsigned long			kmode;
+	enum resctrl_kernel_mode	kmode_cur;
+	struct rdtgroup			*k_rdtgrp;
+};
 extern struct mutex rdtgroup_mutex;
 
 static inline const char *rdt_kn_name(const struct kernfs_node *kn)
fs/resctrl/rdtgroup.c +23 -0
index cc9966ff6cdf..0ee0dfaf9065 100644
@@ -78,6 +78,16 @@ static void mon_put_kn_priv(void);
 
 struct dentry *debugfs_resctrl;
 
+/*
+ * Global kernel-mode resctrl policy. Architectures add supported modes before
+ * resctrl is mounted; @kmode_cur tracks the active policy after user selection.
+ */
+static struct resctrl_kmode_cfg resctrl_kcfg = {
+	.kmode = BIT(INHERIT_CTRL_AND_MON),
+	.kmode_cur = INHERIT_CTRL_AND_MON,
+	.k_rdtgrp = NULL
+};
+
 /*
  * Memory bandwidth monitoring event to use for the default CTRL_MON group
  * and each new CTRL_MON group created by the user.  Only relevant when
@@ -888,6 +898,19 @@ static int rdtgroup_rmid_show(struct kernfs_open_file *of,
 	return ret;
 }
 
+/**
+ * resctrl_set_kmode_support() - Advertise support for a kernel-mode policy
+ * @kmode:	Kernel-mode policy supported by the architecture.
+ *
+ * Architectures call this during resctrl initialization to make @kmode visible
+ * to the resctrl filesystem. INHERIT_CTRL_AND_MON is always supported.
+ */
+void resctrl_set_kmode_support(enum resctrl_kernel_mode kmode)
+{
+	if (kmode <= RESCTRL_KMODE_LAST)
+		__set_bit(kmode, &resctrl_kcfg.kmode);
+}
+
 #ifdef CONFIG_PROC_CPU_RESCTRL
 /*
  * A task can only be part of one resctrl control group and of one monitor
include/linux/resctrl.h +10 -0
index 47db34dd167e..8dd02579f354 100644
@@ -734,6 +734,16 @@ enum resctrl_kernel_mode {
 
 #define RESCTRL_NUM_KERNEL_MODES (RESCTRL_KMODE_LAST + 1)
 
+/**
+ * resctrl_set_kmode_support() - Advertise a supported kernel-mode policy
+ * @kmode:	Kernel-mode policy supported by the architecture.
+ *
+ * Architectures use this during resctrl initialization to make additional
+ * kernel-mode policies available to the filesystem. INHERIT_CTRL_AND_MON is
+ * supported by default and does not need to be registered.
+ */
+void resctrl_set_kmode_support(enum resctrl_kernel_mode kmode);
+
 /**
  * resctrl_arch_configure_kmode() - Program kernel-mode association on CPUs
  * @cpu_mask:	CPUs to update; the architecture applies the change on the
Signature · 1 line
2.43.0
maintainer
#42 lore raw

Re: [RESEND PATCH v4 06/15] fs/resctrl: Introduce resctrl_set_kmode_support() to initialize supported modes

Hi Babu,

Quoted 1 line · Babu Moger

Architectures need a way to advertise which kernel-mode resctrl policies

"kernel-mode resctrl policies" -> "kernel modes"?

Quoted 1 line

they support before generic resctrl exposes those policies through the

"policies" -> "modes"
(this is related to the earlier "use consistent terminology comment" I will stop highlighting instances)

Quoted 7 lines

filesystem.

Add the struct resctrl_kmode_cfg to define the default mode statically, and introduce resctrl_set_kmode_support() so architecture code can register supported kernel-mode policies during resctrl initialization. The INHERIT_CTRL_AND_MON policy is supported by default, so architectures only need to register any additional modes.

Please keep changelog high level and not describe the code that can be seen from patch. When doing so, please write in imperative tone.

Quoted 18 lines

---
v4: New patch to initialize supported kernel-mode's.
https://lore.kernel.org/lkml/[email protected]/
Changed the kmode_cur to enum resctrl_kernel_mode in resctrl_kmode_cfg. Moved the resctrl_kmode_cfg to filesystem code.

---
 fs/resctrl/internal.h   | 12 ++++++++++++
 fs/resctrl/rdtgroup.c   | 23 +++++++++++++++++++++++
 include/linux/resctrl.h | 10 ++++++++++
 3 files changed, 45 insertions(+)
fs/resctrl/internal.h +0 -0
index 48af75b9dc85..178126bb2da5 100644

fs/resctrl/internal.h struct mbm_state { · line 318

Quoted 5 lines
fs/resctrl/internal.h +2 -0
@@ -314,6 +314,18 @@ struct mbm_state {
 	u32	prev_bw;
 };
 
+/**
+ * struct resctrl_kmode_cfg - Kernel-mode policy snapshot from architecture

"policy snapshot"? what does this mean? This is not just from architecture either.

fs/resctrl/internal.h struct mbm_state { · line 321

Quoted 3 lines
fs/resctrl/internal.h +3 -0
+ * @kmode:	Bitmap of supported &enum resctrl_kernel_mode values. Each
+ *		supported mode is represented by BIT(mode).
+ * @kmode_cur:	Currently selected kernel-mode policy.

How about "Active kernel mode"?

fs/resctrl/internal.h struct mbm_state { · line 322

Quoted 1 line
fs/resctrl/internal.h +1 -0
+ * @k_rdtgrp:	Resource group backing global-assign modes when applicable;

(stray semi-colon)

fs/resctrl/internal.h struct mbm_state { · line 325

Quoted 3 lines
fs/resctrl/internal.h +3 -0
+ */
+struct resctrl_kmode_cfg {
+	unsigned long			kmode;

How about "kmode_sup" to complement the "kmode_cur"?

To make it obvious this is a bitmap you can use something like:
DECLARE_BITMAP(kmode_sup, RESCTRL_NUM_KERNEL_MODES)

Quoted 11 lines
fs/resctrl/internal.h +3 -0
+	enum resctrl_kernel_mode	kmode_cur;
+	struct rdtgroup			*k_rdtgrp;
+};
 extern struct mutex rdtgroup_mutex;
 
 static inline const char *rdt_kn_name(const struct kernfs_node *kn)
fs/resctrl/rdtgroup.c +0 -0
index cc9966ff6cdf..0ee0dfaf9065 100644

fs/resctrl/rdtgroup.c static void mon_put_kn_priv(void); · line 83

Quoted 6 lines
fs/resctrl/rdtgroup.c +3 -0
@@ -78,6 +78,16 @@ static void mon_put_kn_priv(void);
 
 struct dentry *debugfs_resctrl;
 
+/*
+ * Global kernel-mode resctrl policy. Architectures add supported modes before
+ * resctrl is mounted; @kmode_cur tracks the active policy after user selection.

ah - above it is referred to as "active". I find "active" to be more descriptive than "selected" as highlighted above. The "after user selection" seems distracting. "@kmode_cur is the active kernel mode" is all that is necessary, no?

fs/resctrl/rdtgroup.c static void mon_put_kn_priv(void); · line 89

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+ */
+static struct resctrl_kmode_cfg resctrl_kcfg = {
+	.kmode = BIT(INHERIT_CTRL_AND_MON),
+	.kmode_cur = INHERIT_CTRL_AND_MON,
+	.k_rdtgrp = NULL
+};

This initialization needs to be reconsidered to take into account that system may not support allocation or monitoring.

Reinette

#43 lore raw

Re: [RESEND PATCH v4 06/15] fs/resctrl: Introduce resctrl_set_kmode_support() to initialize supported modes

Hi Reinette,

Quoted 6 lines · Reinette Chatre

Hi Babu,

Quoted 1 line · Babu Moger

Architectures need a way to advertise which kernel-mode resctrl policies

"kernel-mode resctrl policies" -> "kernel modes"?

Sure.

Quoted 6 lines
Quoted 2 lines

they support before generic resctrl exposes those policies through the

"policies" -> "modes"
(this is related to the earlier "use consistent terminology comment" I will stop highlighting instances)

Sure.

Quoted 11 lines
Quoted 8 lines

filesystem.

Add the struct resctrl_kmode_cfg to define the default mode statically, and introduce resctrl_set_kmode_support() so architecture code can register supported kernel-mode policies during resctrl initialization. The INHERIT_CTRL_AND_MON policy is supported by default, so architectures only need to register any additional modes.

Please keep changelog high level and not describe the code that can be seen from patch. When doing so, please write in imperative tone.

Yes.

Quoted 22 lines
Quoted 22 lines

---
v4: New patch to initialize supported kernel-mode's.
https://lore.kernel.org/lkml/[email protected]/
Changed the kmode_cur to enum resctrl_kernel_mode in resctrl_kmode_cfg. Moved the resctrl_kmode_cfg to filesystem code.

---
  fs/resctrl/internal.h   | 12 ++++++++++++
  fs/resctrl/rdtgroup.c   | 23 +++++++++++++++++++++++
  include/linux/resctrl.h | 10 ++++++++++
  3 files changed, 45 insertions(+)
fs/resctrl/internal.h +0 -0
index 48af75b9dc85..178126bb2da5 100644
@@ -314,6 +314,18 @@ struct mbm_state {
  	u32	prev_bw;
  };
 
Quoted 3 lines

fs/resctrl/internal.h struct mbm_state { · line 318

Quoted 2 lines
fs/resctrl/internal.h +2 -0
+/**
+ * struct resctrl_kmode_cfg - Kernel-mode policy snapshot from architecture

"policy snapshot"? what does this mean? This is not just from architecture either.

struct resctrl_kmode_cfg - Resctrl kernel mode support and active state

Quoted 6 lines

fs/resctrl/internal.h struct mbm_state { · line 321

Quoted 4 lines
fs/resctrl/internal.h +3 -0
+ * @kmode:	Bitmap of supported &enum resctrl_kernel_mode values. Each
+ *		supported mode is represented by BIT(mode).
+ * @kmode_cur:	Currently selected kernel-mode policy.

How about "Active kernel mode"?

Sure.

Quoted 4 lines

fs/resctrl/internal.h struct mbm_state { · line 322

Quoted 2 lines
fs/resctrl/internal.h +1 -0
+ * @k_rdtgrp:	Resource group backing global-assign modes when applicable;

(stray semi-colon)

Ack.

Quoted 6 lines

fs/resctrl/internal.h struct mbm_state { · line 325

Quoted 4 lines
fs/resctrl/internal.h +3 -0
+ */
+struct resctrl_kmode_cfg {
+	unsigned long			kmode;

How about "kmode_sup" to complement the "kmode_cur"?

Sure.

Quoted 3 lines

To make it obvious this is a bitmap you can use something like:
DECLARE_BITMAP(kmode_sup, RESCTRL_NUM_KERNEL_MODES)

Sure. If the code remains same.

Quoted 16 lines
Quoted 16 lines
fs/resctrl/internal.h +3 -0
+	enum resctrl_kernel_mode	kmode_cur;
+	struct rdtgroup			*k_rdtgrp;
+};
  extern struct mutex rdtgroup_mutex;
 
  static inline const char *rdt_kn_name(const struct kernfs_node *kn)
fs/resctrl/rdtgroup.c +0 -0
index cc9966ff6cdf..0ee0dfaf9065 100644
@@ -78,6 +78,16 @@ static void mon_put_kn_priv(void);
 
  struct dentry *debugfs_resctrl;
 
Quoted 7 lines

fs/resctrl/rdtgroup.c static void mon_put_kn_priv(void); · line 83

Quoted 3 lines
fs/resctrl/rdtgroup.c +3 -0
+/*
+ * Global kernel-mode resctrl policy. Architectures add supported modes before
+ * resctrl is mounted; @kmode_cur tracks the active policy after user selection.

ah - above it is referred to as "active". I find "active" to be more descriptive than "selected" as highlighted above. The "after user selection" seems distracting. "@kmode_cur is the active kernel mode" is all that is necessary, no?

Sure.

Quoted 11 lines

fs/resctrl/rdtgroup.c static void mon_put_kn_priv(void); · line 89

Quoted 7 lines
fs/resctrl/rdtgroup.c +6 -0
+ */
+static struct resctrl_kmode_cfg resctrl_kcfg = {
+	.kmode = BIT(INHERIT_CTRL_AND_MON),
+	.kmode_cur = INHERIT_CTRL_AND_MON,
+	.k_rdtgrp = NULL
+};

This initialization needs to be reconsidered to take into account that system may not support allocation or monitoring.

Yes. We may need to change it to dynamic initialization than static.

Thanks
Babu

author reviewer
#44 lore raw

PATCH RESEND v4 7/15 x86/resctrl: Expose the supported PLZA kernel-mode policies during init

In reply to Babu Moger

Generic resctrl exposes kernel-mode policy options via sysfs only after architectures indicate the set of supported policies using resctrl_set_kmode_support().

On AMD systems, Privilege Level Zero Association (PLZA) provides two global assignment modes:

- GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU: Assigns the resource allocation for kernel work; but monitoring is inherited from the user task.
- GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU: Assigns a dedicated resource allocation and monitoring for kernel work.

Expose these modes during resource discovery when PLZA is available.

---
v4: New patch to set the supported features during arch init.

---
 arch/x86/kernel/cpu/resctrl/core.c | 6 ++++++
 1 file changed, 6 insertions(+)
arch/x86/kernel/cpu/resctrl/core.c +6 -0
index 27e09cded829..df7e19fe6007 100644
@@ -962,6 +962,9 @@ static __init bool get_rdt_alloc_resources(void)
 	if (get_slow_mem_config())
 		ret = true;
 
+	if (ret && rdt_cpu_has(X86_FEATURE_PLZA))
+		resctrl_set_kmode_support(GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU);
+
 	return ret;
 }
 
@@ -988,6 +991,9 @@ static __init bool get_rdt_mon_resources(void)
 	if (!ret)
 		return false;
 
+	if (rdt_cpu_has(X86_FEATURE_PLZA))
+		resctrl_set_kmode_support(GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU);
+
 	return !rdt_get_l3_mon_config(r);
 }
 
Signature · 1 line
2.43.0
author reviewer
#45 lore raw

Re: [RESEND PATCH v4 07/15] x86/resctrl: Expose the supported PLZA kernel-mode policies during init

Quoted 36 lines · Babu Moger

Generic resctrl exposes kernel-mode policy options via sysfs only after architectures indicate the set of supported policies using resctrl_set_kmode_support().

On AMD systems, Privilege Level Zero Association (PLZA) provides two global assignment modes:

- GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU: Assigns the resource allocation for kernel work; but monitoring is inherited from the user task.
- GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU: Assigns a dedicated resource allocation and monitoring for kernel work.

Expose these modes during resource discovery when PLZA is available.

---
v4: New patch to set the supported features during arch init.

---
  arch/x86/kernel/cpu/resctrl/core.c | 6 ++++++
  1 file changed, 6 insertions(+)
arch/x86/kernel/cpu/resctrl/core.c +3 -0
index 27e09cded829..df7e19fe6007 100644
@@ -962,6 +962,9 @@ static __init bool get_rdt_alloc_resources(void)
  	if (get_slow_mem_config())
  		ret = true;
 
+	if (ret && rdt_cpu_has(X86_FEATURE_PLZA))
+		resctrl_set_kmode_support(GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU);
+
  	return ret;
  }
 

arch/x86/kernel/cpu/resctrl/core.c static __init bool get_rdt_mon_resources(void) · line 999

Quoted 9 lines
arch/x86/kernel/cpu/resctrl/core.c +3 -0
@@ -988,6 +991,9 @@ static __init bool get_rdt_mon_resources(void)
  	if (!ret)
  		return false;
 
+	if (rdt_cpu_has(X86_FEATURE_PLZA))
+		resctrl_set_kmode_support(GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU);
+
  	return !rdt_get_l3_mon_config(r);
  }
 

Sashiko reported:

https://sashiko.dev/#/patchset/cover.1783461016.git.babu.moger%40amd.com?part=7

--- Patch [7]: [RESEND PATCH v4 07/15] x86/resctrl: Expose the supported PLZA kernel-mode policies during init --- commit 6d029d053cc0d67da93c0b4ae5419b85cfaeb5aa
Author: Babu Moger <[email protected]>
x86/resctrl: Expose the supported PLZA kernel-mode policies during init
This commit updates the generic resctrl subsystem to expose PLZA
kernel-mode policies during resource discovery. When X86_FEATURE_PLZA
is present, it sets up support for GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU
and GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU policies.

Quoted 4 lines
arch/x86/kernel/cpu/resctrl/core.c +0 -0
index 27e09cded8299..df7e19fe60078 100644

[ ... ]

arch/x86/kernel/cpu/resctrl/core.c static __init bool get_rdt_mon_resources(void) · line 995

Quoted 6 lines
arch/x86/kernel/cpu/resctrl/core.c +2 -0
@@ -988,6 +991,9 @@ static __init bool get_rdt_mon_resources(void)
 	if (!ret)
 		return false;
 
+	if (rdt_cpu_has(X86_FEATURE_PLZA))
+		resctrl_set_kmode_support(GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU);

Is it possible for GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU to be advertised here even if resource allocation features are disabled on the system? Because this policy assigns a dedicated resource allocation for kernel work, should this check verify rdt_alloc_capable before exposing the policy? If allocation is disabled via kernel command-line parameters (like rdt=!l3cat), but monitoring features are present, it seems like we might expose an allocation-dependent policy to userspace incorrectly.
------------------------------------------------------------------------

PLZA is really meaningful when allocation is enabled. I think it would be better to check rdt_alloc_capable before enabling GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU. Will add the check.

if (rdt_alloc_capable && rdt_cpu_has(X86_FEATURE_PLZA)) resctrl_set_kmode_support(GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU);

Thanks
Babu

author reviewer
#46 lore raw

PATCH RESEND v4 8/15 fs/resctrl: Add interface to display supported and active kernel-mode policy

In reply to Babu Moger

Kernel-mode resctrl policies define how kernel work is associated with resource allocation and monitoring relative to the user task. Generic resctrl tracks the supported policies, the active policy, and the resctrl group backing any global assignment policy. However, this information is not exposed to user space.

Introduce a new resctrl file, info/kernel_mode, to expose the global kernel-mode policy and its associated resource group (when applicable). This read-only sysfs file lists all supported policies, one per line, and highlights the active policy using square brackets.

---
v4: Fixed the display of inherit_ctrl_and_mon policy. It is not
associated with any group.
Added "uninitialized" for the non-active group. Rewrote the changelog.

v3: New patch to handle the changed interface file info/kernel_mode.
Changed the group name to "none" if kmode binding is not done. Reinette suggested "uninitialized". "none" seemed more relevent.

---
 fs/resctrl/rdtgroup.c | 91 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)
fs/resctrl/rdtgroup.c +91 -0
index 0ee0dfaf9065..346aa4df62a4 100644
@@ -1012,6 +1012,90 @@ static int rdt_last_cmd_status_show(struct kernfs_open_file *of,
 	return 0;
 }
 
+/* Sysfs lines for info/kernel_mode; indexed by enum resctrl_kernel_mode */
+static const char * const resctrl_mode_str[] = {
+	[INHERIT_CTRL_AND_MON]				= "inherit_ctrl_and_mon",
+	[GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU]	= "global_assign_ctrl_inherit_mon_per_cpu",
+	[GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU]		= "global_assign_ctrl_assign_mon_per_cpu",
+};
+
+static_assert(ARRAY_SIZE(resctrl_mode_str) == RESCTRL_NUM_KERNEL_MODES);
+
+/**
+ * resctrl_kernel_mode_show() - Display supported and active kernel-mode policies
+ * @of: kernfs open file
+ * @seq: output seq_file
+ * @v: unused
+ *
+ * Displays one line per mode set in resctrl_kcfg.kmode. Bracket the active
+ * policy (resctrl_kcfg.kmode_cur).
+ *
+ * INHERIT_CTRL_AND_MON is displayed as "[inherit_ctrl_and_mon]" when active
+ * or "inherit_ctrl_and_mon" when supported but inactive, with no :group=
+ * suffix in either case.
+ *
+ * Global-assign modes append :group=. An inactive mode is emitted as
+ * "<mode>:group=uninitialized". An active mode with a bound group is emitted
+ * as "[<mode>:group=<ctrl>/<mon>/]", where <ctrl>/<mon>/ is derived from
+ * resctrl_kcfg.k_rdtgrp.
+ *
+ * Return: 0 on success, or -ENOENT on error.
+ */
+static int resctrl_kernel_mode_show(struct kernfs_open_file *of,
+				    struct seq_file *seq, void *v)
+{
+	enum resctrl_kernel_mode mode;
+	struct rdtgroup *rdtgrp;
+	const char *ctrl, *mon;
+	bool active;
+	int ret = 0;
+
+	mutex_lock(&rdtgroup_mutex);
+	for (mode = 0; mode < RESCTRL_NUM_KERNEL_MODES; mode++) {
+		if (!test_bit(mode, &resctrl_kcfg.kmode))
+			continue;
+
+		active = (resctrl_kcfg.kmode_cur == mode);
+
+		if (mode == INHERIT_CTRL_AND_MON) {
+			seq_printf(seq, active ? "[%s]\n" : "%s\n",
+				   resctrl_mode_str[mode]);
+			continue;
+		}
+
+		if (!active) {
+			seq_printf(seq, "%s:group=uninitialized\n",
+				   resctrl_mode_str[mode]);
+			continue;
+		}
+
+		/*
+		 * There should be a valid group when any of the global
+		 * assign mode is active; otherwise, report an error.
+		 */
+		rdtgrp = resctrl_kcfg.k_rdtgrp;
+		if (!rdtgrp) {
+			ret = -ENOENT;
+			goto out_unlock;
+		}
+
+		ctrl = "";
+		mon = "";
+		if (rdtgrp->type == RDTMON_GROUP) {
+			ctrl = rdt_kn_name(rdtgrp->mon.parent->kn);
+			mon = rdt_kn_name(rdtgrp->kn);
+		} else {
+			ctrl = rdt_kn_name(rdtgrp->kn);
+		}
+		seq_printf(seq, "[%s:group=%s/%s/]\n",
+			   resctrl_mode_str[mode], ctrl, mon);
+	}
+
+out_unlock:
+	mutex_unlock(&rdtgroup_mutex);
+	return ret;
+}
+
 void *rdt_kn_parent_priv(struct kernfs_node *kn)
 {
 	/*
@@ -1915,6 +1999,13 @@ static struct rftype res_common_files[] = {
 		.seq_show	= rdt_last_cmd_status_show,
 		.fflags		= RFTYPE_TOP_INFO,
 	},
+	{
+		.name		= "kernel_mode",
+		.mode		= 0444,
+		.kf_ops		= &rdtgroup_kf_single_ops,
+		.seq_show	= resctrl_kernel_mode_show,
+		.fflags		= RFTYPE_TOP_INFO,
+	},
 	{
 		.name		= "mbm_assign_on_mkdir",
 		.mode		= 0644,
Signature · 1 line
2.43.0
maintainer
#47 lore raw

Re: [RESEND PATCH v4 08/15] fs/resctrl: Add interface to display supported and active kernel-mode policy

Hi Babu,

Quoted 10 lines · Babu Moger

Kernel-mode resctrl policies define how kernel work is associated with resource allocation and monitoring relative to the user task. Generic resctrl tracks the supported policies, the active policy, and the resctrl group backing any global assignment policy. However, this information is not exposed to user space.

Introduce a new resctrl file, info/kernel_mode, to expose the global kernel-mode policy and its associated resource group (when applicable). This read-only sysfs file lists all supported policies, one per line, and highlights the active policy using square brackets.

(please rewrite with consistent terms)

Quoted 25 lines
fs/resctrl/rdtgroup.c +20 -0
+/**
+ * resctrl_kernel_mode_show() - Display supported and active kernel-mode policies
+ * @of: kernfs open file
+ * @seq: output seq_file
+ * @v: unused
+ *
+ * Displays one line per mode set in resctrl_kcfg.kmode. Bracket the active
+ * policy (resctrl_kcfg.kmode_cur).
+ *
+ * INHERIT_CTRL_AND_MON is displayed as "[inherit_ctrl_and_mon]" when active
+ * or "inherit_ctrl_and_mon" when supported but inactive, with no :group=
+ * suffix in either case.
+ *
+ * Global-assign modes append :group=. An inactive mode is emitted as
+ * "<mode>:group=uninitialized". An active mode with a bound group is emitted
+ * as "[<mode>:group=<ctrl>/<mon>/]", where <ctrl>/<mon>/ is derived from
+ * resctrl_kcfg.k_rdtgrp.
+ *
+ * Return: 0 on success, or -ENOENT on error.
+ */

fs/resctrl/rdtgroup.c static int rdt_last_cmd_status_show(struct kernfs_open_file *of, · line 1053

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+static int resctrl_kernel_mode_show(struct kernfs_open_file *of,
+				    struct seq_file *seq, void *v)
+{
+	enum resctrl_kernel_mode mode;
+	struct rdtgroup *rdtgrp;
+	const char *ctrl, *mon;
+	bool active;
+	int ret = 0;
+
+	mutex_lock(&rdtgroup_mutex);

The changes to make resctrl more robust have since been merged. Please consider:
2d77f9768850 ("fs/resctrl: Prevent deadlock and use-after-free in info file handlers")

When you rebase, please use the new info_kn_lock()/info_kn_unlock() helpers.

Quoted 11 lines
fs/resctrl/rdtgroup.c +11 -0
+	for (mode = 0; mode < RESCTRL_NUM_KERNEL_MODES; mode++) {
+		if (!test_bit(mode, &resctrl_kcfg.kmode))
+			continue;
+
+		active = (resctrl_kcfg.kmode_cur == mode);
+
+		if (mode == INHERIT_CTRL_AND_MON) {
+			seq_printf(seq, active ? "[%s]\n" : "%s\n",
+				   resctrl_mode_str[mode]);
+			continue;
+		}

fs/resctrl/rdtgroup.c static int rdt_last_cmd_status_show(struct kernfs_open_file *of, · line 1074

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+
+		if (!active) {
+			seq_printf(seq, "%s:group=uninitialized\n",
+				   resctrl_mode_str[mode]);
+			continue;
+		}
+
+		/*
+		 * There should be a valid group when any of the global
+		 * assign mode is active; otherwise, report an error.

This would indicate a resctrl bug, no?

fs/resctrl/rdtgroup.c static int rdt_last_cmd_status_show(struct kernfs_open_file *of, · line 1079

Quoted 5 lines
fs/resctrl/rdtgroup.c +5 -0
+		 */
+		rdtgrp = resctrl_kcfg.k_rdtgrp;
+		if (!rdtgrp) {
+			ret = -ENOENT;
+			goto out_unlock;

If this fails there needs to be content in last_cmd_status. Otherwise this fails and then last_cmd_status reads "ok" or worse .. an old failure message.

Quoted 26 lines
fs/resctrl/rdtgroup.c +19 -0
+		}
+
+		ctrl = "";
+		mon = "";
+		if (rdtgrp->type == RDTMON_GROUP) {
+			ctrl = rdt_kn_name(rdtgrp->mon.parent->kn);
+			mon = rdt_kn_name(rdtgrp->kn);
+		} else {
+			ctrl = rdt_kn_name(rdtgrp->kn);
+		}
+		seq_printf(seq, "[%s:group=%s/%s/]\n",
+			   resctrl_mode_str[mode], ctrl, mon);
+	}
+
+out_unlock:
+	mutex_unlock(&rdtgroup_mutex);
+	return ret;
+}
+
 void *rdt_kn_parent_priv(struct kernfs_node *kn)
 {
 	/*
@@ -1915,6 +1999,13 @@ static struct rftype res_common_files[] = {
 		.seq_show	= rdt_last_cmd_status_show,
 		.fflags		= RFTYPE_TOP_INFO,
 	},

fs/resctrl/rdtgroup.c static struct rftype res_common_files[] = { · line 2011

Quoted 10 lines
fs/resctrl/rdtgroup.c +7 -0
+	{
+		.name		= "kernel_mode",
+		.mode		= 0444,
+		.kf_ops		= &rdtgroup_kf_single_ops,
+		.seq_show	= resctrl_kernel_mode_show,
+		.fflags		= RFTYPE_TOP_INFO,
+	},
 	{
 		.name		= "mbm_assign_on_mkdir",
 		.mode		= 0644,

Reinette

#48 lore raw

Re: [RESEND PATCH v4 08/15] fs/resctrl: Add interface to display supported and active kernel-mode policy

Hi Reinette,

Quoted 9 lines · Reinette Chatre

Hi Babu,

Quoted 6 lines · Babu Moger

Kernel-mode resctrl policies define how kernel work is associated with resource allocation and monitoring relative to the user task. Generic resctrl tracks the supported policies, the active policy, and the resctrl group backing any global assignment policy. However, this information is not exposed to user space.

Quoted 7 lines
Quoted 4 lines

Introduce a new resctrl file, info/kernel_mode, to expose the global kernel-mode policy and its associated resource group (when applicable). This read-only sysfs file lists all supported policies, one per line, and highlights the active policy using square brackets.

(please rewrite with consistent terms)

Sure.

Quoted 39 lines
Quoted 25 lines
fs/resctrl/rdtgroup.c +20 -0
+/**
+ * resctrl_kernel_mode_show() - Display supported and active kernel-mode policies
+ * @of: kernfs open file
+ * @seq: output seq_file
+ * @v: unused
+ *
+ * Displays one line per mode set in resctrl_kcfg.kmode. Bracket the active
+ * policy (resctrl_kcfg.kmode_cur).
+ *
+ * INHERIT_CTRL_AND_MON is displayed as "[inherit_ctrl_and_mon]" when active
+ * or "inherit_ctrl_and_mon" when supported but inactive, with no :group=
+ * suffix in either case.
+ *
+ * Global-assign modes append :group=. An inactive mode is emitted as
+ * "<mode>:group=uninitialized". An active mode with a bound group is emitted
+ * as "[<mode>:group=<ctrl>/<mon>/]", where <ctrl>/<mon>/ is derived from
+ * resctrl_kcfg.k_rdtgrp.
+ *
+ * Return: 0 on success, or -ENOENT on error.
+ */

fs/resctrl/rdtgroup.c static int rdt_last_cmd_status_show(struct kernfs_open_file *of, · line 1053

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+static int resctrl_kernel_mode_show(struct kernfs_open_file *of,
+				    struct seq_file *seq, void *v)
+{
+	enum resctrl_kernel_mode mode;
+	struct rdtgroup *rdtgrp;
+	const char *ctrl, *mon;
+	bool active;
+	int ret = 0;
+
+	mutex_lock(&rdtgroup_mutex);

The changes to make resctrl more robust have since been merged. Please consider:
2d77f9768850 ("fs/resctrl: Prevent deadlock and use-after-free in info file handlers")

Quoted 1 line

When you rebase, please use the new info_kn_lock()/info_kn_unlock() helpers.

Sure. Will do.

Quoted 16 lines
Quoted 16 lines
fs/resctrl/rdtgroup.c +15 -0
+	for (mode = 0; mode < RESCTRL_NUM_KERNEL_MODES; mode++) {
+		if (!test_bit(mode, &resctrl_kcfg.kmode))
+			continue;
+
+		active = (resctrl_kcfg.kmode_cur == mode);
+
+		if (mode == INHERIT_CTRL_AND_MON) {
+			seq_printf(seq, active ? "[%s]\n" : "%s\n",
+				   resctrl_mode_str[mode]);
+			continue;
+		}
+
+		if (!active) {
+			seq_printf(seq, "%s:group=uninitialized\n",
+				   resctrl_mode_str[mode]);
Quoted 8 lines

fs/resctrl/rdtgroup.c static int rdt_last_cmd_status_show(struct kernfs_open_file *of, · line 1074

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+			continue;
+		}
+
+		/*
+		 * There should be a valid group when any of the global
+		 * assign mode is active; otherwise, report an error.

This would indicate a resctrl bug, no?

Yes.

Quoted 9 lines

fs/resctrl/rdtgroup.c static int rdt_last_cmd_status_show(struct kernfs_open_file *of, · line 1079

Quoted 6 lines
fs/resctrl/rdtgroup.c +5 -0
+		 */
+		rdtgrp = resctrl_kcfg.k_rdtgrp;
+		if (!rdtgrp) {
+			ret = -ENOENT;
+			goto out_unlock;

If this fails there needs to be content in last_cmd_status. Otherwise this fails and then last_cmd_status reads "ok" or worse .. an old failure message.

if (WARN_ON(!rdtgrp)) {
	rdt_last_cmd_puts("Invalid kernel mode group\n");
	ret = -ENOENT;
	goto out_unlock;
}

Thanks
Babu

maintainer
#49 lore raw

Re: [RESEND PATCH v4 08/15] fs/resctrl: Add interface to display supported and active kernel-mode policy

Hi Babu,

Quoted 2 lines · Babu
Quoted 1 line · Reinette Chatre

On 7/7/26 2:50 PM, Babu Moger wrote:

...

Quoted 6 lines
Quoted 6 lines
Quoted 5 lines

+         */
+        rdtgrp = resctrl_kcfg.k_rdtgrp;
+        if (!rdtgrp) {
+            ret = -ENOENT;
+            goto out_unlock;

Quoted 8 lines
Quoted 2 lines

If this fails there needs to be content in last_cmd_status. Otherwise this fails and then last_cmd_status reads "ok" or worse .. an old failure message.

if (WARN_ON(!rdtgrp)) { rdt_last_cmd_puts("Invalid kernel mode group\n"); ret = -ENOENT;
    goto out_unlock;
}

It is not clear to me why the WARN_ON() was added. Is the resource group not being associated with kernel mode not a legitimate scenario if the kernel mode group was re-assigned while the reader of this file was blocked on the mutex?

Reinette

author reviewer
#50 lore raw

Re: [RESEND PATCH v4 08/15] fs/resctrl: Add interface to display supported and active kernel-mode policy

Hi Reinette,

Quoted 17 lines · Reinette Chatre

Hi Babu,

Quoted 2 lines · Babu
Quoted 1 line · Reinette Chatre

On 7/7/26 2:50 PM, Babu Moger wrote:

...

Quoted 9 lines
Quoted 8 lines
Quoted 5 lines

+         */
+        rdtgrp = resctrl_kcfg.k_rdtgrp;
+        if (!rdtgrp) {
+            ret = -ENOENT;
+            goto out_unlock;

If this fails there needs to be content in last_cmd_status. Otherwise this fails and then last_cmd_status reads "ok" or worse .. an old failure message.

Quoted 9 lines
Quoted 5 lines

if (WARN_ON(!rdtgrp)) {
    rdt_last_cmd_puts("Invalid kernel mode group\n"); ret = -ENOENT;
    goto out_unlock;
}

It is not clear to me why the WARN_ON() was added. Is the resource group not being associated with kernel mode not a legitimate scenario if the kernel mode group was re-assigned while the reader of this file was blocked on the mutex?

A valid group is required whenever any global mode is enabled. Reaching this condition without one is unexpected and should be treated as a bug.

To help catch this, I added a WARN_ON() to log the issue. I think updating last_cmd_status is reasonable as well and should provide the necessary user-visible error indication.

thanks
Babu

maintainer
#51 lore raw

Re: [RESEND PATCH v4 08/15] fs/resctrl: Add interface to display supported and active kernel-mode policy

Hi Babu,

Quoted 29 lines · Babu Moger

Hi Reinette,

Quoted 17 lines · Reinette Chatre

Hi Babu,

Quoted 2 lines · Babu
Quoted 1 line · Reinette Chatre

On 7/7/26 2:50 PM, Babu Moger wrote:

...

Quoted 9 lines
Quoted 8 lines
Quoted 5 lines

+         */
+        rdtgrp = resctrl_kcfg.k_rdtgrp;
+        if (!rdtgrp) {
+            ret = -ENOENT;
+            goto out_unlock;

If this fails there needs to be content in last_cmd_status. Otherwise this fails and then last_cmd_status reads "ok" or worse .. an old failure message.

Quoted 9 lines
Quoted 5 lines

if (WARN_ON(!rdtgrp)) { rdt_last_cmd_puts("Invalid kernel mode group\n"); ret = -ENOENT;
     goto out_unlock;
}

It is not clear to me why the WARN_ON() was added. Is the resource group not being associated with kernel mode not a legitimate scenario if the kernel mode group was re-assigned while the reader of this file was blocked on the mutex?

Quoted 7 lines

A valid group is required whenever any global mode is enabled. Reaching this condition without one is unexpected and should be treated as a bug.

To help catch this, I added a WARN_ON() to log the issue. I think updating last_cmd_status is reasonable as well and should provide the necessary user-visible error indication.

ah - thanks. I misread this snippet as an interaction with a resource group's files.

Reinette

author reviewer
#52 lore raw

PATCH RESEND v4 9/15 fs/resctrl: Introduce kmode_cpus/kmode_cpus_list per rdtgroup

In reply to Babu Moger

Kernel-mode resctrl policies allow kernel work to be associated with a specific rdtgroup, optionally restricted to a subset of online CPUs.

While user space can query the active kernel-mode policy and its associated rdtgroup through info/kernel_mode, it currently lacks visibility into the CPU scope of that binding.

Introduce read-only kmode_cpus and kmode_cpus_list files for each rdtgroup. These expose rdtgrp->kmode_cpu_mask in both bitmap and range-list formats, consistent with the existing cpus and cpus_list interfaces.

---
v4: Rewrote the change to be generic.

v3: New patch to add "kmode_cpus" and "kmode_cpus_list" to support
kernel_modes.

---
 fs/resctrl/internal.h |  4 ++++
 fs/resctrl/rdtgroup.c | 46 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)
fs/resctrl/internal.h +4 -0
index 178126bb2da5..12db6933bc54 100644
@@ -216,6 +216,8 @@ struct mongroup {
  * @mon:			mongroup related data
  * @mode:			mode of resource group
  * @mba_mbps_event:		input monitoring event id when mba_sc is enabled
+ * @kmode:			true if this group is bound to a kernel-mode policy
+ * @kmode_cpu_mask:		CPU scope for this group's kernel-mode binding
  * @plr:			pseudo-locked region
  */
 struct rdtgroup {
@@ -229,6 +231,8 @@ struct rdtgroup {
 	struct mongroup			mon;
 	enum rdtgrp_mode		mode;
 	enum resctrl_event_id		mba_mbps_event;
+	bool				kmode;
+	struct cpumask			kmode_cpu_mask;
 	struct pseudo_lock_region	*plr;
 };
 
fs/resctrl/rdtgroup.c +46 -0

58 lines not on this page · raw message

Signature · 1 line
2.43.0
maintainer
#53 lore raw

Re: [RESEND PATCH v4 09/15] fs/resctrl: Introduce kmode_cpus/kmode_cpus_list per rdtgroup

Hi Babu,

Quoted 8 lines · Babu Moger

Kernel-mode resctrl policies allow kernel work to be associated with a specific rdtgroup, optionally restricted to a subset of online CPUs.

While user space can query the active kernel-mode policy and its associated rdtgroup through info/kernel_mode, it currently lacks visibility into the CPU scope of that binding.

Introduce read-only kmode_cpus and kmode_cpus_list files for each rdtgroup.

I think it will be easier to follow if this is deferred to not create these files in all resource groups by default. Instead, at the time they are created it should be obvious that they will only be visible in resource group associated with the active kernel mode.

Quoted 13 lines

These expose rdtgrp->kmode_cpu_mask in both bitmap and range-list formats, consistent with the existing cpus and cpus_list interfaces.

---

fs/resctrl/internal.h +0 -0
index 178126bb2da5..12db6933bc54 100644

fs/resctrl/internal.h struct mongroup { · line 220

Quoted 5 lines
fs/resctrl/internal.h +2 -0
@@ -216,6 +216,8 @@ struct mongroup {
  * @mon:			mongroup related data
  * @mode:			mode of resource group
  * @mba_mbps_event:		input monitoring event id when mba_sc is enabled
+ * @kmode:			true if this group is bound to a kernel-mode policy
+ * @kmode_cpu_mask:		CPU scope for this group's kernel-mode binding

"CPU scope" could be interpreted in various ways here. Could it be more specific to say something like "CPUs on which kernel mode is active"?

Quoted 29 lines
fs/resctrl/internal.h +2 -0
  * @plr:			pseudo-locked region
  */
 struct rdtgroup {
@@ -229,6 +231,8 @@ struct rdtgroup {
 	struct mongroup			mon;
 	enum rdtgrp_mode		mode;
 	enum resctrl_event_id		mba_mbps_event;
+	bool				kmode;
+	struct cpumask			kmode_cpu_mask;
 	struct pseudo_lock_region	*plr;
 };
 
fs/resctrl/rdtgroup.c +9 -0
index 346aa4df62a4..0d5c94169d03 100644
@@ -392,6 +392,37 @@ static int rdtgroup_cpus_show(struct kernfs_open_file *of,
 	return ret;
 }
 
+/*
+ * Display per-rdtgroup CPU bindings for kernel-mode enabled groups.
+ * Supports both "kmode_cpus" (bitmap format) and "kmode_cpus_list"
+ * (range list format); the output format is selected accordingly.
+ *
+ * Returns -ENOENT if the group has been deleted, and -ENODEV for
+ * pseudo-locked groups, which cannot host a kernel-mode binding.
+ */
+static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of,

fs/resctrl/rdtgroup.c static int rdtgroup_cpus_show(struct kernfs_open_file *of, · line 413

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+				    struct seq_file *s, void *v)
+{
+	struct rdtgroup *rdtgrp;
+	int ret = 0;
+
+	rdtgrp = rdtgroup_kn_lock_live(of->kn);
+
+	if (rdtgrp) {
+		if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) {
+			ret = -ENODEV;

sashiko also pointed something related out but it is not clear to me how the different group modes are planned to be accommodated. I think it should be possible to avoid sprinkling these mode checks into user space interactions if it is made explicit that (a) at the time a group is assigned to a kernel mode that group is required to be "shareable", and (b) it is not allowed to change the mode of a group that is assigned to a kernel mode.

Apart from that I do not think a test like this is sufficient to capture the various scenarios that may occur. For example, while waiting for the lock the group assigned to the kernel mode could have been re-assigned. Could a test on rdtgrp->kmode be more robust?

Quoted 27 lines
fs/resctrl/rdtgroup.c +20 -0
+		} else {
+			seq_printf(s, is_cpu_list(of) ? "%*pbl\n" : "%*pb\n",
+				   cpumask_pr_args(&rdtgrp->kmode_cpu_mask));
+		}
+	} else {
+		ret = -ENOENT;
+	}
+	rdtgroup_kn_unlock(of->kn);
+
+	return ret;
+}
+
 /*
  * Update the PGR_ASSOC MSR on all cpus in @cpu_mask,
  *
@@ -2181,6 +2212,21 @@ static struct rftype res_common_files[] = {
 		.flags		= RFTYPE_FLAGS_CPUS_LIST,
 		.fflags		= RFTYPE_BASE,
 	},
+	{
+		.name		= "kmode_cpus",
+		.mode		= 0444,
+		.kf_ops		= &rdtgroup_kf_single_ops,
+		.seq_show	= rdtgroup_kmode_cpus_show,
+		.fflags		= RFTYPE_BASE,
+	},
+	{

fs/resctrl/rdtgroup.c static struct rftype res_common_files[] = { · line 2232

Quoted 10 lines
fs/resctrl/rdtgroup.c +7 -0
+		.name		= "kmode_cpus_list",
+		.mode		= 0444,
+		.kf_ops		= &rdtgroup_kf_single_ops,
+		.seq_show	= rdtgroup_kmode_cpus_show,
+		.flags		= RFTYPE_FLAGS_CPUS_LIST,
+		.fflags		= RFTYPE_BASE,
+	},
 	{
 		.name		= "tasks",
 		.mode		= 0644,

Reinette

author reviewer
#54 lore raw

Re: [RESEND PATCH v4 09/15] fs/resctrl: Introduce kmode_cpus/kmode_cpus_list per rdtgroup

Hi Reinette,

Quoted 10 lines · Reinette Chatre

Hi Babu,

Quoted 7 lines · Babu Moger

Kernel-mode resctrl policies allow kernel work to be associated with a specific rdtgroup, optionally restricted to a subset of online CPUs.

While user space can query the active kernel-mode policy and its associated rdtgroup through info/kernel_mode, it currently lacks visibility into the CPU scope of that binding.

Quoted 6 lines
Quoted 1 line

Introduce read-only kmode_cpus and kmode_cpus_list files for each rdtgroup.

I think it will be easier to follow if this is deferred to not create these files in all resource groups by default. Instead, at the time they are created it should be obvious that they will only be visible in resource group associated with the active kernel mode.

I am not clear on this comment. Do you mean create these files when user associates the group to kernel mode? (during rdtgroup_config_kmode)

Also, you mentioned about rftype::create_hidden in
https://lore.kernel.org/lkml/[email protected]/

Can you please clarify on this?

Quoted 61 lines
Quoted 14 lines

These expose rdtgrp->kmode_cpu_mask in both bitmap and range-list formats, consistent with the existing cpus and cpus_list interfaces.

---

fs/resctrl/internal.h +0 -0
index 178126bb2da5..12db6933bc54 100644

fs/resctrl/internal.h struct mongroup { · line 220

Quoted 5 lines
fs/resctrl/internal.h +2 -0
@@ -216,6 +216,8 @@ struct mongroup {
   * @mon:			mongroup related data
   * @mode:			mode of resource group
   * @mba_mbps_event:		input monitoring event id when mba_sc is enabled
+ * @kmode:			true if this group is bound to a kernel-mode policy
+ * @kmode_cpu_mask:		CPU scope for this group's kernel-mode binding

"CPU scope" could be interpreted in various ways here. Could it be more specific to say something like "CPUs on which kernel mode is active"?

Quoted 38 lines
fs/resctrl/internal.h +2 -0
   * @plr:			pseudo-locked region
   */
  struct rdtgroup {
@@ -229,6 +231,8 @@ struct rdtgroup {
  	struct mongroup			mon;
  	enum rdtgrp_mode		mode;
  	enum resctrl_event_id		mba_mbps_event;
+	bool				kmode;
+	struct cpumask			kmode_cpu_mask;
  	struct pseudo_lock_region	*plr;
  };
 
fs/resctrl/rdtgroup.c +18 -0
index 346aa4df62a4..0d5c94169d03 100644
@@ -392,6 +392,37 @@ static int rdtgroup_cpus_show(struct kernfs_open_file *of,
  	return ret;
  }
 
+/*
+ * Display per-rdtgroup CPU bindings for kernel-mode enabled groups.
+ * Supports both "kmode_cpus" (bitmap format) and "kmode_cpus_list"
+ * (range list format); the output format is selected accordingly.
+ *
+ * Returns -ENOENT if the group has been deleted, and -ENODEV for
+ * pseudo-locked groups, which cannot host a kernel-mode binding.
+ */
+static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of,
+				    struct seq_file *s, void *v)
+{
+	struct rdtgroup *rdtgrp;
+	int ret = 0;
+
+	rdtgrp = rdtgroup_kn_lock_live(of->kn);
+
+	if (rdtgrp) {
+		if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) {
Quoted 9 lines

fs/resctrl/rdtgroup.c static int rdtgroup_cpus_show(struct kernfs_open_file *of, · line 413

Quoted 1 line
fs/resctrl/rdtgroup.c +1 -0
+			ret = -ENODEV;

sashiko also pointed something related out but it is not clear to me how the different group modes are planned to be accommodated. I think it should be possible to avoid sprinkling these mode checks into user space interactions if it is made explicit that (a) at the time a group is assigned to a kernel mode that group is required to be "shareable", and (b) it is not allowed to change the mode of a group that is assigned to a kernel mode.

Sure. We can add there checks.

Quoted 4 lines

Apart from that I do not think a test like this is sufficient to capture the various scenarios that may occur. For example, while waiting for the lock the group assigned to the kernel mode could have been re-assigned. Could a test on rdtgrp->kmode be more robust?

Basically, I need to check for rdtgrp->kmode here. Sure.

thanks
Babu

maintainer
#55 lore raw

Re: [RESEND PATCH v4 09/15] fs/resctrl: Introduce kmode_cpus/kmode_cpus_list per rdtgroup

Hi Babu,

Quoted 13 lines · Babu Moger

Hi Reinette,

Quoted 10 lines · Reinette Chatre

Hi Babu,

Quoted 7 lines · Babu Moger

Kernel-mode resctrl policies allow kernel work to be associated with a specific rdtgroup, optionally restricted to a subset of online CPUs.

While user space can query the active kernel-mode policy and its associated rdtgroup through info/kernel_mode, it currently lacks visibility into the CPU scope of that binding.

Quoted 8 lines
Quoted 6 lines
Quoted 1 line

Introduce read-only kmode_cpus and kmode_cpus_list files for each rdtgroup.

I think it will be easier to follow if this is deferred to not create these files in all resource groups by default. Instead, at the time they are created it should be obvious that they will only be visible in resource group associated with the active kernel mode.

I am not clear on this comment. Do you mean create these files when user associates the group to kernel mode? (during rdtgroup_config_kmode)

No. As this changelog states it creates these files in all resource groups. This is a confusing thing to do at this point in the series since these files are not expected to be present/visible in all resource groups, only in a resource group that is assigned to the "global" kernel mode. This commit mentions nothing about this usage and thus from reader perspective does not seem like the right thing to do here.

Quoted 5 lines

Also, you mentioned about rftype::create_hidden in
https://lore.kernel.org/lkml/[email protected]/

Can you please clarify on this?

resctrl has centralized functions to create files. For example, rdtgroup_add_file() that takes as parameter the properties of the file, struct rftype. With a new property, for example rftype::create_hidden the file's default visibility can be set _at the time it is created_. This simplifies the code by not needing to sprinkle changes to these files' visibility after the fact at the various places files are created.

One patch can add capability to resctrl to have a file property indicating that the file should essentially be created with KERNFS_HIDDEN set.

This patch can then follow by using the capability to create the kmode_cpus and kmode_cpus_list files in all resource groups and it will be clear that the files are not exposed to user space by default.

Reinette

author reviewer
#56 lore raw

Re: [RESEND PATCH v4 09/15] fs/resctrl: Introduce kmode_cpus/kmode_cpus_list per rdtgroup

Hi Reinette,

Quoted 23 lines · Reinette Chatre

Hi Babu,

Quoted 20 lines · Babu Moger

Hi Reinette,

Quoted 16 lines · Reinette Chatre

Hi Babu,

Quoted 8 lines · Babu Moger

Kernel-mode resctrl policies allow kernel work to be associated with a specific rdtgroup, optionally restricted to a subset of online CPUs.

While user space can query the active kernel-mode policy and its associated rdtgroup through info/kernel_mode, it currently lacks visibility into the CPU scope of that binding.

Introduce read-only kmode_cpus and kmode_cpus_list files for each rdtgroup.

I think it will be easier to follow if this is deferred to not create these files in all resource groups by default. Instead, at the time they are created it should be obvious that they will only be visible in resource group associated with the active kernel mode.

Quoted 7 lines
Quoted 1 line

I am not clear on this comment. Do you mean create these files when user associates the group to kernel mode? (during rdtgroup_config_kmode)

No. As this changelog states it creates these files in all resource groups. This is a confusing thing to do at this point in the series since these files are not expected to be present/visible in all resource groups, only in a resource group that is assigned to the "global" kernel mode. This commit mentions nothing about this usage and thus from reader perspective does not seem like the right thing to do here.

Ok. Got it. Commit message is not clear.

Quoted 13 lines
Quoted 6 lines

Also, you mentioned about rftype::create_hidden in
https://lore.kernel.org/lkml/[email protected]/

Can you please clarify on this?

resctrl has centralized functions to create files. For example, rdtgroup_add_file() that takes as parameter the properties of the file, struct rftype. With a new property, for example rftype::create_hidden the file's default visibility can be set _at the time it is created_. This simplifies the code by not needing to sprinkle changes to these files' visibility after the fact at the various places files are created.

Quoted 6 lines

One patch can add capability to resctrl to have a file property indicating that the file should essentially be created with KERNFS_HIDDEN set.

This patch can then follow by using the capability to create the kmode_cpus and kmode_cpus_list files in all resource groups and it will be clear that the files are not exposed to user space by default.

Soundd good. We can do that.
Thanks
Babu

maintainer
#57 lore raw

Re: [RESEND PATCH v4 09/15] fs/resctrl: Introduce kmode_cpus/kmode_cpus_list per rdtgroup

Hi Babu,

Quoted 24 lines · Babu Moger
Quoted 23 lines · Reinette Chatre
Quoted 21 lines · Babu Moger

Hi Reinette,

Quoted 10 lines · Reinette Chatre

Hi Babu,

Quoted 7 lines · Babu Moger

Kernel-mode resctrl policies allow kernel work to be associated with a specific rdtgroup, optionally restricted to a subset of online CPUs.

While user space can query the active kernel-mode policy and its associated rdtgroup through info/kernel_mode, it currently lacks visibility into the CPU scope of that binding.

Quoted 6 lines
Quoted 1 line

Introduce read-only kmode_cpus and kmode_cpus_list files for each rdtgroup.

I think it will be easier to follow if this is deferred to not create these files in all resource groups by default. Instead, at the time they are created it should be obvious that they will only be visible in resource group associated with the active kernel mode.

I am not clear on this comment. Do you mean create these files when user associates the group to kernel mode? (during rdtgroup_config_kmode)

Quoted 7 lines
Quoted 5 lines

No. As this changelog states it creates these files in all resource groups. This is a confusing thing to do at this point in the series since these files are not expected to be present/visible in all resource groups, only in a resource group that is assigned to the "global" kernel mode. This commit mentions nothing about this usage and thus from reader perspective does not seem like the right thing to do here.

Ok. Got it. Commit message is not clear.

This is not just about the commit message being unclear. This commit adds functionality that patches that follow undo. I find this strategy unnecessary even if the commit message is changed to reflect this. I find having the functionality as intended from the beginning easier to follow.

Reinette

#58 lore raw

Re: [RESEND PATCH v4 09/15] fs/resctrl: Introduce kmode_cpus/kmode_cpus_list per rdtgroup

Hi Reinette,

Quoted 33 lines · Reinette Chatre

Hi Babu,

Quoted 30 lines · Babu Moger
Quoted 28 lines · Reinette Chatre
Quoted 13 lines · Babu Moger

Hi Reinette,

Quoted 10 lines · Reinette Chatre

Hi Babu,

Quoted 7 lines · Babu Moger

Kernel-mode resctrl policies allow kernel work to be associated with a specific rdtgroup, optionally restricted to a subset of online CPUs.

While user space can query the active kernel-mode policy and its associated rdtgroup through info/kernel_mode, it currently lacks visibility into the CPU scope of that binding.

Quoted 8 lines
Quoted 6 lines
Quoted 1 line

Introduce read-only kmode_cpus and kmode_cpus_list files for each rdtgroup.

I think it will be easier to follow if this is deferred to not create these files in all resource groups by default. Instead, at the time they are created it should be obvious that they will only be visible in resource group associated with the active kernel mode.

I am not clear on this comment. Do you mean create these files when user associates the group to kernel mode? (during rdtgroup_config_kmode)

No. As this changelog states it creates these files in all resource groups. This is a confusing thing to do at this point in the series since these files are not expected to be present/visible in all resource groups, only in a resource group that is assigned to the "global" kernel mode. This commit mentions nothing about this usage and thus from reader perspective does not seem like the right thing to do here.

Quoted 6 lines
Quoted 1 line

Ok. Got it. Commit message is not clear.

This is not just about the commit message being unclear. This commit adds functionality that patches that follow undo. I find this strategy unnecessary even if the commit message is changed to reflect this. I find having the functionality as intended from the beginning easier to follow.

Ok. Sure.

This code will also be revised to accommodate the addition of hidden file creation functionality.

Thanks
Babu

author reviewer
#59 lore raw

PATCH RESEND v4 10/15 fs/resctrl: Reset the kernel-mode binding when an rdtgroup is removed

In reply to Babu Moger

Resctrl keeps track of the rdtgroup backing the active global kernel-mode policy, including the group's CPU mask used to program kernel-mode associations.

When that rdtgroup is deleted, resctrl must update both its internal state and the hardware configuration associated with the group's kmode_cpu_mask.

Introduce rdtgroup_config_kmode_reset() to disable the active kernel-mode association for the bound group's CPU mask and to clear its kernel-mode state. Invoke this helper from rdtgroup_kmode_detach(), and reset resctrl_kcfg to INHERIT_CTRL_AND_MON. Ensure rdtgroup_kmode_detach() is called during group removal and filesystem teardown, before the bound rdtgroup is freed.

---
v4: Re-wrote the changelog.
Added the call free_all_child_rdtgrp() and rmdir_all_sub() Simplified the code comments.

v3: New patch to handle the kernel_mode clean up.

---
 fs/resctrl/rdtgroup.c | 62 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)
fs/resctrl/rdtgroup.c +62 -0
index 0d5c94169d03..21659fd75850 100644
@@ -1127,6 +1127,61 @@ static int resctrl_kernel_mode_show(struct kernfs_open_file *of,
 	return ret;
 }
 
+/**
+ * rdtgroup_config_kmode_reset() - Tear down the kernel-mode binding on @rdtgrp
+ * @rdtgrp:	Resctrl group whose kernel-mode binding is being released.
+ *		May be %NULL when no group is currently bound, in which case
+ *		this is a no-op.
+ * @kmode:	Kernel-mode policy currently active on @rdtgrp.
+ *
+ * Reset the kernel-mode binding on the CPUs in @rdtgrp's @kmode_cpu_mask.
+ */
+static void rdtgroup_config_kmode_reset(struct rdtgroup *rdtgrp,
+					enum resctrl_kernel_mode kmode)
+{
+	bool assign_mon = false;
+
+	if (!rdtgrp)
+		return;
+
+	if (kmode == INHERIT_CTRL_AND_MON)
+		goto out_clear;
+
+	if (kmode == GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU)
+		assign_mon = true;
+
+	resctrl_arch_configure_kmode(&rdtgrp->kmode_cpu_mask, rdtgrp->closid,
+				     rdtgrp->mon.rmid, assign_mon, false);
+
+out_clear:
+	cpumask_clear(&rdtgrp->kmode_cpu_mask);
+	rdtgrp->kmode = false;
+}
+
+/**
+ * rdtgroup_kmode_detach() - Detach @rdtgrp from kernel-mode assignment
+ * @rdtgrp: Resctrl group being removed or torn down
+ *
+ * If @rdtgrp is bound to the active kernel-mode assignment, disable the
+ * hardware association programmed for that group and reset the kernel-mode
+ * to INHERIT_CTRL_AND_MON.
+ */
+static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp)
+{
+	if (!rdtgrp || !rdtgrp->kmode)
+		return;
+
+	if (resctrl_kcfg.k_rdtgrp != rdtgrp) {
+		pr_warn("resctrl: kernel-mode group not valid\n");
+		return;
+	}
+
+	rdtgroup_config_kmode_reset(rdtgrp, resctrl_kcfg.kmode_cur);
+
+	resctrl_kcfg.k_rdtgrp = NULL;
+	resctrl_kcfg.kmode_cur = INHERIT_CTRL_AND_MON;
+}
+
 void *rdt_kn_parent_priv(struct kernfs_node *kn)
 {
 	/*
@@ -3215,6 +3270,7 @@ static void free_all_child_rdtgrp(struct rdtgroup *rdtgrp)
 
 	head = &rdtgrp->mon.crdtgrp_list;
 	list_for_each_entry_safe(sentry, stmp, head, mon.crdtgrp_list) {
+		rdtgroup_kmode_detach(sentry);
 		rdtgroup_unassign_cntrs(sentry);
 		free_rmid(sentry->closid, sentry->mon.rmid);
 		list_del(&sentry->mon.crdtgrp_list);
@@ -3252,6 +3308,7 @@ static void rmdir_all_sub(void)
 		cpumask_or(&rdtgroup_default.cpu_mask,
 			   &rdtgroup_default.cpu_mask, &rdtgrp->cpu_mask);
 
+		rdtgroup_kmode_detach(rdtgrp);
 		rdtgroup_unassign_cntrs(rdtgrp);
 
 		if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP ||
@@ -3347,6 +3404,7 @@ static void resctrl_fs_teardown(void)
 		return;
 
 	rmdir_all_sub();
+	rdtgroup_kmode_detach(&rdtgroup_default);
 	rdtgroup_unassign_cntrs(&rdtgroup_default);
 	mon_put_kn_priv();
 	rdt_pseudo_lock_release();
@@ -4149,6 +4207,8 @@ static int rdtgroup_rmdir_mon(struct rdtgroup *rdtgrp, cpumask_var_t tmpmask)
 	u32 closid, rmid;
 	int cpu;
 
+	rdtgroup_kmode_detach(rdtgrp);
+
 	/* Give any tasks back to the parent group */
 	rdt_move_group_tasks(rdtgrp, prdtgrp, tmpmask);
 
@@ -4199,6 +4259,8 @@ static int rdtgroup_rmdir_ctrl(struct rdtgroup *rdtgrp, cpumask_var_t tmpmask)
 	u32 closid, rmid;
 	int cpu;
 
+	rdtgroup_kmode_detach(rdtgrp);
+
 	/* Give any tasks back to the default group */
 	rdt_move_group_tasks(rdtgrp, &rdtgroup_default, tmpmask);
 
Signature · 1 line
2.43.0
author reviewer
#60 lore raw

Re: [RESEND PATCH v4 10/15] fs/resctrl: Reset the kernel-mode binding when an rdtgroup is removed

Quoted 125 lines · Babu Moger

Resctrl keeps track of the rdtgroup backing the active global kernel-mode policy, including the group's CPU mask used to program kernel-mode associations.

When that rdtgroup is deleted, resctrl must update both its internal state and the hardware configuration associated with the group's kmode_cpu_mask.

Introduce rdtgroup_config_kmode_reset() to disable the active kernel-mode association for the bound group's CPU mask and to clear its kernel-mode state. Invoke this helper from rdtgroup_kmode_detach(), and reset resctrl_kcfg to INHERIT_CTRL_AND_MON. Ensure rdtgroup_kmode_detach() is called during group removal and filesystem teardown, before the bound rdtgroup is freed.

---
v4: Re-wrote the changelog.
Added the call free_all_child_rdtgrp() and rmdir_all_sub() Simplified the code comments.

v3: New patch to handle the kernel_mode clean up.

---
  fs/resctrl/rdtgroup.c | 62 +++++++++++++++++++++++++++++++++++++++++++
  1 file changed, 62 insertions(+)
fs/resctrl/rdtgroup.c +60 -0
index 0d5c94169d03..21659fd75850 100644
@@ -1127,6 +1127,61 @@ static int resctrl_kernel_mode_show(struct kernfs_open_file *of,
  	return ret;
  }
 
+/**
+ * rdtgroup_config_kmode_reset() - Tear down the kernel-mode binding on @rdtgrp
+ * @rdtgrp:	Resctrl group whose kernel-mode binding is being released.
+ *		May be %NULL when no group is currently bound, in which case
+ *		this is a no-op.
+ * @kmode:	Kernel-mode policy currently active on @rdtgrp.
+ *
+ * Reset the kernel-mode binding on the CPUs in @rdtgrp's @kmode_cpu_mask.
+ */
+static void rdtgroup_config_kmode_reset(struct rdtgroup *rdtgrp,
+					enum resctrl_kernel_mode kmode)
+{
+	bool assign_mon = false;
+
+	if (!rdtgrp)
+		return;
+
+	if (kmode == INHERIT_CTRL_AND_MON)
+		goto out_clear;
+
+	if (kmode == GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU)
+		assign_mon = true;
+
+	resctrl_arch_configure_kmode(&rdtgrp->kmode_cpu_mask, rdtgrp->closid,
+				     rdtgrp->mon.rmid, assign_mon, false);
+
+out_clear:
+	cpumask_clear(&rdtgrp->kmode_cpu_mask);
+	rdtgrp->kmode = false;
+}
+
+/**
+ * rdtgroup_kmode_detach() - Detach @rdtgrp from kernel-mode assignment
+ * @rdtgrp: Resctrl group being removed or torn down
+ *
+ * If @rdtgrp is bound to the active kernel-mode assignment, disable the
+ * hardware association programmed for that group and reset the kernel-mode
+ * to INHERIT_CTRL_AND_MON.
+ */
+static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp)
+{
+	if (!rdtgrp || !rdtgrp->kmode)
+		return;
+
+	if (resctrl_kcfg.k_rdtgrp != rdtgrp) {
+		pr_warn("resctrl: kernel-mode group not valid\n");
+		return;
+	}
+
+	rdtgroup_config_kmode_reset(rdtgrp, resctrl_kcfg.kmode_cur);
+
+	resctrl_kcfg.k_rdtgrp = NULL;
+	resctrl_kcfg.kmode_cur = INHERIT_CTRL_AND_MON;
+}
+
  void *rdt_kn_parent_priv(struct kernfs_node *kn)
  {
  	/*
@@ -3215,6 +3270,7 @@ static void free_all_child_rdtgrp(struct rdtgroup *rdtgrp)
 
  	head = &rdtgrp->mon.crdtgrp_list;
  	list_for_each_entry_safe(sentry, stmp, head, mon.crdtgrp_list) {
+		rdtgroup_kmode_detach(sentry);
  		rdtgroup_unassign_cntrs(sentry);
  		free_rmid(sentry->closid, sentry->mon.rmid);
  		list_del(&sentry->mon.crdtgrp_list);
@@ -3252,6 +3308,7 @@ static void rmdir_all_sub(void)
  		cpumask_or(&rdtgroup_default.cpu_mask,
  			   &rdtgroup_default.cpu_mask, &rdtgrp->cpu_mask);
 
+		rdtgroup_kmode_detach(rdtgrp);
  		rdtgroup_unassign_cntrs(rdtgrp);
 
  		if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP ||
@@ -3347,6 +3404,7 @@ static void resctrl_fs_teardown(void)
  		return;
 
  	rmdir_all_sub();
+	rdtgroup_kmode_detach(&rdtgroup_default);
  	rdtgroup_unassign_cntrs(&rdtgroup_default);
  	mon_put_kn_priv();
  	rdt_pseudo_lock_release();
@@ -4149,6 +4207,8 @@ static int rdtgroup_rmdir_mon(struct rdtgroup *rdtgrp, cpumask_var_t tmpmask)
  	u32 closid, rmid;
  	int cpu;
 
+	rdtgroup_kmode_detach(rdtgrp);
+
  	/* Give any tasks back to the parent group */
  	rdt_move_group_tasks(rdtgrp, prdtgrp, tmpmask);
 

fs/resctrl/rdtgroup.c static int rdtgroup_rmdir_ctrl(struct rdtgroup *rdtgrp, cpumask_var_t tmpmask) · line 4266

Quoted 8 lines
fs/resctrl/rdtgroup.c +2 -0
@@ -4199,6 +4259,8 @@ static int rdtgroup_rmdir_ctrl(struct rdtgroup *rdtgrp, cpumask_var_t tmpmask)
  	u32 closid, rmid;
  	int cpu;
 
+	rdtgroup_kmode_detach(rdtgrp);
+
  	/* Give any tasks back to the default group */
  	rdt_move_group_tasks(rdtgrp, &rdtgroup_default, tmpmask);
 

Sashiko reported:

https://sashiko.dev/#/patchset/cover.1783461016.git.babu.moger%40amd.com?part=10

--- Patch [10]: [RESEND PATCH v4 10/15] fs/resctrl: Reset the kernel-mode binding when an rdtgroup is removed --- commit 42354ae9f22a1b788ec34201f40310a30c5f5247
Author: Babu Moger <[email protected]>
fs/resctrl: Reset the kernel-mode binding when an rdtgroup is removed
This commit introduces rdtgroup_config_kmode_reset() and
rdtgroup_kmode_detach() to tear down the kernel-mode binding on a resctrl
group. It invokes these helpers during group removal and filesystem teardown
to disable active kernel-mode hardware association and clear internal state.

Quoted 4 lines
fs/resctrl/rdtgroup.c +0 -0
index 0d5c94169d03f..21659fd75850e 100644

[ ... ]

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+static void rdtgroup_config_kmode_reset(struct rdtgroup *rdtgrp,
+					enum resctrl_kernel_mode kmode)
+{
+	bool assign_mon = false;
+
+	if (!rdtgrp)

fs/resctrl/rdtgroup.c static int resctrl_kernel_mode_show(struct kernfs_open_file *of, · line 1154

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+		return;
+
+	if (kmode == INHERIT_CTRL_AND_MON)
+		goto out_clear;
+
+	if (kmode == GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU)
+		assign_mon = true;
+
+	resctrl_arch_configure_kmode(&rdtgrp->kmode_cpu_mask, rdtgrp->closid,
+				     rdtgrp->mon.rmid, assign_mon, false);

Does this teardown properly handle offline CPUs?
If a CPU in rdtgrp->kmode_cpu_mask is offlined before this reset is called, the underlying IPI might skip the offline CPU, leaving its MSR unmodified. When the CPU is brought back online, clear_closid_rmid() clears MSR_IA32_PQR_ASSOC, but does it also clear the newly introduced MSR_IA32_PQR_PLZA_ASSOC?
If not, the CPU could resume executing with stale Privilege Level Zero Association state, potentially causing incorrect resource allocation for kernel mode code.

----------------------------------------------------------------------

Yes. This is an issue.
Need to clear the kmode_cpu_list if the cpu being offlined is part of the current kmode. Also, need to disable PLZA on the CPU that is offlined.

Will take care of this in resctrl_offline_cpu(). The changes will go in patch 11 (Patch 11: [RESEND PATCH v4 11/15] fs/resctrl: Program kernel-mode binding when CPU comes online)

Quoted 5 lines
fs/resctrl/rdtgroup.c +5 -0
+
+out_clear:
+	cpumask_clear(&rdtgrp->kmode_cpu_mask);
+	rdtgrp->kmode = false;
+}

[ ... ]

fs/resctrl/rdtgroup.c static void free_all_child_rdtgrp(struct rdtgroup *rdtgrp) · line 3276

Quoted 8 lines
fs/resctrl/rdtgroup.c +1 -0
@@ -3215,6 +3270,7 @@ static void free_all_child_rdtgrp(struct rdtgroup *rdtgrp)
 
 	head = &rdtgrp->mon.crdtgrp_list;
 	list_for_each_entry_safe(sentry, stmp, head, mon.crdtgrp_list) {
+		rdtgroup_kmode_detach(sentry);
 		rdtgroup_unassign_cntrs(sentry);
 		free_rmid(sentry->closid, sentry->mon.rmid);
 		list_del(&sentry->mon.crdtgrp_list);

This is a pre-existing issue, but can unmounting the filesystem lead to a use-after-free here if child monitor groups are present?

If the admin unmounts the resctrl filesystem while a user process holds an open file descriptor to a file within a monitor group directory, resctrl_fs_teardown() calls rmdir_all_sub() which calls
free_all_child_rdtgrp().

A few lines below this hunk, this function frees the monitor group (sentry) via rdtgroup_remove() without first calling kernfs_remove(sentry->kn).
The sentry->kn node retains a refcount and remains active in the kernfs tree. Could a concurrent read() or write() by the user process access the freed sentry structure via kn->priv before the tree is finally destroyed?
----------------------------------------------------------------------

If a user process still holds the file descriptor, the waitcount is non-zero, and rdtgroup_remove(sentry) is not called. As a result, the sentry structure is not freed.

Is this actually an issue?

Thanks
Babu

maintainer
#61 lore raw

Re: [RESEND PATCH v4 10/15] fs/resctrl: Reset the kernel-mode binding when an rdtgroup is removed

In reply to Babu Moger

Hi Babu,

Quoted 6 lines · Babu Moger

Resctrl keeps track of the rdtgroup backing the active global kernel-mode policy, including the group's CPU mask used to program kernel-mode associations.

When that rdtgroup is deleted, resctrl must update both its internal state and the hardware configuration associated with the group's kmode_cpu_mask.

Instead of updating the hardware configuration itself resctrl fs will request the underlying architecture to do so.

Quoted 6 lines

Introduce rdtgroup_config_kmode_reset() to disable the active kernel-mode association for the bound group's CPU mask and to clear its kernel-mode state. Invoke this helper from rdtgroup_kmode_detach(), and reset resctrl_kcfg to INHERIT_CTRL_AND_MON. Ensure rdtgroup_kmode_detach() is called during group removal and filesystem teardown, before the bound rdtgroup is freed.

(Same comment as before - please do not describe the code details and write in imperative tone. Please check all changelogs.)

I think it will be helpful to add reminder why "reset" call needs to include all the existing assignments. This could be part of resctrl fs "contract" with architecture on when and how it calls resctrl_arch_configure_kmode().

Quoted 20 lines

---
v4: Re-wrote the changelog.
Added the call free_all_child_rdtgrp() and rmdir_all_sub() Simplified the code comments.

v3: New patch to handle the kernel_mode clean up.

---
 fs/resctrl/rdtgroup.c | 62 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)
fs/resctrl/rdtgroup.c +0 -0
index 0d5c94169d03..21659fd75850 100644
@@ -1127,6 +1127,61 @@ static int resctrl_kernel_mode_show(struct kernfs_open_file *of,
 	return ret;
 }
 

fs/resctrl/rdtgroup.c static int resctrl_kernel_mode_show(struct kernfs_open_file *of, · line 1139

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+/**
+ * rdtgroup_config_kmode_reset() - Tear down the kernel-mode binding on @rdtgrp
+ * @rdtgrp:	Resctrl group whose kernel-mode binding is being released.
+ *		May be %NULL when no group is currently bound, in which case
+ *		this is a no-op.
+ * @kmode:	Kernel-mode policy currently active on @rdtgrp.
+ *
+ * Reset the kernel-mode binding on the CPUs in @rdtgrp's @kmode_cpu_mask.
+ */
+static void rdtgroup_config_kmode_reset(struct rdtgroup *rdtgrp,

So far the word "active" has been used a lot when referring to the "active" kernel mode. To complement this I think it will make this work easier to understand if this is renamed to rdtgroup_kmode_deactivate() and to match it rdtgroup_config_kmode() could be renamed to rdtgroup_kmode_activate()?

fs/resctrl/rdtgroup.c static int resctrl_kernel_mode_show(struct kernfs_open_file *of, · line 1148

Quoted 9 lines
fs/resctrl/rdtgroup.c +9 -0
+					enum resctrl_kernel_mode kmode)
+{
+	bool assign_mon = false;
+
+	if (!rdtgrp)
+		return;
+
+	if (kmode == INHERIT_CTRL_AND_MON)
+		goto out_clear;

When kmode is INHERIT_CTRL_AND_MON then there should not be a resource group assigned so the work done at "out_clear" is not necessary?

fs/resctrl/rdtgroup.c static int resctrl_kernel_mode_show(struct kernfs_open_file *of, · line 1151

Quoted 3 lines
fs/resctrl/rdtgroup.c +3 -0
+
+	if (kmode == GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU)
+		assign_mon = true;

Could use the same assignment as resctrl_kmode_online_cpu() and kmode_cpus_write() ?

Quoted 70 lines
fs/resctrl/rdtgroup.c +38 -0
+
+	resctrl_arch_configure_kmode(&rdtgrp->kmode_cpu_mask, rdtgrp->closid,
+				     rdtgrp->mon.rmid, assign_mon, false);
+
+out_clear:
+	cpumask_clear(&rdtgrp->kmode_cpu_mask);
+	rdtgrp->kmode = false;
+}
+
+/**
+ * rdtgroup_kmode_detach() - Detach @rdtgrp from kernel-mode assignment
+ * @rdtgrp: Resctrl group being removed or torn down
+ *
+ * If @rdtgrp is bound to the active kernel-mode assignment, disable the
+ * hardware association programmed for that group and reset the kernel-mode
+ * to INHERIT_CTRL_AND_MON.
+ */
+static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp)
+{
+	if (!rdtgrp || !rdtgrp->kmode)
+		return;
+
+	if (resctrl_kcfg.k_rdtgrp != rdtgrp) {
+		pr_warn("resctrl: kernel-mode group not valid\n");
+		return;
+	}
+
+	rdtgroup_config_kmode_reset(rdtgrp, resctrl_kcfg.kmode_cur);
+
+	resctrl_kcfg.k_rdtgrp = NULL;
+	resctrl_kcfg.kmode_cur = INHERIT_CTRL_AND_MON;
+}
+
 void *rdt_kn_parent_priv(struct kernfs_node *kn)
 {
 	/*
@@ -3215,6 +3270,7 @@ static void free_all_child_rdtgrp(struct rdtgroup *rdtgrp)
 
 	head = &rdtgrp->mon.crdtgrp_list;
 	list_for_each_entry_safe(sentry, stmp, head, mon.crdtgrp_list) {
+		rdtgroup_kmode_detach(sentry);
 		rdtgroup_unassign_cntrs(sentry);
 		free_rmid(sentry->closid, sentry->mon.rmid);
 		list_del(&sentry->mon.crdtgrp_list);
@@ -3252,6 +3308,7 @@ static void rmdir_all_sub(void)
 		cpumask_or(&rdtgroup_default.cpu_mask,
 			   &rdtgroup_default.cpu_mask, &rdtgrp->cpu_mask);
 
+		rdtgroup_kmode_detach(rdtgrp);
 		rdtgroup_unassign_cntrs(rdtgrp);
 
 		if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP ||
@@ -3347,6 +3404,7 @@ static void resctrl_fs_teardown(void)
 		return;
 
 	rmdir_all_sub();
+	rdtgroup_kmode_detach(&rdtgroup_default);
 	rdtgroup_unassign_cntrs(&rdtgroup_default);
 	mon_put_kn_priv();
 	rdt_pseudo_lock_release();
@@ -4149,6 +4207,8 @@ static int rdtgroup_rmdir_mon(struct rdtgroup *rdtgrp, cpumask_var_t tmpmask)
 	u32 closid, rmid;
 	int cpu;
 
+	rdtgroup_kmode_detach(rdtgrp);
+
 	/* Give any tasks back to the parent group */
 	rdt_move_group_tasks(rdtgrp, prdtgrp, tmpmask);
 

fs/resctrl/rdtgroup.c static int rdtgroup_rmdir_ctrl(struct rdtgroup *rdtgrp, cpumask_var_t tmpmask) · line 4266

Quoted 8 lines
fs/resctrl/rdtgroup.c +2 -0
@@ -4199,6 +4259,8 @@ static int rdtgroup_rmdir_ctrl(struct rdtgroup *rdtgrp, cpumask_var_t tmpmask)
 	u32 closid, rmid;
 	int cpu;
 
+	rdtgroup_kmode_detach(rdtgrp);
+
 	/* Give any tasks back to the default group */
 	rdt_move_group_tasks(rdtgrp, &rdtgroup_default, tmpmask);
 

Reinette

author reviewer
#62 lore raw

Re: [RESEND PATCH v4 10/15] fs/resctrl: Reset the kernel-mode binding when an rdtgroup is removed

Hi Reinette,

Quoted 7 lines · Reinette Chatre

Hi Babu,

Quoted 4 lines · Babu Moger

Resctrl keeps track of the rdtgroup backing the active global kernel-mode policy, including the group's CPU mask used to program kernel-mode associations.

Quoted 5 lines
Quoted 2 lines

When that rdtgroup is deleted, resctrl must update both its internal state and the hardware configuration associated with the group's kmode_cpu_mask.

Instead of updating the hardware configuration itself resctrl fs will request the underlying architecture to do so.

Yes. Sure.

Quoted 10 lines
Quoted 7 lines

Introduce rdtgroup_config_kmode_reset() to disable the active kernel-mode association for the bound group's CPU mask and to clear its kernel-mode state. Invoke this helper from rdtgroup_kmode_detach(), and reset resctrl_kcfg to INHERIT_CTRL_AND_MON. Ensure rdtgroup_kmode_detach() is called during group removal and filesystem teardown, before the bound rdtgroup is freed.

(Same comment as before - please do not describe the code details and write in imperative tone. Please check all changelogs.)

Ack.

Quoted 4 lines

I think it will be helpful to add reminder why "reset" call needs to include all the existing assignments. This could be part of resctrl fs "contract" with architecture on when and how it calls resctrl_arch_configure_kmode().

Sure.>

Quoted 20 lines
Quoted 20 lines

---
v4: Re-wrote the changelog.
Added the call free_all_child_rdtgrp() and rmdir_all_sub() Simplified the code comments.

v3: New patch to handle the kernel_mode clean up.

---
  fs/resctrl/rdtgroup.c | 62 +++++++++++++++++++++++++++++++++++++++++++
  1 file changed, 62 insertions(+)
fs/resctrl/rdtgroup.c +0 -0
index 0d5c94169d03..21659fd75850 100644
@@ -1127,6 +1127,61 @@ static int resctrl_kernel_mode_show(struct kernfs_open_file *of,
  	return ret;
  }
 
Quoted 15 lines

fs/resctrl/rdtgroup.c static int resctrl_kernel_mode_show(struct kernfs_open_file *of, · line 1139

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+/**
+ * rdtgroup_config_kmode_reset() - Tear down the kernel-mode binding on @rdtgrp
+ * @rdtgrp:	Resctrl group whose kernel-mode binding is being released.
+ *		May be %NULL when no group is currently bound, in which case
+ *		this is a no-op.
+ * @kmode:	Kernel-mode policy currently active on @rdtgrp.
+ *
+ * Reset the kernel-mode binding on the CPUs in @rdtgrp's @kmode_cpu_mask.
+ */
+static void rdtgroup_config_kmode_reset(struct rdtgroup *rdtgrp,

So far the word "active" has been used a lot when referring to the "active" kernel mode. To complement this I think it will make this work easier to understand if this is renamed to rdtgroup_kmode_deactivate() and to match it rdtgroup_config_kmode() could be renamed to rdtgroup_kmode_activate()?

Sure.

Quoted 13 lines

fs/resctrl/rdtgroup.c static int resctrl_kernel_mode_show(struct kernfs_open_file *of, · line 1148

Quoted 10 lines
fs/resctrl/rdtgroup.c +9 -0
+					enum resctrl_kernel_mode kmode)
+{
+	bool assign_mon = false;
+
+	if (!rdtgrp)
+		return;
+
+	if (kmode == INHERIT_CTRL_AND_MON)
+		goto out_clear;

When kmode is INHERIT_CTRL_AND_MON then there should not be a resource group assigned so the work done at "out_clear" is not necessary?

Correct. Not required.

Quoted 6 lines

fs/resctrl/rdtgroup.c static int resctrl_kernel_mode_show(struct kernfs_open_file *of, · line 1151

Quoted 4 lines
fs/resctrl/rdtgroup.c +3 -0
+
+	if (kmode == GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU)
+		assign_mon = true;

Could use the same assignment as resctrl_kmode_online_cpu() and kmode_cpus_write() ?

Sure.

Thanks
Babu

author reviewer
#63 lore raw

PATCH RESEND v4 11/15 fs/resctrl: Program kernel-mode binding when CPU comes online

In reply to Babu Moger

Kernel-mode resctrl associations are programmed per CPU. When a global-assign kernel-mode policy is selected, all CPUs that are online at that time are configured; however, CPUs that come online later are not automatically updated.

As a result, hot-added CPUs, or CPUs that were offline when the policy was selected, can run without the active kernel-mode association even though the resctrl policy is still in effect.

Add resctrl_kmode_online_cpu() and call it from resctrl_online_cpu(). When a global-assign policy is active, add the newly online CPU to the bound group's kmode_cpu_mask and program the kernel-mode association on that CPU.

---
v4: New patch in the series. Patch taken from:
https://lore.kernel.org/lkml/[email protected]/
Updated the code to enable kernel-mode by default whenever a CPU comes online when one of global-assign mode is enabled.

---
 fs/resctrl/rdtgroup.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)
fs/resctrl/rdtgroup.c +29 -0
index 21659fd75850..413d3ff14546 100644
@@ -4722,11 +4722,40 @@ int resctrl_online_mon_domain(struct rdt_resource *r, struct rdt_domain_hdr *hdr
 	return err;
 }
 
+/*
+ * resctrl_kmode_online_cpu() - Configure kernel-mode binding for a CPU that
+ *				comes online
+ * @cpu: CPU that has just been brought online.
+ *
+ * Kernel-mode associations are maintained per CPU. When a CPU becomes
+ * online after a global-assign policy has been applied, it is updated
+ * with the current kernel-mode configuration. The CPU is then added to
+ * the bound group's kmode_cpu_mask, and the appropriate association is
+ * programmed for it.
+ */
+static void resctrl_kmode_online_cpu(unsigned int cpu)
+{
+	struct rdtgroup *rdtgrp = resctrl_kcfg.k_rdtgrp;
+	bool assign_mon = false;
+
+	if (resctrl_kcfg.kmode_cur == INHERIT_CTRL_AND_MON || !rdtgrp)
+		return;
+
+	assign_mon = (resctrl_kcfg.kmode_cur == GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU);
+
+	cpumask_set_cpu(cpu, &rdtgrp->kmode_cpu_mask);
+
+	resctrl_arch_configure_kmode(cpumask_of(cpu), rdtgrp->closid, rdtgrp->mon.rmid,
+				     assign_mon, true);
+}
+
 void resctrl_online_cpu(unsigned int cpu)
 {
 	mutex_lock(&rdtgroup_mutex);
 	/* The CPU is set in default rdtgroup after online. */
 	cpumask_set_cpu(cpu, &rdtgroup_default.cpu_mask);
+	/* Program any active kernel-mode binding on this CPU. */
+	resctrl_kmode_online_cpu(cpu);
 	mutex_unlock(&rdtgroup_mutex);
 }
 
Signature · 1 line
2.43.0
author reviewer
#64 lore raw

Re: [RESEND PATCH v4 11/15] fs/resctrl: Program kernel-mode binding when CPU comes online

Quoted 58 lines · Babu Moger

Kernel-mode resctrl associations are programmed per CPU. When a global-assign kernel-mode policy is selected, all CPUs that are online at that time are configured; however, CPUs that come online later are not automatically updated.

As a result, hot-added CPUs, or CPUs that were offline when the policy was selected, can run without the active kernel-mode association even though the resctrl policy is still in effect.

Add resctrl_kmode_online_cpu() and call it from resctrl_online_cpu(). When a global-assign policy is active, add the newly online CPU to the bound group's kmode_cpu_mask and program the kernel-mode association on that CPU.

---
v4: New patch in the series. Patch taken from:
https://lore.kernel.org/lkml/[email protected]/
Updated the code to enable kernel-mode by default whenever a CPU comes online when one of global-assign mode is enabled.

---
  fs/resctrl/rdtgroup.c | 29 +++++++++++++++++++++++++++++
  1 file changed, 29 insertions(+)
fs/resctrl/rdtgroup.c +27 -0
index 21659fd75850..413d3ff14546 100644
@@ -4722,11 +4722,40 @@ int resctrl_online_mon_domain(struct rdt_resource *r, struct rdt_domain_hdr *hdr
  	return err;
  }
 
+/*
+ * resctrl_kmode_online_cpu() - Configure kernel-mode binding for a CPU that
+ *				comes online
+ * @cpu: CPU that has just been brought online.
+ *
+ * Kernel-mode associations are maintained per CPU. When a CPU becomes
+ * online after a global-assign policy has been applied, it is updated
+ * with the current kernel-mode configuration. The CPU is then added to
+ * the bound group's kmode_cpu_mask, and the appropriate association is
+ * programmed for it.
+ */
+static void resctrl_kmode_online_cpu(unsigned int cpu)
+{
+	struct rdtgroup *rdtgrp = resctrl_kcfg.k_rdtgrp;
+	bool assign_mon = false;
+
+	if (resctrl_kcfg.kmode_cur == INHERIT_CTRL_AND_MON || !rdtgrp)
+		return;
+
+	assign_mon = (resctrl_kcfg.kmode_cur == GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU);
+
+	cpumask_set_cpu(cpu, &rdtgrp->kmode_cpu_mask);
+
+	resctrl_arch_configure_kmode(cpumask_of(cpu), rdtgrp->closid, rdtgrp->mon.rmid,
+				     assign_mon, true);
+}
+

fs/resctrl/rdtgroup.c int resctrl_online_mon_domain(struct rdt_resource *r, struct rdt_domain_hdr *hdr · line 4761

Quoted 10 lines
fs/resctrl/rdtgroup.c +2 -0
  void resctrl_online_cpu(unsigned int cpu)
  {
  	mutex_lock(&rdtgroup_mutex);
  	/* The CPU is set in default rdtgroup after online. */
  	cpumask_set_cpu(cpu, &rdtgroup_default.cpu_mask);
+	/* Program any active kernel-mode binding on this CPU. */
+	resctrl_kmode_online_cpu(cpu);
  	mutex_unlock(&rdtgroup_mutex);
  }
 

Sashiko reported:

https://sashiko.dev/#/patchset/cover.1783461016.git.babu.moger%40amd.com?part=11

--- Patch [11]: [RESEND PATCH v4 11/15] fs/resctrl: Program kernel-mode binding when CPU comes online --- commit ab44f1490e3dbe9a24a0baa6c7b98b7456c62c03
Author: Babu Moger <[email protected]>
fs/resctrl: Program kernel-mode binding when CPU comes online
Kernel-mode resctrl associations are programmed per CPU. When a global-assign kernel-mode policy is selected, all CPUs that are online at that time are
configured; however, CPUs that come online later are not automatically
updated.

fs/resctrl/rdtgroup.c +0 -0
index 21659fd75850e..413d3ff14546b 100644

[ ... ]

Quoted 12 lines
fs/resctrl/rdtgroup.c +8 -0
@@ -4722,11 +4722,40 @@ int resctrl_online_mon_domain(struct rdt_resource *r, struct rdt_domain_hdr *hdr
 	return err;
 }
 
+/*
+ * resctrl_kmode_online_cpu() - Configure kernel-mode binding for a CPU that
+ *				comes online
+ * @cpu: CPU that has just been brought online.
+ *
+ * Kernel-mode associations are maintained per CPU. When a CPU becomes
+ * online after a global-assign policy has been applied, it is updated
+ * with the current kernel-mode configuration. The CPU is then added to

fs/resctrl/rdtgroup.c int resctrl_online_mon_domain(struct rdt_resource *r, struct rdt_domain_hdr *hdr · line 4742

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+ * the bound group's kmode_cpu_mask, and the appropriate association is
+ * programmed for it.
+ */
+static void resctrl_kmode_online_cpu(unsigned int cpu)
+{
+	struct rdtgroup *rdtgrp = resctrl_kcfg.k_rdtgrp;
+	bool assign_mon = false;
+
+	if (resctrl_kcfg.kmode_cur == INHERIT_CTRL_AND_MON || !rdtgrp)
+		return;

If a CPU goes offline while a kernel-mode policy is active, and the policy is subsequently disabled (reverting to INHERIT_CTRL_AND_MON), does returning early here leave the newly onlined CPU with a stale kernel-mode resctrl association?

Looking at clear_closid_rmid(), it does not reset MSR_IA32_PQR_PLZA_ASSOC during CPU online initialization. Could this lead to the CPU executing CPL0 traffic with an invalid or malicious cache allocation if the stale CLOSID/RMID is reallocated?

--------------------------------------------------------------------

Yes. This is an issue.
Need to clear the kmode_cpu_list if the cpu being offlined is part of the current kmode. Also, need to disable PLZA on the CPU that is offlined.

Will take care of this in resctrl_offline_cpu().

-------------------------------------------------------------------

fs/resctrl/rdtgroup.c int resctrl_online_mon_domain(struct rdt_resource *r, struct rdt_domain_hdr *hdr · line 4746

Quoted 4 lines
fs/resctrl/rdtgroup.c +4 -0
+
+	assign_mon = (resctrl_kcfg.kmode_cur == GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU);
+
+	cpumask_set_cpu(cpu, &rdtgrp->kmode_cpu_mask);

Since the CPU is added to kmode_cpu_mask here when it comes online, shouldn't it be removed when it goes offline? Looking at resctrl_offline_cpu(), it clears the CPU from rdtgrp->cpu_mask:

	if (cpumask_test_and_clear_cpu(cpu, &rdtgrp->cpu_mask)) {
		clear_childcpus(rdtgrp, cpu);
		break;
	}

But there is no corresponding logic to clear it from kmode_cpu_mask. Does this cause stale state to be exposed to userspace via the kmode_cpus file?

----------------------------------------------------------------------

Ditto: Will take care of this in resctrl_offline_cpu().

----------------------------------------------------------------------

Is it possible for a MON group that is actively bound to a kernel-mode policy to be reparented?

Looking at rdtgroup_rename(), it allows reparenting if cpu_mask is empty without checking kmode_cpu_mask:

	if (!cpumask_empty(&rdtgrp->cpu_mask)) {
		ret = -EINVAL;
		goto out;
	}
Then mongrp_reparent() updates the closid but fails to reprogram PLZA MSRs for CPUs in kmode_cpu_mask:
	rdtgrp->mon.parent = new_prdtgrp;
	rdtgrp->closid = new_prdtgrp->closid;
	/* Propagate updated closid to all tasks in this group. */
	rdt_move_group_tasks(rdtgrp, rdtgrp, cpus);
	update_closid_rmid(cpus, NULL);

Does this leave CPUs in kmode_cpu_mask running with the old parent's CLOSID?

-----------------------------------------------------------------------

I don't see a reason to reparent the active kernel-mode group.

I'll add a check for:

if (!cpumask_empty(&rdtgrp->kmode_cpu_mask))

Thanks
Babu

author reviewer
#65 lore raw

PATCH RESEND v4 12/15 fs/resctrl: Hide kmode_cpus[_list] on groups not bound to kernel-mode

In reply to Babu Moger

kmode_cpus and kmode_cpus_list describe the CPU scope for the rdtgroup that owns the active kernel-mode binding. They are meaningful only for resctrl_kcfg.k_rdtgrp.

On groups that do not own the kernel-mode binding, they appear as inactive stubs and can let user space inspect or update state that does not apply to that group.

Hide kmode_cpus and kmode_cpus_list on groups that are not bound to kernel-mode. Keep the files hidden when groups are created, show them when rdtgroup_config_kmode() binds the group, and hide them again when the binding is released.

---
v4: Updated the changelog and code comments.

v3: New patch to hide/show "kmode_cpus" and "kmode_cpus_list" when kernel
modes binding changes.

---
 fs/resctrl/rdtgroup.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
fs/resctrl/rdtgroup.c +33 -0
index 413d3ff14546..c537846d9264 100644
@@ -1127,6 +1127,35 @@ static int resctrl_kernel_mode_show(struct kernfs_open_file *of,
 	return ret;
 }
 
+/**
+ * resctrl_kmode_files_set_visible() - Toggle visibility of the per-group
+ *		kernel-mode CPU files under @rdtgrp.
+ * @rdtgrp:	Resctrl group whose "kmode_cpus" / "kmode_cpus_list" files
+ *		should be hidden or shown.
+ * @visible:	%true to expose the files, %false to hide them via
+ *		kernfs_show().
+ *
+ * Each file is resolved independently as a sibling under @rdtgrp->kn.
+ * Failures from kernfs_find_and_get() are deliberately ignored, allowing
+ * callers to invoke this before activation, during group creation, or when
+ * the kernel-mode binding is updated.
+ */
+static void resctrl_kmode_files_set_visible(struct rdtgroup *rdtgrp, bool visible)
+{
+	/* Keep in sync with res_common_files[] entries for these files. */
+	static const char * const files[] = { "kmode_cpus", "kmode_cpus_list" };
+	struct kernfs_node *kn;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(files); i++) {
+		kn = kernfs_find_and_get(rdtgrp->kn, files[i]);
+		if (!kn)
+			continue;
+		kernfs_show(kn, visible);
+		kernfs_put(kn);
+	}
+}
+
 /**
  * rdtgroup_config_kmode_reset() - Tear down the kernel-mode binding on @rdtgrp
  * @rdtgrp:	Resctrl group whose kernel-mode binding is being released.
@@ -1155,6 +1184,7 @@ static void rdtgroup_config_kmode_reset(struct rdtgroup *rdtgrp,
 
 out_clear:
 	cpumask_clear(&rdtgrp->kmode_cpu_mask);
+	resctrl_kmode_files_set_visible(rdtgrp, false);
 	rdtgrp->kmode = false;
 }
 
@@ -3068,6 +3098,7 @@ static int rdt_get_tree(struct fs_context *fc)
 	if (ret)
 		goto out_closid_exit;
 
+	resctrl_kmode_files_set_visible(&rdtgroup_default, false);
 	kernfs_activate(rdtgroup_default.kn);
 
 	ret = rdtgroup_create_info_dir(rdtgroup_default.kn);
@@ -4098,6 +4129,7 @@ static int rdtgroup_mkdir_mon(struct kernfs_node *parent_kn,
 		goto out_unlock;
 	}
 
+	resctrl_kmode_files_set_visible(rdtgrp, false);
 	kernfs_activate(rdtgrp->kn);
 
 	/*
@@ -4142,6 +4174,7 @@ static int rdtgroup_mkdir_ctrl_mon(struct kernfs_node *parent_kn,
 	if (ret)
 		goto out_closid_free;
 
+	resctrl_kmode_files_set_visible(rdtgrp, false);
 	kernfs_activate(rdtgrp->kn);
 
 	ret = rdtgroup_init_alloc(rdtgrp);
Signature · 1 line
2.43.0
maintainer
#66 lore raw

Re: [RESEND PATCH v4 12/15] fs/resctrl: Hide kmode_cpus[_list] on groups not bound to kernel-mode

Hi Babu,

Quoted 88 lines · Babu Moger

kmode_cpus and kmode_cpus_list describe the CPU scope for the rdtgroup that owns the active kernel-mode binding. They are meaningful only for resctrl_kcfg.k_rdtgrp.

On groups that do not own the kernel-mode binding, they appear as inactive stubs and can let user space inspect or update state that does not apply to that group.

Hide kmode_cpus and kmode_cpus_list on groups that are not bound to kernel-mode. Keep the files hidden when groups are created, show them when rdtgroup_config_kmode() binds the group, and hide them again when the binding is released.

---
v4: Updated the changelog and code comments.

v3: New patch to hide/show "kmode_cpus" and "kmode_cpus_list" when kernel
modes binding changes.

---
 fs/resctrl/rdtgroup.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
fs/resctrl/rdtgroup.c +32 -0
index 413d3ff14546..c537846d9264 100644
@@ -1127,6 +1127,35 @@ static int resctrl_kernel_mode_show(struct kernfs_open_file *of,
 	return ret;
 }
 
+/**
+ * resctrl_kmode_files_set_visible() - Toggle visibility of the per-group
+ *		kernel-mode CPU files under @rdtgrp.
+ * @rdtgrp:	Resctrl group whose "kmode_cpus" / "kmode_cpus_list" files
+ *		should be hidden or shown.
+ * @visible:	%true to expose the files, %false to hide them via
+ *		kernfs_show().
+ *
+ * Each file is resolved independently as a sibling under @rdtgrp->kn.
+ * Failures from kernfs_find_and_get() are deliberately ignored, allowing
+ * callers to invoke this before activation, during group creation, or when
+ * the kernel-mode binding is updated.
+ */
+static void resctrl_kmode_files_set_visible(struct rdtgroup *rdtgrp, bool visible)
+{
+	/* Keep in sync with res_common_files[] entries for these files. */
+	static const char * const files[] = { "kmode_cpus", "kmode_cpus_list" };
+	struct kernfs_node *kn;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(files); i++) {
+		kn = kernfs_find_and_get(rdtgrp->kn, files[i]);
+		if (!kn)
+			continue;
+		kernfs_show(kn, visible);
+		kernfs_put(kn);
+	}
+}
+
 /**
  * rdtgroup_config_kmode_reset() - Tear down the kernel-mode binding on @rdtgrp
  * @rdtgrp:	Resctrl group whose kernel-mode binding is being released.
@@ -1155,6 +1184,7 @@ static void rdtgroup_config_kmode_reset(struct rdtgroup *rdtgrp,
 
 out_clear:
 	cpumask_clear(&rdtgrp->kmode_cpu_mask);
+	resctrl_kmode_files_set_visible(rdtgrp, false);
 	rdtgrp->kmode = false;
 }
 
@@ -3068,6 +3098,7 @@ static int rdt_get_tree(struct fs_context *fc)
 	if (ret)
 		goto out_closid_exit;
 
+	resctrl_kmode_files_set_visible(&rdtgroup_default, false);
 	kernfs_activate(rdtgroup_default.kn);
 
 	ret = rdtgroup_create_info_dir(rdtgroup_default.kn);
@@ -4098,6 +4129,7 @@ static int rdtgroup_mkdir_mon(struct kernfs_node *parent_kn,
 		goto out_unlock;
 	}
 
+	resctrl_kmode_files_set_visible(rdtgrp, false);
 	kernfs_activate(rdtgrp->kn);
 
 	/*

fs/resctrl/rdtgroup.c static int rdtgroup_mkdir_ctrl_mon(struct kernfs_node *parent_kn, · line 4180

Quoted 7 lines
fs/resctrl/rdtgroup.c +1 -0
@@ -4142,6 +4174,7 @@ static int rdtgroup_mkdir_ctrl_mon(struct kernfs_node *parent_kn,
 	if (ret)
 		goto out_closid_free;
 
+	resctrl_kmode_files_set_visible(rdtgrp, false);
 	kernfs_activate(rdtgrp->kn);
 
 	ret = rdtgroup_init_alloc(rdtgrp);

Sprinkling these resctrl_kmode_files_set_visible() in every path that creates these files seem error prone. Could this be simplified with a new, for example, rftype::create_hidden that will instruct the file to be created hidden. This would just create the file correctly from the beginning and eliminate these calls that go back and "fix things up" for kernel mode use. This may also eliminate the need to ignore errors in resctrl_kmode_files_set_visible() making this more robust while making it obvious how the file visibility is actually connected to the kernel mode since that would be the only points where the file visibility is changed.

Reinette

author reviewer
#67 lore raw

Re: [RESEND PATCH v4 12/15] fs/resctrl: Hide kmode_cpus[_list] on groups not bound to kernel-mode

Hi Reinette,

Quoted 97 lines · Reinette Chatre

Hi Babu,

Quoted 94 lines · Babu Moger

kmode_cpus and kmode_cpus_list describe the CPU scope for the rdtgroup that owns the active kernel-mode binding. They are meaningful only for resctrl_kcfg.k_rdtgrp.

On groups that do not own the kernel-mode binding, they appear as inactive stubs and can let user space inspect or update state that does not apply to that group.

Hide kmode_cpus and kmode_cpus_list on groups that are not bound to kernel-mode. Keep the files hidden when groups are created, show them when rdtgroup_config_kmode() binds the group, and hide them again when the binding is released.

---
v4: Updated the changelog and code comments.

v3: New patch to hide/show "kmode_cpus" and "kmode_cpus_list" when kernel
modes binding changes.

---
  fs/resctrl/rdtgroup.c | 33 +++++++++++++++++++++++++++++++++
  1 file changed, 33 insertions(+)
fs/resctrl/rdtgroup.c +33 -0
index 413d3ff14546..c537846d9264 100644
@@ -1127,6 +1127,35 @@ static int resctrl_kernel_mode_show(struct kernfs_open_file *of,
  	return ret;
  }
 
+/**
+ * resctrl_kmode_files_set_visible() - Toggle visibility of the per-group
+ *		kernel-mode CPU files under @rdtgrp.
+ * @rdtgrp:	Resctrl group whose "kmode_cpus" / "kmode_cpus_list" files
+ *		should be hidden or shown.
+ * @visible:	%true to expose the files, %false to hide them via
+ *		kernfs_show().
+ *
+ * Each file is resolved independently as a sibling under @rdtgrp->kn.
+ * Failures from kernfs_find_and_get() are deliberately ignored, allowing
+ * callers to invoke this before activation, during group creation, or when
+ * the kernel-mode binding is updated.
+ */
+static void resctrl_kmode_files_set_visible(struct rdtgroup *rdtgrp, bool visible)
+{
+	/* Keep in sync with res_common_files[] entries for these files. */
+	static const char * const files[] = { "kmode_cpus", "kmode_cpus_list" };
+	struct kernfs_node *kn;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(files); i++) {
+		kn = kernfs_find_and_get(rdtgrp->kn, files[i]);
+		if (!kn)
+			continue;
+		kernfs_show(kn, visible);
+		kernfs_put(kn);
+	}
+}
+
  /**
   * rdtgroup_config_kmode_reset() - Tear down the kernel-mode binding on @rdtgrp
   * @rdtgrp:	Resctrl group whose kernel-mode binding is being released.
@@ -1155,6 +1184,7 @@ static void rdtgroup_config_kmode_reset(struct rdtgroup *rdtgrp,
 
  out_clear:
  	cpumask_clear(&rdtgrp->kmode_cpu_mask);
+	resctrl_kmode_files_set_visible(rdtgrp, false);
  	rdtgrp->kmode = false;
  }
 
@@ -3068,6 +3098,7 @@ static int rdt_get_tree(struct fs_context *fc)
  	if (ret)
  		goto out_closid_exit;
 
+	resctrl_kmode_files_set_visible(&rdtgroup_default, false);
  	kernfs_activate(rdtgroup_default.kn);
 
  	ret = rdtgroup_create_info_dir(rdtgroup_default.kn);
@@ -4098,6 +4129,7 @@ static int rdtgroup_mkdir_mon(struct kernfs_node *parent_kn,
  		goto out_unlock;
  	}
 
+	resctrl_kmode_files_set_visible(rdtgrp, false);
  	kernfs_activate(rdtgrp->kn);
 
  	/*
@@ -4142,6 +4174,7 @@ static int rdtgroup_mkdir_ctrl_mon(struct kernfs_node *parent_kn,
  	if (ret)
  		goto out_closid_free;
 
+	resctrl_kmode_files_set_visible(rdtgrp, false);
  	kernfs_activate(rdtgrp->kn);
 
Quoted 10 lines

fs/resctrl/rdtgroup.c static int rdtgroup_mkdir_ctrl_mon(struct kernfs_node *parent_kn, · line 4180

Quoted 1 line
fs/resctrl/rdtgroup.c +0 -0
  	ret = rdtgroup_init_alloc(rdtgrp);

Sprinkling these resctrl_kmode_files_set_visible() in every path that creates these files seem error prone. Could this be simplified with a new, for example, rftype::create_hidden that will instruct the file to be created hidden. This would just create the file correctly from the beginning and eliminate these calls that go back and "fix things up" for kernel mode use. This may also eliminate the need to ignore errors in resctrl_kmode_files_set_visible() making this more robust while making it obvious how the file visibility is actually connected to the kernel mode since that would be the only points where the file visibility is changed.

Already discussed to create the hidden files for all the groups during the group creation. Then call resctrl_kmode_files_set_visible() based on visibility requirement when group is added/removed from global kernel mode.

https://lore.kernel.org/lkml/[email protected]/.

Thanks
Babu

author reviewer
#68 lore raw

PATCH RESEND v4 13/15 fs/resctrl: Add interface to modify kernel-mode via info/kernel_mode

In reply to Babu Moger

info/kernel_mode reports which kernel-mode policies the platform supports and which one is active, but it is read-only and does not show the rdtgroup bound to the active kernel-mode policy.

User space needs both pieces to manage kernel-mode assignment: it must be able to select a policy and bind the global-assign modes to a specific resctrl group, and it must be able to read back which group is currently bound.

Make info/kernel_mode writable and extend the read format to identify the bound group for active global-assign modes. Inactive global-assign modes are reported as "group=uninitialized"; INHERIT has no group suffix because it does not bind an rdtgroup. Square brackets mark the active mode on read only and must not be included when writing.

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

---
v4: Rewrote the changelog.
Moved all the fail path earlier so that failures will retain the old binding.
Taken care of requirement
assign_mon can be RDTMON_GROUP or RDTCTRL_GROUP. inherit_mon can only be RDTCTRL_GROUP.

v3: New patch to handle the changed interface file info/kernel_mode.

---
 Documentation/filesystems/resctrl.rst |  80 +++++++++
 fs/resctrl/rdtgroup.c                 | 238 +++++++++++++++++++++++++-
 2 files changed, 315 insertions(+), 3 deletions(-)
Documentation/filesystems/resctrl.rst +80 -0
index f3e941404967..5a13814d1325 100644
@@ -528,6 +528,86 @@ conveyed in the error returns from file operations. E.g.
 	# cat info/last_cmd_status
 	mask f7 has non-consecutive 1-bits
 
+"kernel_mode":
+	In the top level of the "info" directory, "kernel_mode" controls how
+	resource allocation and monitoring work in kernel mode. This is used on
+	some platforms to assign dedicated allocation and/or monitoring to
+	kernel-mode work.
+
+	Reading the file lists supported kernel modes, one per line.  The
+	currently active mode is wrapped in square brackets for display only.
+
+	The modes are displayed in the following format:
+	"<mode>:group=<ctrl>/<mon>/"
+
+	The inherit_ctrl_and_mon mode is shown as "<mode>" with no ":group=" suffix.
+	Inactive global-assign modes report "group=uninitialized".
+
+	The bound group path uses empty components when they do not apply:
+
+	"//":
+		The default (root) control group.
+	"<ctrl>//":
+		The control group named <ctrl>.
+	"/<mon>/":
+		The monitor group named <mon> under the default control group.
+	"<ctrl>/<mon>/":
+		The monitor group named <mon> under the control group named <ctrl>.
+
+	Modes:
+
+	- "inherit_ctrl_and_mon": Kernel work inherits allocation and monitoring
+	  from the current user-space task (default).
+	- "global_assign_ctrl_inherit_mon_per_cpu": A single allocation is
+	  assigned for all kernel work; monitoring is still inherited from user
+	  space.  Requires a CTRL_MON group.
+	- "global_assign_ctrl_assign_mon_per_cpu": A single resource group
+	  supplies both allocation and monitoring for all kernel work.  May be
+	  a CTRL_MON or MON group.
+
+	Only modes supported by the platform are listed on read.
+	Example::
+
+	  # mount -t resctrl resctrl /sys/fs/resctrl
+	  # cd /sys/fs/resctrl
+	  # cat info/kernel_mode
+	  [inherit_ctrl_and_mon]
+	  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
+	  global_assign_ctrl_assign_mon_per_cpu:group=uninitialized
+
+	The modes and binding can be modified by writing to the interface. Writing
+	one line (terminated by a newline) selects the active mode and binds it to
+	a resctrl group.
+
+	Writes must follow the format:
+	"<mode>:group=<ctrl>/<mon>/"
+
+	The ":group=<spec>" suffix is optional; when omitted the default (root)
+	control group is used for global-assign modes. Selecting a new mode or group
+	tears down any active global-assign binding before programming the new one,
+	including when switching between global-assign modes on the same group.
+	The inherit_ctrl_and_mon mode ignores any supplied group and clears the
+	active kernel-mode binding.  The mode must match one of the supported names
+	exactly, and modes not advertised by the platform cannot be set. The
+	display-only "group=uninitialized" form is rejected. Errors are reported in
+	"info/last_cmd_status".
+	Example::
+
+	  # mkdir ctrl1
+	  # echo "global_assign_ctrl_assign_mon_per_cpu:group=ctrl1//" \
+	         > info/kernel_mode
+
+	  # cat info/kernel_mode
+	  inherit_ctrl_and_mon
+	  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
+	  [global_assign_ctrl_assign_mon_per_cpu:group=ctrl1//]
+
+	  # echo "inherit_ctrl_and_mon" > info/kernel_mode
+	  # cat info/kernel_mode
+	  [inherit_ctrl_and_mon]
+	  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
+	  global_assign_ctrl_assign_mon_per_cpu:group=uninitialized
+
 Resource alloc and monitor groups
 =================================
 
fs/resctrl/rdtgroup.c +235 -3

270 lines not on this page · raw message

Signature · 1 line
2.43.0
#69 lore raw

Re: [RESEND PATCH v4 13/15] fs/resctrl: Add interface to modify kernel-mode via info/kernel_mode

Quoted 392 lines · Babu Moger

info/kernel_mode reports which kernel-mode policies the platform supports and which one is active, but it is read-only and does not show the rdtgroup bound to the active kernel-mode policy.

User space needs both pieces to manage kernel-mode assignment: it must be able to select a policy and bind the global-assign modes to a specific resctrl group, and it must be able to read back which group is currently bound.

Make info/kernel_mode writable and extend the read format to identify the bound group for active global-assign modes. Inactive global-assign modes are reported as "group=uninitialized"; INHERIT has no group suffix because it does not bind an rdtgroup. Square brackets mark the active mode on read only and must not be included when writing.

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

---
v4: Rewrote the changelog.
Moved all the fail path earlier so that failures will retain the old binding.
Taken care of requirement
assign_mon can be RDTMON_GROUP or RDTCTRL_GROUP. inherit_mon can only be RDTCTRL_GROUP.

v3: New patch to handle the changed interface file info/kernel_mode.

---
  Documentation/filesystems/resctrl.rst |  80 +++++++++
  fs/resctrl/rdtgroup.c                 | 238 +++++++++++++++++++++++++-
  2 files changed, 315 insertions(+), 3 deletions(-)
Documentation/filesystems/resctrl.rst +80 -0
index f3e941404967..5a13814d1325 100644
@@ -528,6 +528,86 @@ conveyed in the error returns from file operations. E.g.
  	# cat info/last_cmd_status
  	mask f7 has non-consecutive 1-bits
 
+"kernel_mode":
+	In the top level of the "info" directory, "kernel_mode" controls how
+	resource allocation and monitoring work in kernel mode. This is used on
+	some platforms to assign dedicated allocation and/or monitoring to
+	kernel-mode work.
+
+	Reading the file lists supported kernel modes, one per line.  The
+	currently active mode is wrapped in square brackets for display only.
+
+	The modes are displayed in the following format:
+	"<mode>:group=<ctrl>/<mon>/"
+
+	The inherit_ctrl_and_mon mode is shown as "<mode>" with no ":group=" suffix.
+	Inactive global-assign modes report "group=uninitialized".
+
+	The bound group path uses empty components when they do not apply:
+
+	"//":
+		The default (root) control group.
+	"<ctrl>//":
+		The control group named <ctrl>.
+	"/<mon>/":
+		The monitor group named <mon> under the default control group.
+	"<ctrl>/<mon>/":
+		The monitor group named <mon> under the control group named <ctrl>.
+
+	Modes:
+
+	- "inherit_ctrl_and_mon": Kernel work inherits allocation and monitoring
+	  from the current user-space task (default).
+	- "global_assign_ctrl_inherit_mon_per_cpu": A single allocation is
+	  assigned for all kernel work; monitoring is still inherited from user
+	  space.  Requires a CTRL_MON group.
+	- "global_assign_ctrl_assign_mon_per_cpu": A single resource group
+	  supplies both allocation and monitoring for all kernel work.  May be
+	  a CTRL_MON or MON group.
+
+	Only modes supported by the platform are listed on read.
+	Example::
+
+	  # mount -t resctrl resctrl /sys/fs/resctrl
+	  # cd /sys/fs/resctrl
+	  # cat info/kernel_mode
+	  [inherit_ctrl_and_mon]
+	  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
+	  global_assign_ctrl_assign_mon_per_cpu:group=uninitialized
+
+	The modes and binding can be modified by writing to the interface. Writing
+	one line (terminated by a newline) selects the active mode and binds it to
+	a resctrl group.
+
+	Writes must follow the format:
+	"<mode>:group=<ctrl>/<mon>/"
+
+	The ":group=<spec>" suffix is optional; when omitted the default (root)
+	control group is used for global-assign modes. Selecting a new mode or group
+	tears down any active global-assign binding before programming the new one,
+	including when switching between global-assign modes on the same group.
+	The inherit_ctrl_and_mon mode ignores any supplied group and clears the
+	active kernel-mode binding.  The mode must match one of the supported names
+	exactly, and modes not advertised by the platform cannot be set. The
+	display-only "group=uninitialized" form is rejected. Errors are reported in
+	"info/last_cmd_status".
+	Example::
+
+	  # mkdir ctrl1
+	  # echo "global_assign_ctrl_assign_mon_per_cpu:group=ctrl1//" \
+	         > info/kernel_mode
+
+	  # cat info/kernel_mode
+	  inherit_ctrl_and_mon
+	  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
+	  [global_assign_ctrl_assign_mon_per_cpu:group=ctrl1//]
+
+	  # echo "inherit_ctrl_and_mon" > info/kernel_mode
+	  # cat info/kernel_mode
+	  [inherit_ctrl_and_mon]
+	  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
+	  global_assign_ctrl_assign_mon_per_cpu:group=uninitialized
+
  Resource alloc and monitor groups
  =================================
 
fs/resctrl/rdtgroup.c +233 -2
index c537846d9264..7b06c3b3f00e 100644
@@ -1059,7 +1059,8 @@ static_assert(ARRAY_SIZE(resctrl_mode_str) == RESCTRL_NUM_KERNEL_MODES);
   * @v: unused
   *
   * Displays one line per mode set in resctrl_kcfg.kmode. Bracket the active
- * policy (resctrl_kcfg.kmode_cur).
+ * policy (resctrl_kcfg.kmode_cur). Square brackets are display-only; writes
+ * to info/kernel_mode must not include them.
   *
   * INHERIT_CTRL_AND_MON is displayed as "[inherit_ctrl_and_mon]" when active
   * or "inherit_ctrl_and_mon" when supported but inactive, with no :group=
@@ -1068,7 +1069,7 @@ static_assert(ARRAY_SIZE(resctrl_mode_str) == RESCTRL_NUM_KERNEL_MODES);
   * Global-assign modes append :group=. An inactive mode is emitted as
   * "<mode>:group=uninitialized". An active mode with a bound group is emitted
   * as "[<mode>:group=<ctrl>/<mon>/]", where <ctrl>/<mon>/ is derived from
- * resctrl_kcfg.k_rdtgrp.
+ * resctrl_kcfg.k_rdtgrp. The bracketed form is not accepted on write.
   *
   * Return: 0 on success, or -ENOENT on error.
   */
@@ -1164,6 +1165,8 @@ static void resctrl_kmode_files_set_visible(struct rdtgroup *rdtgrp, bool visibl
   * @kmode:	Kernel-mode policy currently active on @rdtgrp.
   *
   * Reset the kernel-mode binding on the CPUs in @rdtgrp's @kmode_cpu_mask.
+ * Called from resctrl_kernel_mode_write() whenever an active global-assign
+ * policy is replaced, including a mode change on the same group.
   */
  static void rdtgroup_config_kmode_reset(struct rdtgroup *rdtgrp,
  					enum resctrl_kernel_mode kmode)
@@ -1212,6 +1215,234 @@ static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp)
  	resctrl_kcfg.kmode_cur = INHERIT_CTRL_AND_MON;
  }
 
+/**
+ * rdtgroup_config_kmode() - Push @rdtgrp's kernel CLOSID/RMID to hardware
+ * @rdtgrp:	Resctrl group whose CLOSID/RMID should be programmed.
+ * @kmode:	Kernel-mode policy to program for @rdtgrp.
+ *
+ * @rdtgrp carries the CLOSID/RMID to program. For monitor groups, the CLOSID
+ * matches the parent control group while the RMID belongs to the monitor group.
+ *
+ * The caller (resctrl_kernel_mode_write()) is responsible for validating that
+ * the (kmode, group type) pair is permitted before invoking this helper.
+ * This helper records the current online CPUs in @rdtgrp->kmode_cpu_mask and
+ * programs those CPUs with @rdtgrp's CLOSID/RMID.
+ */
+static void rdtgroup_config_kmode(struct rdtgroup *rdtgrp, enum resctrl_kernel_mode kmode)
+{
+	bool assign_mon = (kmode == GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU);
+
+	/* A new binding starts with all currently online CPUs in scope. */
+	cpumask_copy(&rdtgrp->kmode_cpu_mask, cpu_online_mask);
+
+	resctrl_arch_configure_kmode(&rdtgrp->kmode_cpu_mask, rdtgrp->closid,
+				     rdtgrp->mon.rmid, assign_mon, true);
+
+	rdtgrp->kmode = true;
+	resctrl_kmode_files_set_visible(rdtgrp, true);
+}
+
+/**
+ * rdtgroup_by_kmode_path() - Resolve a "<ctrl>/<mon>/" path to an rdtgroup
+ * @ctrl_name:	Control-group name, or "" for the default control group.
+ * @mon_name:	Monitor-group name, or "" to select the control group itself.
+ *
+ * Matches the path syntax emitted by resctrl_kernel_mode_show():
+ *   "//"            - the default control group
+ *   "<ctrl>//"      - control group @ctrl_name
+ *   "/<mon>/"       - monitor group @mon_name under the default control group
+ *   "<ctrl>/<mon>/" - monitor group @mon_name under control group @ctrl_name
+ *
+ * An empty @ctrl_name selects &rdtgroup_default. Otherwise @ctrl_name must
+ * match an existing control group. If @mon_name is empty, the selected control
+ * group is returned; otherwise @mon_name is looked up in the selected control
+ * group's monitor children.
+ *
+ * Return: Pointer to the matching rdtgroup, or NULL if no such group exists.
+ */
+static struct rdtgroup *rdtgroup_by_kmode_path(const char *ctrl_name,
+					       const char *mon_name)
+{
+	struct rdtgroup *rdtg, *parent = &rdtgroup_default;
+
+	if (*ctrl_name) {
+		parent = NULL;
+		list_for_each_entry(rdtg, &rdt_all_groups, rdtgroup_list) {
+			if (rdtg->type != RDTCTRL_GROUP)
+				continue;
+			if (!strcmp(rdt_kn_name(rdtg->kn), ctrl_name)) {
+				parent = rdtg;
+				break;
+			}
+		}
+	}
+	if (!parent)
+		return NULL;
+
+	if (!*mon_name)
+		return parent;
+
+	list_for_each_entry(rdtg, &parent->mon.crdtgrp_list, mon.crdtgrp_list)
+		if (!strcmp(rdt_kn_name(rdtg->kn), mon_name))
+			return rdtg;
+	return NULL;
+}
+
+/**
+ * resctrl_kernel_mode_write() - Select kernel mode and bind group via info/kernel_mode
+ * @of:		kernfs file handle.
+ * @buf:	One line of the form "<mode>[:group=<ctrl>/<mon>/]"; must end
+ *		with a newline. Do not include the square brackets used to mark
+ *		the active mode in resctrl_kernel_mode_show(). Leading and trailing
+ *		whitespace is ignored, as is whitespace between the mode name and
+ *		an optional ":group=" suffix. The ":group=<spec>" suffix is
+ *		optional; when omitted the default control group
+ *		(&rdtgroup_default) is used.
+ * @nbytes:	Length of @buf.
+ * @off:	File offset (unused).
+ *
+ * Parses @buf, validates that <mode> is listed in resctrl_mode_str[] and is
+ * supported by the platform (resctrl_kcfg.kmode), resolves <ctrl>/<mon>/ to
+ * an existing rdtgroup (or picks &rdtgroup_default if no group was specified),
+ * treats INHERIT as an unbound mode, tears down any active global-assign
+ * binding via rdtgroup_config_kmode_reset(), programs hardware via
+ * rdtgroup_config_kmode() when the new mode is not INHERIT_CTRL_AND_MON, and
+ * on success updates resctrl_kcfg.k_rdtgrp and resctrl_kcfg.kmode_cur. The
+ * display-only "group=uninitialized" form is rejected.  Errors are reported
+ * in last_cmd_status.
+ *
+ * Return: @nbytes on success, negative errno with last_cmd_status set 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;
+	char *mode_str, *group_str, *slash;
+	const char *ctrl_name, *mon_name;
+	struct rdtgroup *rdtgrp;
+	int ret = 0;
+
+	if (nbytes == 0 || buf[nbytes - 1] != '\n')
+		return -EINVAL;
+	buf[nbytes - 1] = '\0';
+
+	/* Tolerate surrounding whitespace before mode parsing. */
+	buf = strim(buf);
+
+	/*
+	 * Split "<mode>:group=<spec>"; the ":group=<spec>" suffix is optional
+	 * and when omitted the default control group (&rdtgroup_default) is used.
+	 * Trim mode_str after the split so whitespace before ":group=" is ignored.
+	 * Square brackets from resctrl_kernel_mode_show() are not accepted.
+	 */
+	group_str = strstr(buf, ":group=");
+	if (group_str) {
+		*group_str = '\0';
+		group_str += strlen(":group=");
+	}
+	mode_str = strim(buf);
+
+	mutex_lock(&rdtgroup_mutex);
+	rdt_last_cmd_clear();
+
+	for (mode = 0; mode < RESCTRL_NUM_KERNEL_MODES; mode++)
+		if (!strcmp(mode_str, resctrl_mode_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_kcfg.kmode))) {
+		rdt_last_cmd_puts("Kernel mode not available\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	/*
+	 * INHERIT mode binds no rdtgroup. Ignore any user-supplied :group=
+	 * suffix and let show print the mode without a group.
+	 */
+	if (mode == INHERIT_CTRL_AND_MON) {
+		rdtgrp = NULL;
+		goto update_mode;
+	}
+
+	if (!group_str) {
+		/* No ":group=" suffix: fall back to the default control group. */
+		rdtgrp = &rdtgroup_default;
+	} else if (!strcmp(group_str, "uninitialized")) {
+		/* Display-only placeholder emitted by show; not selectable. */
+		rdt_last_cmd_puts("Cannot bind to 'uninitialized' group\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	} else {
+		/* Require exactly "<ctrl>/<mon>/" format */
+		slash = strchr(group_str, '/');
+		if (!slash) {
+			rdt_last_cmd_puts("Group must be <ctrl>/<mon>/\n");
+			ret = -EINVAL;
+			goto out_unlock;
+		}
+		*slash = '\0';
+		ctrl_name = group_str;
+		mon_name = slash + 1;
+		slash = strchr(mon_name, '/');
+		if (!slash || slash[1] != '\0') {
+			rdt_last_cmd_puts("Group must be <ctrl>/<mon>/\n");
+			ret = -EINVAL;
+			goto out_unlock;
+		}
+		*slash = '\0';
+
+		rdtgrp = rdtgroup_by_kmode_path(ctrl_name, mon_name);
+		if (!rdtgrp) {
+			rdt_last_cmd_puts("Group not found\n");
+			ret = -EINVAL;
+			goto out_unlock;
+		}
+	}
+
+	if (mode == GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU &&
+	    rdtgrp->type != RDTCTRL_GROUP) {
+		rdt_last_cmd_puts("global_assign_ctrl_inherit_mon_per_cpu requires a control group\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED ||
+	    rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
+		rdt_last_cmd_puts("Pseudo-locking in progress\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+update_mode:
+	/* No-op if the same mode is already active on the same group. */
+	if (resctrl_kcfg.kmode_cur == mode && resctrl_kcfg.k_rdtgrp == rdtgrp)
+		goto out_unlock;
+
+	/*
+	 * Tear down any active global-assign binding before applying the new
+	 * policy, including when only the mode changes on the same group.
+	 */
+	if (resctrl_kcfg.kmode_cur != INHERIT_CTRL_AND_MON)
+		rdtgroup_config_kmode_reset(resctrl_kcfg.k_rdtgrp,
+					    resctrl_kcfg.kmode_cur);
+
+	if (mode != INHERIT_CTRL_AND_MON)
+		rdtgroup_config_kmode(rdtgrp, mode);
+
+	resctrl_kcfg.k_rdtgrp = rdtgrp;
+	resctrl_kcfg.kmode_cur = mode;
+
+out_unlock:
+	mutex_unlock(&rdtgroup_mutex);
+	return ret ?: nbytes;
+}
+
  void *rdt_kn_parent_priv(struct kernfs_node *kn)
  {
  	/*
@@ -2117,9 +2348,10 @@ static struct rftype res_common_files[] = {
  	},

fs/resctrl/rdtgroup.c static struct rftype res_common_files[] = { · line 2357

Quoted 10 lines
fs/resctrl/rdtgroup.c +2 -1
  	{
  		.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,
  	},
  	{

Sashiko reported:

https://sashiko.dev/#/patchset/cover.1783461016.git.babu.moger%40amd.com?part=13

--- Patch [13]: [RESEND PATCH v4 13/15] fs/resctrl: Add interface to modify kernel-mode via info/kernel_mode --- commit f22e9f0418857d31e6764f0d2604e8d9fd48827e
Author: Babu Moger <[email protected]>
fs/resctrl: Add interface to modify kernel-mode via info/kernel_mode

info/kernel_mode reports which kernel-mode policies the platform supports and which one is active, but it is read-only and does not show the rdtgroup bound to the active kernel-mode policy. This patch makes it writable and extends the read format to identify the bound group.

Quoted 4 lines
fs/resctrl/rdtgroup.c +0 -0
index c537846d92648..7b06c3b3f00e0 100644

[ ... ]

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1220

Quoted 7 lines
fs/resctrl/rdtgroup.c +6 -0
@@ -1212,6 +1215,234 @@ static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp)
+static void rdtgroup_config_kmode(struct rdtgroup *rdtgrp, enum resctrl_kernel_mode kmode)
+{
+	bool assign_mon = (kmode == GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU);
+
+	/* A new binding starts with all currently online CPUs in scope. */
+	cpumask_copy(&rdtgrp->kmode_cpu_mask, cpu_online_mask);

In the resctrl_kernel_mode_write() call path, cpu_online_mask is accessed here without holding cpus_read_lock(). Could a concurrent CPU hotplug operation remove a CPU from cpu_online_mask immediately after this copy executes, causing on_each_cpu_mask() to issue a warning for offline CPUs?
---------------------------------------------------------------------

Yes. Need to hold cpus_read_lock() while accessing cpu_online_mask. Will add it in next revision.

---------------------------------------------------------------------

Also, if a CPU is brought offline while a kernel-mode policy is active, is it removed from kmode_cpu_mask? Looking at resctrl_offline_cpu(), it clears the CPU from the standard rdtgrp->cpu_mask but appears to leave kmode_cpu_mask unchanged. Will this accumulate offline CPU references, leading to warnings during later policy resets or changes?

----------------------------------------------------------------------

Yes. This is another issue. This will be fixed as part of

[RESEND PATCH v4 11/15] fs/resctrl: Program kernel-mode binding when CPU comes online

----------------------------------------------------------------------

Quoted 7 lines
fs/resctrl/rdtgroup.c +7 -0
+
+	resctrl_arch_configure_kmode(&rdtgrp->kmode_cpu_mask, rdtgrp->closid,
+				     rdtgrp->mon.rmid, assign_mon, true);
+
+	rdtgrp->kmode = true;
+	resctrl_kmode_files_set_visible(rdtgrp, true);
+}

[ ... ]

Quoted 3 lines
fs/resctrl/rdtgroup.c +3 -0
+static ssize_t resctrl_kernel_mode_write(struct kernfs_open_file *of,
+					 char *buf, size_t nbytes, loff_t off)
+{

[ ... ]

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1416

Quoted 2 lines
fs/resctrl/rdtgroup.c +2 -0
+	if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED ||
+	    rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {

This prevents assigning a kernel mode to a group that is already
pseudo-locked, but what prevents a group that is already bound to a kernel mode from entering pseudo-locksetup mode? Looking at rdtgroup_locksetup_enter(), it checks if rdtgrp->cpu_mask is
empty but does not check rdtgrp->kmode. If the group successfully enters
pseudo-locked mode, rdtgroup_pseudo_lock_create() calls closid_free().
Could this allow the closid to be reallocated to a new group while the
hardware remains actively programmed for the kernel-mode CPUs?

-------------------------------------------------------------------
Yes. Needs a check for rdtgrp->kmode in rdtgroup_locksetup_enter(). Will add it.
---------------------------------------------------------------------

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+		rdt_last_cmd_puts("Pseudo-locking in progress\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+update_mode:
+	/* No-op if the same mode is already active on the same group. */
+	if (resctrl_kcfg.kmode_cur == mode && resctrl_kcfg.k_rdtgrp == rdtgrp)
+		goto out_unlock;
+

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1436

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+	/*
+	 * Tear down any active global-assign binding before applying the new
+	 * policy, including when only the mode changes on the same group.
+	 */
+	if (resctrl_kcfg.kmode_cur != INHERIT_CTRL_AND_MON)
+		rdtgroup_config_kmode_reset(resctrl_kcfg.k_rdtgrp,
+					    resctrl_kcfg.kmode_cur);
+
+	if (mode != INHERIT_CTRL_AND_MON)
+		rdtgroup_config_kmode(rdtgrp, mode);

If a monitor group is bound to a kernel mode policy here, what happens if it is subsequently reparented via rename()? The existing rdtgroup_rename() logic allows the rename if rdtgrp->cpu_mask is empty, ignoring kmode_cpu_mask. Since mongrp_reparent() updates the
software closid but does not reprogram hardware MSRs for the CPUs in
kmode_cpu_mask, might the kernel-mode CPUs continue using the old parent's closid even after it is freed and reallocated?

---------------------------------------------------------------------
Yes. This needs a fix. Will add a check in rdtgroup_rename() for kmode_cpu_mask.

Thanks

Babu

maintainer
#70 lore raw

Re: [RESEND PATCH v4 13/15] fs/resctrl: Add interface to modify kernel-mode via info/kernel_mode

In reply to Babu Moger

Hi Babu,

Quoted 10 lines · Babu Moger

info/kernel_mode reports which kernel-mode policies the platform supports and which one is active, but it is read-only and does not show the rdtgroup bound to the active kernel-mode policy.

User space needs both pieces to manage kernel-mode assignment: it must be able to select a policy and bind the global-assign modes to a specific resctrl group, and it must be able to read back which group is currently bound.

Make info/kernel_mode writable and extend the read format to identify the

"Make info/kernel_mode writable and extend the read format" - what does this mean?

Quoted 9 lines

bound group for active global-assign modes. Inactive global-assign modes are reported as "group=uninitialized"; INHERIT has no group suffix because it does not bind an rdtgroup. Square brackets mark the active mode on read only and must not be included when writing.

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

---

...

Quoted 10 lines
---
 Documentation/filesystems/resctrl.rst |  80 +++++++++
 fs/resctrl/rdtgroup.c                 | 238 +++++++++++++++++++++++++-
 2 files changed, 315 insertions(+), 3 deletions(-)
Documentation/filesystems/resctrl.rst +0 -0
index f3e941404967..5a13814d1325 100644

Documentation/filesystems/resctrl.rst conveyed in the error returns from file operations. E.g. · line 535

Quoted 8 lines
Documentation/filesystems/resctrl.rst +5 -0
@@ -528,6 +528,86 @@ conveyed in the error returns from file operations. E.g.
 	# cat info/last_cmd_status
 	mask f7 has non-consecutive 1-bits
 
+"kernel_mode":
+	In the top level of the "info" directory, "kernel_mode" controls how
+	resource allocation and monitoring work in kernel mode. This is used on
+	some platforms to assign dedicated allocation and/or monitoring to
+	kernel-mode work.

"assign dedicated allocation and/or monitoring to kernel-mode work" - I do not understand what this means.

Documentation/filesystems/resctrl.rst conveyed in the error returns from file operations. E.g. · line 541

Quoted 6 lines
Documentation/filesystems/resctrl.rst +6 -0
+
+	Reading the file lists supported kernel modes, one per line.  The
+	currently active mode is wrapped in square brackets for display only.
+
+	The modes are displayed in the following format:
+	"<mode>:group=<ctrl>/<mon>/"

Please no! We know that resctrl needs to support more kernel modes and we know that their configuration interfaces will be different from what is needed to support AMD. They will introduce new modes to "kernel_mode" but those modes may bring new sytax to kernel_mode associated with those modes and/or introduce new files associated with those modes (like kmode_cpus for these modes). Writing something like above derails the plans to support those future kernel modes.

Instead, please write something like: "The display format depends on the kernel mode." followed by each supported kernel mode (nothing that there may be more) and what *that* kernel mode's display format looks like. Please do not enforce PLZA display format on this and all future kernel modes.

Quoted 32 lines
Documentation/filesystems/resctrl.rst +32 -0
+
+	The inherit_ctrl_and_mon mode is shown as "<mode>" with no ":group=" suffix.
+	Inactive global-assign modes report "group=uninitialized".
+
+	The bound group path uses empty components when they do not apply:
+
+	"//":
+		The default (root) control group.
+	"<ctrl>//":
+		The control group named <ctrl>.
+	"/<mon>/":
+		The monitor group named <mon> under the default control group.
+	"<ctrl>/<mon>/":
+		The monitor group named <mon> under the control group named <ctrl>.
+
+	Modes:
+
+	- "inherit_ctrl_and_mon": Kernel work inherits allocation and monitoring
+	  from the current user-space task (default).
+	- "global_assign_ctrl_inherit_mon_per_cpu": A single allocation is
+	  assigned for all kernel work; monitoring is still inherited from user
+	  space.  Requires a CTRL_MON group.
+	- "global_assign_ctrl_assign_mon_per_cpu": A single resource group
+	  supplies both allocation and monitoring for all kernel work.  May be
+	  a CTRL_MON or MON group.
+
+	Only modes supported by the platform are listed on read.
+	Example::
+
+	  # mount -t resctrl resctrl /sys/fs/resctrl
+	  # cd /sys/fs/resctrl
+	  # cat info/kernel_mode

Documentation/filesystems/resctrl.rst conveyed in the error returns from file operations. E.g. · line 583

Quoted 10 lines
Documentation/filesystems/resctrl.rst +10 -0
+	  [inherit_ctrl_and_mon]
+	  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
+	  global_assign_ctrl_assign_mon_per_cpu:group=uninitialized
+
+	The modes and binding can be modified by writing to the interface. Writing
+	one line (terminated by a newline) selects the active mode and binds it to
+	a resctrl group.
+
+	Writes must follow the format:
+	"<mode>:group=<ctrl>/<mon>/"

Please no. Here also, please replace with something like: "Write format depends on the kernel mode." Followed by a list of supported kernel modes and description of what format each mode uses.

Quoted 63 lines
Documentation/filesystems/resctrl.rst +27 -0
+
+	The ":group=<spec>" suffix is optional; when omitted the default (root)
+	control group is used for global-assign modes. Selecting a new mode or group
+	tears down any active global-assign binding before programming the new one,
+	including when switching between global-assign modes on the same group.
+	The inherit_ctrl_and_mon mode ignores any supplied group and clears the
+	active kernel-mode binding.  The mode must match one of the supported names
+	exactly, and modes not advertised by the platform cannot be set. The
+	display-only "group=uninitialized" form is rejected. Errors are reported in
+	"info/last_cmd_status".
+	Example::
+
+	  # mkdir ctrl1
+	  # echo "global_assign_ctrl_assign_mon_per_cpu:group=ctrl1//" \
+	         > info/kernel_mode
+
+	  # cat info/kernel_mode
+	  inherit_ctrl_and_mon
+	  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
+	  [global_assign_ctrl_assign_mon_per_cpu:group=ctrl1//]
+
+	  # echo "inherit_ctrl_and_mon" > info/kernel_mode
+	  # cat info/kernel_mode
+	  [inherit_ctrl_and_mon]
+	  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
+	  global_assign_ctrl_assign_mon_per_cpu:group=uninitialized
+
 Resource alloc and monitor groups
 =================================
 
fs/resctrl/rdtgroup.c +5 -2
index c537846d9264..7b06c3b3f00e 100644
@@ -1059,7 +1059,8 @@ static_assert(ARRAY_SIZE(resctrl_mode_str) == RESCTRL_NUM_KERNEL_MODES);
  * @v: unused
  *
  * Displays one line per mode set in resctrl_kcfg.kmode. Bracket the active
- * policy (resctrl_kcfg.kmode_cur).
+ * policy (resctrl_kcfg.kmode_cur). Square brackets are display-only; writes
+ * to info/kernel_mode must not include them.
  *
  * INHERIT_CTRL_AND_MON is displayed as "[inherit_ctrl_and_mon]" when active
  * or "inherit_ctrl_and_mon" when supported but inactive, with no :group=
@@ -1068,7 +1069,7 @@ static_assert(ARRAY_SIZE(resctrl_mode_str) == RESCTRL_NUM_KERNEL_MODES);
  * Global-assign modes append :group=. An inactive mode is emitted as
  * "<mode>:group=uninitialized". An active mode with a bound group is emitted
  * as "[<mode>:group=<ctrl>/<mon>/]", where <ctrl>/<mon>/ is derived from
- * resctrl_kcfg.k_rdtgrp.
+ * resctrl_kcfg.k_rdtgrp. The bracketed form is not accepted on write.
  *
  * Return: 0 on success, or -ENOENT on error.
  */
@@ -1164,6 +1165,8 @@ static void resctrl_kmode_files_set_visible(struct rdtgroup *rdtgrp, bool visibl
  * @kmode:	Kernel-mode policy currently active on @rdtgrp.
  *
  * Reset the kernel-mode binding on the CPUs in @rdtgrp's @kmode_cpu_mask.
+ * Called from resctrl_kernel_mode_write() whenever an active global-assign
+ * policy is replaced, including a mode change on the same group.
  */
 static void rdtgroup_config_kmode_reset(struct rdtgroup *rdtgrp,
 					enum resctrl_kernel_mode kmode)

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1223

Quoted 9 lines
fs/resctrl/rdtgroup.c +6 -0
@@ -1212,6 +1215,234 @@ static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp)
 	resctrl_kcfg.kmode_cur = INHERIT_CTRL_AND_MON;
 }
 
+/**
+ * rdtgroup_config_kmode() - Push @rdtgrp's kernel CLOSID/RMID to hardware
+ * @rdtgrp:	Resctrl group whose CLOSID/RMID should be programmed.
+ * @kmode:	Kernel-mode policy to program for @rdtgrp.
+ *
+ * @rdtgrp carries the CLOSID/RMID to program. For monitor groups, the CLOSID

I just cannot get used to this writing. It is not coherent. It reads like text from several people were just concatenated into this series.

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1229

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+ * matches the parent control group while the RMID belongs to the monitor group.
+ *
+ * The caller (resctrl_kernel_mode_write()) is responsible for validating that
+ * the (kmode, group type) pair is permitted before invoking this helper.
+ * This helper records the current online CPUs in @rdtgrp->kmode_cpu_mask and
+ * programs those CPUs with @rdtgrp's CLOSID/RMID.

Please do not describe the code in such detail - this detail can be seen from the code self. Please make the description high level. Please check whole series.

Quoted 33 lines
fs/resctrl/rdtgroup.c +33 -0
+ */
+static void rdtgroup_config_kmode(struct rdtgroup *rdtgrp, enum resctrl_kernel_mode kmode)
+{
+	bool assign_mon = (kmode == GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU);
+
+	/* A new binding starts with all currently online CPUs in scope. */
+	cpumask_copy(&rdtgrp->kmode_cpu_mask, cpu_online_mask);
+
+	resctrl_arch_configure_kmode(&rdtgrp->kmode_cpu_mask, rdtgrp->closid,
+				     rdtgrp->mon.rmid, assign_mon, true);
+
+	rdtgrp->kmode = true;
+	resctrl_kmode_files_set_visible(rdtgrp, true);
+}
+
+/**
+ * rdtgroup_by_kmode_path() - Resolve a "<ctrl>/<mon>/" path to an rdtgroup
+ * @ctrl_name:	Control-group name, or "" for the default control group.
+ * @mon_name:	Monitor-group name, or "" to select the control group itself.
+ *
+ * Matches the path syntax emitted by resctrl_kernel_mode_show():
+ *   "//"            - the default control group
+ *   "<ctrl>//"      - control group @ctrl_name
+ *   "/<mon>/"       - monitor group @mon_name under the default control group
+ *   "<ctrl>/<mon>/" - monitor group @mon_name under control group @ctrl_name
+ *
+ * An empty @ctrl_name selects &rdtgroup_default. Otherwise @ctrl_name must
+ * match an existing control group. If @mon_name is empty, the selected control
+ * group is returned; otherwise @mon_name is looked up in the selected control
+ * group's monitor children.
+ *
+ * Return: Pointer to the matching rdtgroup, or NULL if no such group exists.
+ */

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1272

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+static struct rdtgroup *rdtgroup_by_kmode_path(const char *ctrl_name,
+					       const char *mon_name)
+{
+	struct rdtgroup *rdtg, *parent = &rdtgroup_default;
+
+	if (*ctrl_name) {
+		parent = NULL;
+		list_for_each_entry(rdtg, &rdt_all_groups, rdtgroup_list) {
+			if (rdtg->type != RDTCTRL_GROUP)
+				continue;

All groups in rdt_all_groups are control groups, no?

Quoted 30 lines
fs/resctrl/rdtgroup.c +30 -0
+			if (!strcmp(rdt_kn_name(rdtg->kn), ctrl_name)) {
+				parent = rdtg;
+				break;
+			}
+		}
+	}
+	if (!parent)
+		return NULL;
+
+	if (!*mon_name)
+		return parent;
+
+	list_for_each_entry(rdtg, &parent->mon.crdtgrp_list, mon.crdtgrp_list)
+		if (!strcmp(rdt_kn_name(rdtg->kn), mon_name))
+			return rdtg;
+	return NULL;
+}
+
+/**
+ * resctrl_kernel_mode_write() - Select kernel mode and bind group via info/kernel_mode
+ * @of:		kernfs file handle.
+ * @buf:	One line of the form "<mode>[:group=<ctrl>/<mon>/]"; must end
+ *		with a newline. Do not include the square brackets used to mark
+ *		the active mode in resctrl_kernel_mode_show(). Leading and trailing
+ *		whitespace is ignored, as is whitespace between the mode name and
+ *		an optional ":group=" suffix. The ":group=<spec>" suffix is
+ *		optional; when omitted the default control group
+ *		(&rdtgroup_default) is used.
+ * @nbytes:	Length of @buf.
+ * @off:	File offset (unused).

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1312

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+ *
+ * Parses @buf, validates that <mode> is listed in resctrl_mode_str[] and is
+ * supported by the platform (resctrl_kcfg.kmode), resolves <ctrl>/<mon>/ to
+ * an existing rdtgroup (or picks &rdtgroup_default if no group was specified),
+ * treats INHERIT as an unbound mode, tears down any active global-assign
+ * binding via rdtgroup_config_kmode_reset(), programs hardware via
+ * rdtgroup_config_kmode() when the new mode is not INHERIT_CTRL_AND_MON, and
+ * on success updates resctrl_kcfg.k_rdtgrp and resctrl_kcfg.kmode_cur. The
+ * display-only "group=uninitialized" form is rejected.  Errors are reported
+ * in last_cmd_status.

This is just a summary of the code?

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1321

Quoted 9 lines
fs/resctrl/rdtgroup.c +9 -0
+ *
+ * Return: @nbytes on success, negative errno with last_cmd_status set 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;
+	char *mode_str, *group_str, *slash;
+	const char *ctrl_name, *mon_name;

(needs reverse fir)

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1326

Quoted 5 lines
fs/resctrl/rdtgroup.c +5 -0
+	struct rdtgroup *rdtgrp;
+	int ret = 0;
+
+	if (nbytes == 0 || buf[nbytes - 1] != '\n')
+		return -EINVAL;

function comment states: "negative errno with last_cmd_status set on error" yet here it returns negative errno without any update to last_cmd_status.
Please see commit 242c0ab4d51d ("fs/resctrl: Change last_cmd_status custom during input parsing")

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+	buf[nbytes - 1] = '\0';
+
+	/* Tolerate surrounding whitespace before mode parsing. */
+	buf = strim(buf);
+
+	/*
+	 * Split "<mode>:group=<spec>"; the ":group=<spec>" suffix is optional
+	 * and when omitted the default control group (&rdtgroup_default) is used.
+	 * Trim mode_str after the split so whitespace before ":group=" is ignored.
+	 * Square brackets from resctrl_kernel_mode_show() are not accepted.

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1346

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+	 */
+	group_str = strstr(buf, ":group=");
+	if (group_str) {
+		*group_str = '\0';
+		group_str += strlen(":group=");
+	}
+	mode_str = strim(buf);
+
+	mutex_lock(&rdtgroup_mutex);
+	rdt_last_cmd_clear();

Needs info_kn_lock()/info_kn_unlock()

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+
+	for (mode = 0; mode < RESCTRL_NUM_KERNEL_MODES; mode++)
+		if (!strcmp(mode_str, resctrl_mode_str[mode]))
+			break;
+
+	if (mode == RESCTRL_NUM_KERNEL_MODES) {
+		rdt_last_cmd_puts("Unknown kernel mode\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	}

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1366

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+
+	if (!(test_bit(mode, &resctrl_kcfg.kmode))) {
+		rdt_last_cmd_puts("Kernel mode not available\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	/*
+	 * INHERIT mode binds no rdtgroup. Ignore any user-supplied :group=
+	 * suffix and let show print the mode without a group.

copy&paste?

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1376

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+	 */
+	if (mode == INHERIT_CTRL_AND_MON) {
+		rdtgrp = NULL;
+		goto update_mode;
+	}
+
+	if (!group_str) {
+		/* No ":group=" suffix: fall back to the default control group. */
+		rdtgrp = &rdtgroup_default;
+	} else if (!strcmp(group_str, "uninitialized")) {

Why is this needed? Dropping this would just result in one of the group error messages that should be sufficient?

Quoted 30 lines
fs/resctrl/rdtgroup.c +30 -0
+		/* Display-only placeholder emitted by show; not selectable. */
+		rdt_last_cmd_puts("Cannot bind to 'uninitialized' group\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	} else {
+		/* Require exactly "<ctrl>/<mon>/" format */
+		slash = strchr(group_str, '/');
+		if (!slash) {
+			rdt_last_cmd_puts("Group must be <ctrl>/<mon>/\n");
+			ret = -EINVAL;
+			goto out_unlock;
+		}
+		*slash = '\0';
+		ctrl_name = group_str;
+		mon_name = slash + 1;
+		slash = strchr(mon_name, '/');
+		if (!slash || slash[1] != '\0') {
+			rdt_last_cmd_puts("Group must be <ctrl>/<mon>/\n");
+			ret = -EINVAL;
+			goto out_unlock;
+		}
+		*slash = '\0';
+
+		rdtgrp = rdtgroup_by_kmode_path(ctrl_name, mon_name);
+		if (!rdtgrp) {
+			rdt_last_cmd_puts("Group not found\n");
+			ret = -EINVAL;
+			goto out_unlock;
+		}
+	}

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1416

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+
+	if (mode == GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU &&
+	    rdtgrp->type != RDTCTRL_GROUP) {
+		rdt_last_cmd_puts("global_assign_ctrl_inherit_mon_per_cpu requires a control group\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED ||
+	    rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {

Could it be more specific to just require here that the resource group is required to be shareable?

Quoted 34 lines
fs/resctrl/rdtgroup.c +29 -0
+		rdt_last_cmd_puts("Pseudo-locking in progress\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+update_mode:
+	/* No-op if the same mode is already active on the same group. */
+	if (resctrl_kcfg.kmode_cur == mode && resctrl_kcfg.k_rdtgrp == rdtgrp)
+		goto out_unlock;
+
+	/*
+	 * Tear down any active global-assign binding before applying the new
+	 * policy, including when only the mode changes on the same group.
+	 */
+	if (resctrl_kcfg.kmode_cur != INHERIT_CTRL_AND_MON)
+		rdtgroup_config_kmode_reset(resctrl_kcfg.k_rdtgrp,
+					    resctrl_kcfg.kmode_cur);
+
+	if (mode != INHERIT_CTRL_AND_MON)
+		rdtgroup_config_kmode(rdtgrp, mode);
+
+	resctrl_kcfg.k_rdtgrp = rdtgrp;
+	resctrl_kcfg.kmode_cur = mode;
+
+out_unlock:
+	mutex_unlock(&rdtgroup_mutex);
+	return ret ?: nbytes;
+}
+
 void *rdt_kn_parent_priv(struct kernfs_node *kn)
 {
 	/*
@@ -2117,9 +2348,10 @@ static struct rftype res_common_files[] = {
 	},

fs/resctrl/rdtgroup.c static struct rftype res_common_files[] = { · line 2357

Quoted 10 lines
fs/resctrl/rdtgroup.c +2 -1
 	{
 		.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,
 	},
 	{

Reinette

author reviewer
#71 lore raw

Re: [RESEND PATCH v4 13/15] fs/resctrl: Add interface to modify kernel-mode via info/kernel_mode

Hi Reinette,

Quoted 7 lines · Reinette Chatre

Hi Babu,

Quoted 4 lines · Babu Moger

info/kernel_mode reports which kernel-mode policies the platform supports and which one is active, but it is read-only and does not show the rdtgroup bound to the active kernel-mode policy.

Quoted 8 lines
Quoted 6 lines

User space needs both pieces to manage kernel-mode assignment: it must be able to select a policy and bind the global-assign modes to a specific resctrl group, and it must be able to read back which group is currently bound.

Make info/kernel_mode writable and extend the read format to identify the

"Make info/kernel_mode writable and extend the read format" - what does this mean?

Will rewrite the changelog. The text "extend the read format to identify" is not nessasary.

Quoted 26 lines
Quoted 10 lines

bound group for active global-assign modes. Inactive global-assign modes are reported as "group=uninitialized"; INHERIT has no group suffix because it does not bind an rdtgroup. Square brackets mark the active mode on read only and must not be included when writing.

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

---

...

Quoted 13 lines
---
  Documentation/filesystems/resctrl.rst |  80 +++++++++
  fs/resctrl/rdtgroup.c                 | 238 +++++++++++++++++++++++++-
  2 files changed, 315 insertions(+), 3 deletions(-)
Documentation/filesystems/resctrl.rst +0 -0
index f3e941404967..5a13814d1325 100644
@@ -528,6 +528,86 @@ conveyed in the error returns from file operations. E.g.
  	# cat info/last_cmd_status
  	mask f7 has non-consecutive 1-bits
 
Quoted 8 lines

Documentation/filesystems/resctrl.rst conveyed in the error returns from file operations. E.g. · line 535

Quoted 5 lines
Documentation/filesystems/resctrl.rst +5 -0
+"kernel_mode":
+	In the top level of the "info" directory, "kernel_mode" controls how
+	resource allocation and monitoring work in kernel mode. This is used on
+	some platforms to assign dedicated allocation and/or monitoring to
+	kernel-mode work.

"assign dedicated allocation and/or monitoring to kernel-mode work" - I do not understand what this means.

I need to write in terms of CTLR_MON and MON group. Let me update that.

Quoted 14 lines

Documentation/filesystems/resctrl.rst conveyed in the error returns from file operations. E.g. · line 541

Quoted 7 lines
Documentation/filesystems/resctrl.rst +6 -0
+
+	Reading the file lists supported kernel modes, one per line.  The
+	currently active mode is wrapped in square brackets for display only.
+
+	The modes are displayed in the following format:
+	"<mode>:group=<ctrl>/<mon>/"

Please no! We know that resctrl needs to support more kernel modes and we know that their configuration interfaces will be different from what is needed to support AMD. They will introduce new modes to "kernel_mode" but those modes may bring new sytax to kernel_mode associated with those modes and/or introduce new files associated with those modes (like kmode_cpus for these modes). Writing something like above derails the plans to support those future kernel modes.

Quoted 4 lines

Instead, please write something like: "The display format depends on the kernel mode." followed by each supported kernel mode (nothing that there may be more) and what *that* kernel mode's display format looks like. Please do not enforce PLZA display format on this and all future kernel modes.

Ok.

Quoted 40 lines
Quoted 40 lines
Documentation/filesystems/resctrl.rst +38 -0
+
+	The inherit_ctrl_and_mon mode is shown as "<mode>" with no ":group=" suffix.
+	Inactive global-assign modes report "group=uninitialized".
+
+	The bound group path uses empty components when they do not apply:
+
+	"//":
+		The default (root) control group.
+	"<ctrl>//":
+		The control group named <ctrl>.
+	"/<mon>/":
+		The monitor group named <mon> under the default control group.
+	"<ctrl>/<mon>/":
+		The monitor group named <mon> under the control group named <ctrl>.
+
+	Modes:
+
+	- "inherit_ctrl_and_mon": Kernel work inherits allocation and monitoring
+	  from the current user-space task (default).
+	- "global_assign_ctrl_inherit_mon_per_cpu": A single allocation is
+	  assigned for all kernel work; monitoring is still inherited from user
+	  space.  Requires a CTRL_MON group.
+	- "global_assign_ctrl_assign_mon_per_cpu": A single resource group
+	  supplies both allocation and monitoring for all kernel work.  May be
+	  a CTRL_MON or MON group.
+
+	Only modes supported by the platform are listed on read.
+	Example::
+
+	  # mount -t resctrl resctrl /sys/fs/resctrl
+	  # cd /sys/fs/resctrl
+	  # cat info/kernel_mode
+	  [inherit_ctrl_and_mon]
+	  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
+	  global_assign_ctrl_assign_mon_per_cpu:group=uninitialized
+
+	The modes and binding can be modified by writing to the interface. Writing
+	one line (terminated by a newline) selects the active mode and binds it to
Quoted 8 lines

Documentation/filesystems/resctrl.rst conveyed in the error returns from file operations. E.g. · line 583

Quoted 4 lines
Documentation/filesystems/resctrl.rst +4 -0
+	a resctrl group.
+
+	Writes must follow the format:
+	"<mode>:group=<ctrl>/<mon>/"

Please no. Here also, please replace with something like: "Write format depends on the kernel mode." Followed by a list of supported kernel modes and description of what format each mode uses.

ok.

Quoted 67 lines
Quoted 67 lines
Documentation/filesystems/resctrl.rst +27 -0
+
+	The ":group=<spec>" suffix is optional; when omitted the default (root)
+	control group is used for global-assign modes. Selecting a new mode or group
+	tears down any active global-assign binding before programming the new one,
+	including when switching between global-assign modes on the same group.
+	The inherit_ctrl_and_mon mode ignores any supplied group and clears the
+	active kernel-mode binding.  The mode must match one of the supported names
+	exactly, and modes not advertised by the platform cannot be set. The
+	display-only "group=uninitialized" form is rejected. Errors are reported in
+	"info/last_cmd_status".
+	Example::
+
+	  # mkdir ctrl1
+	  # echo "global_assign_ctrl_assign_mon_per_cpu:group=ctrl1//" \
+	         > info/kernel_mode
+
+	  # cat info/kernel_mode
+	  inherit_ctrl_and_mon
+	  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
+	  [global_assign_ctrl_assign_mon_per_cpu:group=ctrl1//]
+
+	  # echo "inherit_ctrl_and_mon" > info/kernel_mode
+	  # cat info/kernel_mode
+	  [inherit_ctrl_and_mon]
+	  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
+	  global_assign_ctrl_assign_mon_per_cpu:group=uninitialized
+
  Resource alloc and monitor groups
  =================================
 
fs/resctrl/rdtgroup.c +5 -2
index c537846d9264..7b06c3b3f00e 100644
@@ -1059,7 +1059,8 @@ static_assert(ARRAY_SIZE(resctrl_mode_str) == RESCTRL_NUM_KERNEL_MODES);
   * @v: unused
   *
   * Displays one line per mode set in resctrl_kcfg.kmode. Bracket the active
- * policy (resctrl_kcfg.kmode_cur).
+ * policy (resctrl_kcfg.kmode_cur). Square brackets are display-only; writes
+ * to info/kernel_mode must not include them.
   *
   * INHERIT_CTRL_AND_MON is displayed as "[inherit_ctrl_and_mon]" when active
   * or "inherit_ctrl_and_mon" when supported but inactive, with no :group=
@@ -1068,7 +1069,7 @@ static_assert(ARRAY_SIZE(resctrl_mode_str) == RESCTRL_NUM_KERNEL_MODES);
   * Global-assign modes append :group=. An inactive mode is emitted as
   * "<mode>:group=uninitialized". An active mode with a bound group is emitted
   * as "[<mode>:group=<ctrl>/<mon>/]", where <ctrl>/<mon>/ is derived from
- * resctrl_kcfg.k_rdtgrp.
+ * resctrl_kcfg.k_rdtgrp. The bracketed form is not accepted on write.
   *
   * Return: 0 on success, or -ENOENT on error.
   */
@@ -1164,6 +1165,8 @@ static void resctrl_kmode_files_set_visible(struct rdtgroup *rdtgrp, bool visibl
   * @kmode:	Kernel-mode policy currently active on @rdtgrp.
   *
   * Reset the kernel-mode binding on the CPUs in @rdtgrp's @kmode_cpu_mask.
+ * Called from resctrl_kernel_mode_write() whenever an active global-assign
+ * policy is replaced, including a mode change on the same group.
   */
  static void rdtgroup_config_kmode_reset(struct rdtgroup *rdtgrp,
  					enum resctrl_kernel_mode kmode)
@@ -1212,6 +1215,234 @@ static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp)
  	resctrl_kcfg.kmode_cur = INHERIT_CTRL_AND_MON;
  }
 
Quoted 9 lines

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1223

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+/**
+ * rdtgroup_config_kmode() - Push @rdtgrp's kernel CLOSID/RMID to hardware
+ * @rdtgrp:	Resctrl group whose CLOSID/RMID should be programmed.
+ * @kmode:	Kernel-mode policy to program for @rdtgrp.
+ *
+ * @rdtgrp carries the CLOSID/RMID to program. For monitor groups, the CLOSID

I just cannot get used to this writing. It is not coherent. It reads like text from several people were just concatenated into this series.

Will rewrite it.

Quoted 10 lines

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1229

Quoted 7 lines
fs/resctrl/rdtgroup.c +6 -0
+ * matches the parent control group while the RMID belongs to the monitor group.
+ *
+ * The caller (resctrl_kernel_mode_write()) is responsible for validating that
+ * the (kmode, group type) pair is permitted before invoking this helper.
+ * This helper records the current online CPUs in @rdtgrp->kmode_cpu_mask and
+ * programs those CPUs with @rdtgrp's CLOSID/RMID.

Please do not describe the code in such detail - this detail can be seen from the code self. Please make the description high level. Please check whole series.

ok.

Quoted 38 lines
Quoted 38 lines
fs/resctrl/rdtgroup.c +37 -0
+ */
+static void rdtgroup_config_kmode(struct rdtgroup *rdtgrp, enum resctrl_kernel_mode kmode)
+{
+	bool assign_mon = (kmode == GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU);
+
+	/* A new binding starts with all currently online CPUs in scope. */
+	cpumask_copy(&rdtgrp->kmode_cpu_mask, cpu_online_mask);
+
+	resctrl_arch_configure_kmode(&rdtgrp->kmode_cpu_mask, rdtgrp->closid,
+				     rdtgrp->mon.rmid, assign_mon, true);
+
+	rdtgrp->kmode = true;
+	resctrl_kmode_files_set_visible(rdtgrp, true);
+}
+
+/**
+ * rdtgroup_by_kmode_path() - Resolve a "<ctrl>/<mon>/" path to an rdtgroup
+ * @ctrl_name:	Control-group name, or "" for the default control group.
+ * @mon_name:	Monitor-group name, or "" to select the control group itself.
+ *
+ * Matches the path syntax emitted by resctrl_kernel_mode_show():
+ *   "//"            - the default control group
+ *   "<ctrl>//"      - control group @ctrl_name
+ *   "/<mon>/"       - monitor group @mon_name under the default control group
+ *   "<ctrl>/<mon>/" - monitor group @mon_name under control group @ctrl_name
+ *
+ * An empty @ctrl_name selects &rdtgroup_default. Otherwise @ctrl_name must
+ * match an existing control group. If @mon_name is empty, the selected control
+ * group is returned; otherwise @mon_name is looked up in the selected control
+ * group's monitor children.
+ *
+ * Return: Pointer to the matching rdtgroup, or NULL if no such group exists.
+ */
+static struct rdtgroup *rdtgroup_by_kmode_path(const char *ctrl_name,
+					       const char *mon_name)
+{
+	struct rdtgroup *rdtg, *parent = &rdtgroup_default;
Quoted 8 lines

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1272

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+
+	if (*ctrl_name) {
+		parent = NULL;
+		list_for_each_entry(rdtg, &rdt_all_groups, rdtgroup_list) {
+			if (rdtg->type != RDTCTRL_GROUP)
+				continue;

All groups in rdt_all_groups are control groups, no?

Yes. I think so. Let me check that.

Quoted 35 lines
Quoted 35 lines
fs/resctrl/rdtgroup.c +34 -0
+			if (!strcmp(rdt_kn_name(rdtg->kn), ctrl_name)) {
+				parent = rdtg;
+				break;
+			}
+		}
+	}
+	if (!parent)
+		return NULL;
+
+	if (!*mon_name)
+		return parent;
+
+	list_for_each_entry(rdtg, &parent->mon.crdtgrp_list, mon.crdtgrp_list)
+		if (!strcmp(rdt_kn_name(rdtg->kn), mon_name))
+			return rdtg;
+	return NULL;
+}
+
+/**
+ * resctrl_kernel_mode_write() - Select kernel mode and bind group via info/kernel_mode
+ * @of:		kernfs file handle.
+ * @buf:	One line of the form "<mode>[:group=<ctrl>/<mon>/]"; must end
+ *		with a newline. Do not include the square brackets used to mark
+ *		the active mode in resctrl_kernel_mode_show(). Leading and trailing
+ *		whitespace is ignored, as is whitespace between the mode name and
+ *		an optional ":group=" suffix. The ":group=<spec>" suffix is
+ *		optional; when omitted the default control group
+ *		(&rdtgroup_default) is used.
+ * @nbytes:	Length of @buf.
+ * @off:	File offset (unused).
+ *
+ * Parses @buf, validates that <mode> is listed in resctrl_mode_str[] and is
+ * supported by the platform (resctrl_kcfg.kmode), resolves <ctrl>/<mon>/ to
+ * an existing rdtgroup (or picks &rdtgroup_default if no group was specified),
Quoted 8 lines

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1312

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+ * treats INHERIT as an unbound mode, tears down any active global-assign
+ * binding via rdtgroup_config_kmode_reset(), programs hardware via
+ * rdtgroup_config_kmode() when the new mode is not INHERIT_CTRL_AND_MON, and
+ * on success updates resctrl_kcfg.k_rdtgrp and resctrl_kcfg.kmode_cur. The
+ * display-only "group=uninitialized" form is rejected.  Errors are reported
+ * in last_cmd_status.

This is just a summary of the code?

Let me update this. Let me convert it to high level summary,

Quoted 12 lines

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1321

Quoted 10 lines
fs/resctrl/rdtgroup.c +9 -0
+ *
+ * Return: @nbytes on success, negative errno with last_cmd_status set 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;
+	char *mode_str, *group_str, *slash;
+	const char *ctrl_name, *mon_name;

(needs reverse fir)

Yes.

Quoted 10 lines

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1326

Quoted 6 lines
fs/resctrl/rdtgroup.c +5 -0
+	struct rdtgroup *rdtgrp;
+	int ret = 0;
+
+	if (nbytes == 0 || buf[nbytes - 1] != '\n')
+		return -EINVAL;

function comment states: "negative errno with last_cmd_status set on error" yet here it returns negative errno without any update to last_cmd_status.
Please see commit 242c0ab4d51d ("fs/resctrl: Change last_cmd_status custom during input parsing")

Sure.

Quoted 15 lines
Quoted 15 lines
fs/resctrl/rdtgroup.c +14 -0
+	buf[nbytes - 1] = '\0';
+
+	/* Tolerate surrounding whitespace before mode parsing. */
+	buf = strim(buf);
+
+	/*
+	 * Split "<mode>:group=<spec>"; the ":group=<spec>" suffix is optional
+	 * and when omitted the default control group (&rdtgroup_default) is used.
+	 * Trim mode_str after the split so whitespace before ":group=" is ignored.
+	 * Square brackets from resctrl_kernel_mode_show() are not accepted.
+	 */
+	group_str = strstr(buf, ":group=");
+	if (group_str) {
+		*group_str = '\0';
Quoted 8 lines

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1346

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+		group_str += strlen(":group=");
+	}
+	mode_str = strim(buf);
+
+	mutex_lock(&rdtgroup_mutex);
+	rdt_last_cmd_clear();

Needs info_kn_lock()/info_kn_unlock()

Sure.

Quoted 15 lines
Quoted 15 lines
fs/resctrl/rdtgroup.c +14 -0
+
+	for (mode = 0; mode < RESCTRL_NUM_KERNEL_MODES; mode++)
+		if (!strcmp(mode_str, resctrl_mode_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_kcfg.kmode))) {
+		rdt_last_cmd_puts("Kernel mode not available\n");
+		ret = -EINVAL;
Quoted 8 lines

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1366

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+		goto out_unlock;
+	}
+
+	/*
+	 * INHERIT mode binds no rdtgroup. Ignore any user-supplied :group=
+	 * suffix and let show print the mode without a group.

copy&paste?

Hmm.. Text seems correct here to me. Did I miss something?

All these code will change with new interface.

Quoted 14 lines

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1376

Quoted 11 lines
fs/resctrl/rdtgroup.c +10 -0
+	 */
+	if (mode == INHERIT_CTRL_AND_MON) {
+		rdtgrp = NULL;
+		goto update_mode;
+	}
+
+	if (!group_str) {
+		/* No ":group=" suffix: fall back to the default control group. */
+		rdtgrp = &rdtgroup_default;
+	} else if (!strcmp(group_str, "uninitialized")) {

Why is this needed? Dropping this would just result in one of the group error messages that should be sufficient?

Yes. That is correct.

Quoted 36 lines
Quoted 36 lines
fs/resctrl/rdtgroup.c +35 -0
+		/* Display-only placeholder emitted by show; not selectable. */
+		rdt_last_cmd_puts("Cannot bind to 'uninitialized' group\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	} else {
+		/* Require exactly "<ctrl>/<mon>/" format */
+		slash = strchr(group_str, '/');
+		if (!slash) {
+			rdt_last_cmd_puts("Group must be <ctrl>/<mon>/\n");
+			ret = -EINVAL;
+			goto out_unlock;
+		}
+		*slash = '\0';
+		ctrl_name = group_str;
+		mon_name = slash + 1;
+		slash = strchr(mon_name, '/');
+		if (!slash || slash[1] != '\0') {
+			rdt_last_cmd_puts("Group must be <ctrl>/<mon>/\n");
+			ret = -EINVAL;
+			goto out_unlock;
+		}
+		*slash = '\0';
+
+		rdtgrp = rdtgroup_by_kmode_path(ctrl_name, mon_name);
+		if (!rdtgrp) {
+			rdt_last_cmd_puts("Group not found\n");
+			ret = -EINVAL;
+			goto out_unlock;
+		}
+	}
+
+	if (mode == GLOBAL_ASSIGN_CTRL_INHERIT_MON_PER_CPU &&
+	    rdtgrp->type != RDTCTRL_GROUP) {
+		rdt_last_cmd_puts("global_assign_ctrl_inherit_mon_per_cpu requires a control group\n");
+		ret = -EINVAL;
Quoted 9 lines

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1416

Quoted 5 lines
fs/resctrl/rdtgroup.c +5 -0
+		goto out_unlock;
+	}
+
+	if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED ||
+	    rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {

Could it be more specific to just require here that the resource group is required to be shareable?

Yes. Correct.

Quoted 47 lines
Quoted 34 lines
fs/resctrl/rdtgroup.c +29 -0
+		rdt_last_cmd_puts("Pseudo-locking in progress\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+update_mode:
+	/* No-op if the same mode is already active on the same group. */
+	if (resctrl_kcfg.kmode_cur == mode && resctrl_kcfg.k_rdtgrp == rdtgrp)
+		goto out_unlock;
+
+	/*
+	 * Tear down any active global-assign binding before applying the new
+	 * policy, including when only the mode changes on the same group.
+	 */
+	if (resctrl_kcfg.kmode_cur != INHERIT_CTRL_AND_MON)
+		rdtgroup_config_kmode_reset(resctrl_kcfg.k_rdtgrp,
+					    resctrl_kcfg.kmode_cur);
+
+	if (mode != INHERIT_CTRL_AND_MON)
+		rdtgroup_config_kmode(rdtgrp, mode);
+
+	resctrl_kcfg.k_rdtgrp = rdtgrp;
+	resctrl_kcfg.kmode_cur = mode;
+
+out_unlock:
+	mutex_unlock(&rdtgroup_mutex);
+	return ret ?: nbytes;
+}
+
  void *rdt_kn_parent_priv(struct kernfs_node *kn)
  {
  	/*
@@ -2117,9 +2348,10 @@ static struct rftype res_common_files[] = {
  	},

fs/resctrl/rdtgroup.c static struct rftype res_common_files[] = { · line 2357

Quoted 10 lines
fs/resctrl/rdtgroup.c +2 -1
  	{
  		.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,
  	},
  	{

Reinette

maintainer
#72 lore raw

Re: [RESEND PATCH v4 13/15] fs/resctrl: Add interface to modify kernel-mode via info/kernel_mode

Hi Babu,

Quoted 14 lines · Babu Moger
Quoted 13 lines · Reinette Chatre
Quoted 9 lines · Babu Moger

+ *
+ * Return: @nbytes on success, negative errno with last_cmd_status set on error.
+ */

fs/resctrl/rdtgroup.c +6 -0
+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;
+    char *mode_str, *group_str, *slash;
+    const char *ctrl_name, *mon_name;

...

Quoted 23 lines
Quoted 14 lines
Quoted 14 lines
fs/resctrl/rdtgroup.c +14 -0
+
+    for (mode = 0; mode < RESCTRL_NUM_KERNEL_MODES; mode++)
+        if (!strcmp(mode_str, resctrl_mode_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_kcfg.kmode))) {
+        rdt_last_cmd_puts("Kernel mode not available\n");
+        ret = -EINVAL;
Quoted 8 lines
Quoted 6 lines

+        goto out_unlock;
+    }
+
+    /*
+     * INHERIT mode binds no rdtgroup. Ignore any user-supplied :group= +     * suffix and let show print the mode without a group.

copy&paste?

Quoted 1 line

Hmm.. Text seems correct here to me. Did I miss something?

This is the function that parses user input so the comment describing what should be displayed to user space seems out of place.

Reinette

#73 lore raw

Re: [RESEND PATCH v4 13/15] fs/resctrl: Add interface to modify kernel-mode via info/kernel_mode

Hi Reinette,

Quoted 43 lines · Reinette Chatre

Hi Babu,

Quoted 14 lines · Babu Moger
Quoted 13 lines · Reinette Chatre
Quoted 9 lines · Babu Moger

+ *
+ * Return: @nbytes on success, negative errno with last_cmd_status set on error.
+ */

fs/resctrl/rdtgroup.c +6 -0
+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;
+    char *mode_str, *group_str, *slash;
+    const char *ctrl_name, *mon_name;

...

Quoted 23 lines
Quoted 22 lines
Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+
+    for (mode = 0; mode < RESCTRL_NUM_KERNEL_MODES; mode++)
+        if (!strcmp(mode_str, resctrl_mode_str[mode]))
+            break;
+
+    if (mode == RESCTRL_NUM_KERNEL_MODES) {
+        rdt_last_cmd_puts("Unknown kernel mode\n");
+        ret = -EINVAL;
+        goto out_unlock;
+    }

fs/resctrl/rdtgroup.c static void rdtgroup_kmode_detach(struct rdtgroup *rdtgrp) · line 1366

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+
+    if (!(test_bit(mode, &resctrl_kcfg.kmode))) {
+        rdt_last_cmd_puts("Kernel mode not available\n");
+        ret = -EINVAL;
+        goto out_unlock;
+    }
+
+    /*
+     * INHERIT mode binds no rdtgroup. Ignore any user-supplied :group=
+     * suffix and let show print the mode without a group.

copy&paste?

Quoted 5 lines
Quoted 1 line

Hmm.. Text seems correct here to me. Did I miss something?

This is the function that parses user input so the comment describing what should be displayed to user space seems out of place.

Got it. Thanks
Babu

author reviewer
#74 lore raw

PATCH RESEND v4 14/15 fs/resctrl: Allow user space to write kmode_cpus/kmode_cpus_list

In reply to Babu Moger

kmode_cpus and kmode_cpus_list expose the CPU scope for the rdtgroup bound to the active kernel-mode policy. They are currently read-only, so changing the scope requires rebinding through info/kernel_mode, which reprograms the whole binding instead of only the CPUs whose state changes.

Make kmode_cpus and kmode_cpus_list writable. Parse writes as a bitmap or CPU range list. Reject pseudo-locked and pseudo-lock-setup groups, writes to a group other than resctrl_kcfg.k_rdtgrp (including stale file descriptors left open across an info/kernel_mode change), malformed input, and masks that name offline CPUs.

Update the bound group's kmode_cpu_mask and reprogram hardware
incrementally: disable kernel-mode association on CPUs in the old mask but not the new mask, and enable it on CPUs in the new mask but not the old mask.

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

---
v4: Empty masks are now allowed and updated masks are in rdtgroup->kmode_cpu_mask.
Updated the changelog.

v3: New patch to add "kmode_cpus" and "kmode_cpus_list" to support
kernel_modes.

---
 Documentation/filesystems/resctrl.rst |  30 +++++
 fs/resctrl/rdtgroup.c                 | 151 +++++++++++++++++++++++++-
 2 files changed, 179 insertions(+), 2 deletions(-)
Documentation/filesystems/resctrl.rst +30 -0
index 5a13814d1325..4a2bdd74d4aa 100644
@@ -676,6 +676,36 @@ All groups contain the following files:
 "cpus_list":
 	Just like "cpus", only using ranges of CPUs instead of bitmasks.
 
+"kmode_cpus":
+	Visible only on the rdtgroup currently bound to the active kernel
+	mode (see "info/kernel_mode"); hidden on every other rdtgroup,
+	including when "inherit_ctrl_and_mon" is active.
+
+	Bitmask of the logical CPUs scoped for this group's kernel-mode
+	binding.  At bind time through info/kernel_mode, every currently
+	online CPU is included in the scope.  CPUs that come online later
+	are automatically added to the scope and programmed with the binding.
+
+	Writing a mask reprograms the binding incrementally: it enables on
+	the CPUs newly added by the write and disables on the CPUs dropped
+	from the previous mask.  An empty mask disables the binding on all
+	CPUs in the current scope.  The mask must contain only online CPUs;
+	masks naming offline CPUs are rejected.
+	Errors are reported in "info/last_cmd_status".  Example::
+
+	  # mkdir ctrl1
+	  # echo "global_assign_ctrl_inherit_mon_per_cpu:group=ctrl1//" \
+	        > info/kernel_mode
+	  # echo 0-3 > ctrl1/kmode_cpus_list
+	  # cat ctrl1/kmode_cpus
+	  f
+	  # cat ctrl1/kmode_cpus_list
+	  0-3
+
+"kmode_cpus_list":
+	Just like "kmode_cpus", only using ranges of CPUs instead of bitmasks.
+	Writable with the same semantics and restrictions as "kmode_cpus".
+
 
 When control is enabled all CTRL_MON groups will also contain:
 
fs/resctrl/rdtgroup.c +149 -2

170 lines not on this page · raw message

Signature · 1 line
2.43.0
#75 lore raw

Re: [RESEND PATCH v4 14/15] fs/resctrl: Allow user space to write kmode_cpus/kmode_cpus_list

Quoted 237 lines · Babu Moger

kmode_cpus and kmode_cpus_list expose the CPU scope for the rdtgroup bound to the active kernel-mode policy. They are currently read-only, so changing the scope requires rebinding through info/kernel_mode, which reprograms the whole binding instead of only the CPUs whose state changes.

Make kmode_cpus and kmode_cpus_list writable. Parse writes as a bitmap or CPU range list. Reject pseudo-locked and pseudo-lock-setup groups, writes to a group other than resctrl_kcfg.k_rdtgrp (including stale file descriptors left open across an info/kernel_mode change), malformed input, and masks that name offline CPUs.

Update the bound group's kmode_cpu_mask and reprogram hardware
incrementally: disable kernel-mode association on CPUs in the old mask but not the new mask, and enable it on CPUs in the new mask but not the old mask.

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

---
v4: Empty masks are now allowed and updated masks are in rdtgroup->kmode_cpu_mask.
Updated the changelog.

v3: New patch to add "kmode_cpus" and "kmode_cpus_list" to support
kernel_modes.

---
  Documentation/filesystems/resctrl.rst |  30 +++++
  fs/resctrl/rdtgroup.c                 | 151 +++++++++++++++++++++++++-
  2 files changed, 179 insertions(+), 2 deletions(-)
Documentation/filesystems/resctrl.rst +30 -0
index 5a13814d1325..4a2bdd74d4aa 100644
@@ -676,6 +676,36 @@ All groups contain the following files:
  "cpus_list":
  	Just like "cpus", only using ranges of CPUs instead of bitmasks.
 
+"kmode_cpus":
+	Visible only on the rdtgroup currently bound to the active kernel
+	mode (see "info/kernel_mode"); hidden on every other rdtgroup,
+	including when "inherit_ctrl_and_mon" is active.
+
+	Bitmask of the logical CPUs scoped for this group's kernel-mode
+	binding.  At bind time through info/kernel_mode, every currently
+	online CPU is included in the scope.  CPUs that come online later
+	are automatically added to the scope and programmed with the binding.
+
+	Writing a mask reprograms the binding incrementally: it enables on
+	the CPUs newly added by the write and disables on the CPUs dropped
+	from the previous mask.  An empty mask disables the binding on all
+	CPUs in the current scope.  The mask must contain only online CPUs;
+	masks naming offline CPUs are rejected.
+	Errors are reported in "info/last_cmd_status".  Example::
+
+	  # mkdir ctrl1
+	  # echo "global_assign_ctrl_inherit_mon_per_cpu:group=ctrl1//" \
+	        > info/kernel_mode
+	  # echo 0-3 > ctrl1/kmode_cpus_list
+	  # cat ctrl1/kmode_cpus
+	  f
+	  # cat ctrl1/kmode_cpus_list
+	  0-3
+
+"kmode_cpus_list":
+	Just like "kmode_cpus", only using ranges of CPUs instead of bitmasks.
+	Writable with the same semantics and restrictions as "kmode_cpus".
+
 
  When control is enabled all CTRL_MON groups will also contain:
 
fs/resctrl/rdtgroup.c +147 -1
index 7b06c3b3f00e..8ecd107368b3 100644
@@ -423,6 +423,151 @@ static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of,
  	return ret;
  }
 
+/**
+ * kmode_cpus_write() - Update @rdtgrp's kmode_cpu_mask from @newmask
+ * @rdtgrp:	Resctrl group whose kmode_cpu_mask is being updated.
+ * @kmode:	Kernel-mode policy currently active on @rdtgrp.
+ * @newmask:	Set of online CPUs scoped for @rdtgrp's kernel-mode binding.
+ * @tmpmask:	Caller-allocated scratch cpumask used to compute the
+ *		incremental enable/disable deltas; contents on entry are
+ *		ignored and on return are unspecified.
+ *
+ * Compute the difference between @rdtgrp->kmode_cpu_mask and @newmask
+ * and call resctrl_arch_configure_kmode() only on the CPUs whose enable
+ * state actually changes:
+ *
+ *   - disable on (old & ~new)
+ *   - enable on (new & ~old)
+ *
+ * Then copy @newmask into @rdtgrp->kmode_cpu_mask so subsequent
+ * show/write operations reflect the updated scope.
+ */
+static void kmode_cpus_write(struct rdtgroup *rdtgrp, enum resctrl_kernel_mode kmode,
+			     cpumask_var_t newmask, cpumask_var_t tmpmask)
+{
+	bool assign_mon = (kmode == GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU);
+	u32 closid, rmid;
+
+	closid = rdtgrp->closid;
+	rmid = rdtgrp->mon.rmid;
+
+	/* CPUs dropped from this group: old & ~newmask. */
+	cpumask_andnot(tmpmask, &rdtgrp->kmode_cpu_mask, newmask);
+	if (!cpumask_empty(tmpmask))
+		resctrl_arch_configure_kmode(tmpmask, closid, rmid, assign_mon, false);
+
+	/* CPUs newly added: newmask & ~old. */
+	cpumask_andnot(tmpmask, newmask, &rdtgrp->kmode_cpu_mask);
+	if (!cpumask_empty(tmpmask))
+		resctrl_arch_configure_kmode(tmpmask, closid, rmid, assign_mon, true);
+
+	cpumask_copy(&rdtgrp->kmode_cpu_mask, newmask);
+}
+
+/**
+ * rdtgroup_kmode_cpus_write() - Sysfs write handler for kmode_cpus[_list]
+ * @of:		kernfs open file (selects bitmap vs range-list parsing via
+ *		is_cpu_list()).
+ * @buf:	NUL-terminated input from userspace.
+ * @nbytes:	Length of @buf, returned on success.
+ * @off:	File offset (unused).
+ *
+ * Parses @buf into a cpumask and rejects:
+ *   - pseudo-locked / pseudo-lock-setup groups,
+ *   - writes when INHERIT_CTRL_AND_MON is active or to a group other than
+ *     resctrl_kcfg.k_rdtgrp (stale fds opened before an info/kernel_mode
+ *     change),
+ *   - malformed input,
+ *   - masks containing offline CPUs.
+ *
+ * Validated masks are passed to kmode_cpus_write() to update
+ * @rdtgrp->kmode_cpu_mask and reprogram hardware incrementally.
+ * Errors are reported in last_cmd_status.
+ *
+ * Return: @nbytes on success, -ENOENT if the group has been deleted,
+ * -EINVAL for pseudo-locked or pseudo-lock-setup groups, malformed input, or
+ * offline CPUs in the requested mask, -EBUSY if INHERIT_CTRL_AND_MON is active
+ * or the group is not resctrl_kcfg.k_rdtgrp, and -ENOMEM if the scratch
+ * cpumasks cannot be allocated.
+ */
+static ssize_t rdtgroup_kmode_cpus_write(struct kernfs_open_file *of,
+					 char *buf, size_t nbytes, loff_t off)
+{
+	cpumask_var_t tmpmask, newmask;
+	struct rdtgroup *rdtgrp;
+	int ret;
+
+	if (!buf)
+		return -EINVAL;
+
+	if (!zalloc_cpumask_var(&tmpmask, GFP_KERNEL))
+		return -ENOMEM;
+	if (!zalloc_cpumask_var(&newmask, GFP_KERNEL)) {
+		free_cpumask_var(tmpmask);
+		return -ENOMEM;
+	}
+
+	rdtgrp = rdtgroup_kn_lock_live(of->kn);
+	if (!rdtgrp) {
+		ret = -ENOENT;
+		goto unlock;
+	}
+
+	rdt_last_cmd_clear();
+
+	if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED ||
+	    rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
+		ret = -EINVAL;
+		rdt_last_cmd_puts("Pseudo-locked group cannot host kernel-mode binding\n");
+		goto unlock;
+	}
+
+	if (resctrl_kcfg.kmode_cur == INHERIT_CTRL_AND_MON) {
+		ret = -EBUSY;
+		rdt_last_cmd_puts("No active kernel-mode binding\n");
+		goto unlock;
+	}
+
+	/*
+	 * The visibility layer (kernfs_show()) prevents fresh open() on a
+	 * non-bound group, but file descriptors opened while the group was
+	 * bound stay valid across an info/kernel_mode change.  Reject those
+	 * stale-fd writes so they cannot corrupt the now-active binding.
+	 */
+	if (resctrl_kcfg.k_rdtgrp != rdtgrp) {
+		ret = -EBUSY;
+		rdt_last_cmd_puts("Group is not the active kernel-mode binding\n");
+		goto unlock;
+	}
+
+	if (is_cpu_list(of))
+		ret = cpulist_parse(buf, newmask);
+	else
+		ret = cpumask_parse(buf, newmask);
+
+	if (ret) {
+		rdt_last_cmd_puts("Bad CPU list/mask\n");
+		goto unlock;
+	}
+
+	/* kernel-mode binding is only programmed on online CPUs. */
+	cpumask_andnot(tmpmask, newmask, cpu_online_mask);
+	if (!cpumask_empty(tmpmask)) {
+		ret = -EINVAL;
+		rdt_last_cmd_puts("Can only assign online CPUs\n");
+		goto unlock;
+	}
+
+	kmode_cpus_write(rdtgrp, resctrl_kcfg.kmode_cur, newmask, tmpmask);
+
+unlock:
+	rdtgroup_kn_unlock(of->kn);
+	free_cpumask_var(tmpmask);
+	free_cpumask_var(newmask);
+
+	return ret ?: nbytes;
+}
+
  /*
   * Update the PGR_ASSOC MSR on all cpus in @cpu_mask,
   *
@@ -2531,15 +2676,17 @@ static struct rftype res_common_files[] = {
  	},
  	{
  		.name		= "kmode_cpus",
-		.mode		= 0444,
+		.mode		= 0644,
  		.kf_ops		= &rdtgroup_kf_single_ops,
+		.write		= rdtgroup_kmode_cpus_write,
  		.seq_show	= rdtgroup_kmode_cpus_show,
  		.fflags		= RFTYPE_BASE,

fs/resctrl/rdtgroup.c static struct rftype res_common_files[] = { · line 2692

Quoted 10 lines
fs/resctrl/rdtgroup.c +2 -1
  	},
  	{
  		.name		= "kmode_cpus_list",
-		.mode		= 0444,
+		.mode		= 0644,
  		.kf_ops		= &rdtgroup_kf_single_ops,
+		.write		= rdtgroup_kmode_cpus_write,
  		.seq_show	= rdtgroup_kmode_cpus_show,
  		.flags		= RFTYPE_FLAGS_CPUS_LIST,
  		.fflags		= RFTYPE_BASE,

Sashiko reported:

https://sashiko.dev/#/patchset/cover.1783461016.git.babu.moger%40amd.com?part=14

--- Patch [14]: [RESEND PATCH v4 14/15] fs/resctrl: Allow user space to write kmode_cpus/kmode_cpus_list --- commit 263cb432ef00bc0bc1801a5cac6bf42139e89250
Author: Babu Moger <[email protected]>
fs/resctrl: Allow user space to write kmode_cpus/kmode_cpus_list
This commit makes the kmode_cpus and kmode_cpus_list files writable. It
allows userspace to incrementally reprogram the CPU scope for the active
kernel-mode policy. Writes are parsed and validated to reject
pseudo-locked groups, incorrect groups, malformed input, and offline CPUs.

Quoted 4 lines
fs/resctrl/rdtgroup.c +0 -0
index 7b06c3b3f00e0..8ecd107368b3d 100644

[ ... ]

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+static ssize_t rdtgroup_kmode_cpus_write(struct kernfs_open_file *of,
+					 char *buf, size_t nbytes, loff_t off)
+{
+	cpumask_var_t tmpmask, newmask;
+	struct rdtgroup *rdtgrp;
+	int ret;

[ ... ]

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 520

Quoted 3 lines
fs/resctrl/rdtgroup.c +3 -0
+	if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED ||
+	    rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
+		ret = -EINVAL;

---------------------------------------------------------------------
While we reject writing to kmode_cpus for pseudo-locksetup groups, what prevents the active kernel-mode binding group from entering pseudo-locksetup mode in the first place?
------------------------------------------------------------------------

Will add a check "rdtgrp->kmode" in rdtgroup_locksetup_enter() This should avoid the following issue
---------------------------------------------------------------------

If a group bound as resctrl_kcfg.k_rdtgrp transitions via rdtgroup_mode_write() -> rdtgroup_locksetup_enter(), and rdtgroup_locksetup_enter() does not check kmode_cpu_mask or active kernel-mode bindings, it can successfully enter pseudo-locksetup mode. Later, if the user removes this group, rdtgroup_rmdir() routes to rdtgroup_ctrl_remove() instead of rdtgroup_rmdir_ctrl():

rdtgroup_rmdir() {
    ...
    if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP ||
        rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) {
        ret = rdtgroup_ctrl_remove(rdtgrp);
    } else {
        ret = rdtgroup_rmdir_ctrl(rdtgrp, tmpmask);
    }
}

Since rdtgroup_ctrl_remove() bypasses the rdtgroup_kmode_detach() call present in rdtgroup_rmdir_ctrl(), the group is deleted without detaching from resctrl_kcfg.k_rdtgrp. Can this leave resctrl_kcfg.k_rdtgrp as a dangling pointer, leading to a use-after-free regression on subsequent CPU hotplug events?

Quoted 5 lines
fs/resctrl/rdtgroup.c +5 -0
+		rdt_last_cmd_puts("Pseudo-locked group cannot host kernel-mode binding\n");
+		goto unlock;
+	}
+
+	if (resctrl_kcfg.kmode_cur == INHERIT_CTRL_AND_MON) {

[ ... ]

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 556

Quoted 4 lines
fs/resctrl/rdtgroup.c +4 -0
+	/* kernel-mode binding is only programmed on online CPUs. */
+	cpumask_andnot(tmpmask, newmask, cpu_online_mask);
+	if (!cpumask_empty(tmpmask)) {
+		ret = -EINVAL;

If resctrl_offline_cpu() does not clear offline CPUs from kmode_cpu_mask:

resctrl_offline_cpu() {
    list_for_each_entry(rdtgrp, &rdt_all_groups, rdtgroup_list) {
        if (cpumask_test_and_clear_cpu(cpu, &rdtgrp->cpu_mask)) {
            clear_childcpus(rdtgrp, cpu);
            break;
        }
    }
}

Would this regression break the read-modify-write workflow for kmode_cpus? If a CPU in the active kernel-mode mask goes offline, userspace reading kmode_cpus and rewriting it (or modifying it) would be rejected here with -EINVAL because the offline CPU was left in kmode_cpu_mask.

----------------------------------------------------------------------

Yes. This is an issue.
Need to clear the kmode_cpu_list if the cpu being offlined is part of the current kmode. Also, need to disable PLZA on the CPU that is offlined.

Will take care of this in resctrl_offline_cpu().

Thanks
Babu

maintainer
#76 lore raw

Re: [RESEND PATCH v4 14/15] fs/resctrl: Allow user space to write kmode_cpus/kmode_cpus_list

In reply to Babu Moger

Hi Babu,

Quoted 35 lines · Babu Moger

kmode_cpus and kmode_cpus_list expose the CPU scope for the rdtgroup bound to the active kernel-mode policy. They are currently read-only, so changing the scope requires rebinding through info/kernel_mode, which reprograms the whole binding instead of only the CPUs whose state changes.

Make kmode_cpus and kmode_cpus_list writable. Parse writes as a bitmap or CPU range list. Reject pseudo-locked and pseudo-lock-setup groups, writes to a group other than resctrl_kcfg.k_rdtgrp (including stale file descriptors left open across an info/kernel_mode change), malformed input, and masks that name offline CPUs.

Update the bound group's kmode_cpu_mask and reprogram hardware
incrementally: disable kernel-mode association on CPUs in the old mask but not the new mask, and enable it on CPUs in the new mask but not the old mask.

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

---
v4: Empty masks are now allowed and updated masks are in rdtgroup->kmode_cpu_mask.
Updated the changelog.

v3: New patch to add "kmode_cpus" and "kmode_cpus_list" to support
kernel_modes.

---
 Documentation/filesystems/resctrl.rst |  30 +++++
 fs/resctrl/rdtgroup.c                 | 151 +++++++++++++++++++++++++-
 2 files changed, 179 insertions(+), 2 deletions(-)
Documentation/filesystems/resctrl.rst +0 -0
index 5a13814d1325..4a2bdd74d4aa 100644

Documentation/filesystems/resctrl.rst All groups contain the following files: · line 680

Quoted 5 lines
Documentation/filesystems/resctrl.rst +2 -0
@@ -676,6 +676,36 @@ All groups contain the following files:
 "cpus_list":
 	Just like "cpus", only using ranges of CPUs instead of bitmasks.
 
+"kmode_cpus":
+	Visible only on the rdtgroup currently bound to the active kernel

"Visible" -> "Accessible"?
"on" -> "within"?

rdtgroup -> "resource group"
bound -> "assigned"

Documentation/filesystems/resctrl.rst All groups contain the following files: · line 682

Quoted 2 lines
Documentation/filesystems/resctrl.rst +2 -0
+	mode (see "info/kernel_mode"); hidden on every other rdtgroup,
+	including when "inherit_ctrl_and_mon" is active.

No need to mention that it is hidden in other groups.

Documentation/filesystems/resctrl.rst All groups contain the following files: · line 684

Quoted 2 lines
Documentation/filesystems/resctrl.rst +2 -0
+
+	Bitmask of the logical CPUs scoped for this group's kernel-mode

What does the "scoped" distinction mean?

Documentation/filesystems/resctrl.rst All groups contain the following files: · line 685

Quoted 1 line
Documentation/filesystems/resctrl.rst +1 -0
+	binding.  At bind time through info/kernel_mode, every currently

What is "bind time"? Could "bind time through" be replaced with "assigned via"? Can "assign" be used instead of "bind" throughout this text?

Documentation/filesystems/resctrl.rst All groups contain the following files: · line 687

Quoted 2 lines
Documentation/filesystems/resctrl.rst +2 -0
+	online CPU is included in the scope.  CPUs that come online later
+	are automatically added to the scope and programmed with the binding.

I do not think "scope" is the right term here.

Documentation/filesystems/resctrl.rst All groups contain the following files: · line 689

Quoted 2 lines
Documentation/filesystems/resctrl.rst +2 -0
+
+	Writing a mask reprograms the binding incrementally: it enables on

I interpret "incrementally" as the write _adds_ the new CPUs to the mask, which is not what the implementation does.

Documentation/filesystems/resctrl.rst All groups contain the following files: · line 692

Quoted 3 lines
Documentation/filesystems/resctrl.rst +3 -0
+	the CPUs newly added by the write and disables on the CPUs dropped
+	from the previous mask.  An empty mask disables the binding on all
+	CPUs in the current scope.  The mask must contain only online CPUs;

"CPUs in the current scope" what does "in the current scope" refer to?

Quoted 25 lines
Documentation/filesystems/resctrl.rst +16 -0
+	masks naming offline CPUs are rejected.
+	Errors are reported in "info/last_cmd_status".  Example::
+
+	  # mkdir ctrl1
+	  # echo "global_assign_ctrl_inherit_mon_per_cpu:group=ctrl1//" \
+	        > info/kernel_mode
+	  # echo 0-3 > ctrl1/kmode_cpus_list
+	  # cat ctrl1/kmode_cpus
+	  f
+	  # cat ctrl1/kmode_cpus_list
+	  0-3
+
+"kmode_cpus_list":
+	Just like "kmode_cpus", only using ranges of CPUs instead of bitmasks.
+	Writable with the same semantics and restrictions as "kmode_cpus".
+
 
 When control is enabled all CTRL_MON groups will also contain:
 
fs/resctrl/rdtgroup.c +0 -0
index 7b06c3b3f00e..8ecd107368b3 100644
@@ -423,6 +423,151 @@ static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of,
 	return ret;

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 433

Quoted 10 lines
fs/resctrl/rdtgroup.c +8 -0
 }
 
+/**
+ * kmode_cpus_write() - Update @rdtgrp's kmode_cpu_mask from @newmask
+ * @rdtgrp:	Resctrl group whose kmode_cpu_mask is being updated.
+ * @kmode:	Kernel-mode policy currently active on @rdtgrp.
+ * @newmask:	Set of online CPUs scoped for @rdtgrp's kernel-mode binding.
+ * @tmpmask:	Caller-allocated scratch cpumask used to compute the
+ *		incremental enable/disable deltas; contents on entry are
+ *		ignored and on return are unspecified.

ah - this is where "incremental" comes from. I think this is an implementation detail that should be invisible to user space.

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 443

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+ *
+ * Compute the difference between @rdtgrp->kmode_cpu_mask and @newmask
+ * and call resctrl_arch_configure_kmode() only on the CPUs whose enable
+ * state actually changes:
+ *
+ *   - disable on (old & ~new)
+ *   - enable on (new & ~old)
+ *
+ * Then copy @newmask into @rdtgrp->kmode_cpu_mask so subsequent
+ * show/write operations reflect the updated scope.

This can be seen from the code.

Quoted 28 lines
fs/resctrl/rdtgroup.c +28 -0
+ */
+static void kmode_cpus_write(struct rdtgroup *rdtgrp, enum resctrl_kernel_mode kmode,
+			     cpumask_var_t newmask, cpumask_var_t tmpmask)
+{
+	bool assign_mon = (kmode == GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU);
+	u32 closid, rmid;
+
+	closid = rdtgrp->closid;
+	rmid = rdtgrp->mon.rmid;
+
+	/* CPUs dropped from this group: old & ~newmask. */
+	cpumask_andnot(tmpmask, &rdtgrp->kmode_cpu_mask, newmask);
+	if (!cpumask_empty(tmpmask))
+		resctrl_arch_configure_kmode(tmpmask, closid, rmid, assign_mon, false);
+
+	/* CPUs newly added: newmask & ~old. */
+	cpumask_andnot(tmpmask, newmask, &rdtgrp->kmode_cpu_mask);
+	if (!cpumask_empty(tmpmask))
+		resctrl_arch_configure_kmode(tmpmask, closid, rmid, assign_mon, true);
+
+	cpumask_copy(&rdtgrp->kmode_cpu_mask, newmask);
+}
+
+/**
+ * rdtgroup_kmode_cpus_write() - Sysfs write handler for kmode_cpus[_list]
+ * @of:		kernfs open file (selects bitmap vs range-list parsing via
+ *		is_cpu_list()).
+ * @buf:	NUL-terminated input from userspace.

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 481

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+ * @nbytes:	Length of @buf, returned on success.
+ * @off:	File offset (unused).
+ *
+ * Parses @buf into a cpumask and rejects:
+ *   - pseudo-locked / pseudo-lock-setup groups,
+ *   - writes when INHERIT_CTRL_AND_MON is active or to a group other than
+ *     resctrl_kcfg.k_rdtgrp (stale fds opened before an info/kernel_mode
+ *     change),
+ *   - malformed input,
+ *   - masks containing offline CPUs.

This just describes the code and seems unnecessarry.

Quoted 17 lines
fs/resctrl/rdtgroup.c +17 -0
+ *
+ * Validated masks are passed to kmode_cpus_write() to update
+ * @rdtgrp->kmode_cpu_mask and reprogram hardware incrementally.
+ * Errors are reported in last_cmd_status.
+ *
+ * Return: @nbytes on success, -ENOENT if the group has been deleted,
+ * -EINVAL for pseudo-locked or pseudo-lock-setup groups, malformed input, or
+ * offline CPUs in the requested mask, -EBUSY if INHERIT_CTRL_AND_MON is active
+ * or the group is not resctrl_kcfg.k_rdtgrp, and -ENOMEM if the scratch
+ * cpumasks cannot be allocated.
+ */
+static ssize_t rdtgroup_kmode_cpus_write(struct kernfs_open_file *of,
+					 char *buf, size_t nbytes, loff_t off)
+{
+	cpumask_var_t tmpmask, newmask;
+	struct rdtgroup *rdtgrp;
+	int ret;

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 508

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+
+	if (!buf)
+		return -EINVAL;
+
+	if (!zalloc_cpumask_var(&tmpmask, GFP_KERNEL))
+		return -ENOMEM;
+	if (!zalloc_cpumask_var(&newmask, GFP_KERNEL)) {
+		free_cpumask_var(tmpmask);
+		return -ENOMEM;
+	}

Please see related recent changes to resctrl:
commit 242c0ab4d51d ("fs/resctrl: Change last_cmd_status custom during input parsing")

For comparison you can view latest
implementation of rdtgroup_cpus_write().

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 516

Quoted 8 lines
fs/resctrl/rdtgroup.c +8 -0
+
+	rdtgrp = rdtgroup_kn_lock_live(of->kn);
+	if (!rdtgrp) {
+		ret = -ENOENT;
+		goto unlock;
+	}
+
+	rdt_last_cmd_clear();

rdtgroup_kn_lock_live() now calls rdt_last_cmd_clear().

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 523

Quoted 7 lines
fs/resctrl/rdtgroup.c +7 -0
+
+	if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED ||
+	    rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
+		ret = -EINVAL;
+		rdt_last_cmd_puts("Pseudo-locked group cannot host kernel-mode binding\n");
+		goto unlock;
+	}

Similar to previous comment I believe this sprinkling of pseudo-locked mode checks can be avoided by ensuring that (a) a pseudo-locked/locksetup group cannot be assigned to a kernel mode, and (b) a group assigned to a kernel mode cannot have its mode changed.

In this case then resctrl_kmode_cfg::k_rdtgroup can never be a pseudo-locked group and the if (resctrl_kcfg.k_rdtgrp != rdtgrp) check below would be sufficient?

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 527

Quoted 4 lines
fs/resctrl/rdtgroup.c +4 -0
+
+	if (resctrl_kcfg.kmode_cur == INHERIT_CTRL_AND_MON) {
+		ret = -EBUSY;
+		rdt_last_cmd_puts("No active kernel-mode binding\n");

I do not know where this "binding" term came from and all of a sudden it is everywhere. The inconsistent constantly changing terms used in this series makes it difficult to follow.

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 532

Quoted 5 lines
fs/resctrl/rdtgroup.c +5 -0
+		goto unlock;
+	}
+
+	/*
+	 * The visibility layer (kernfs_show()) prevents fresh open() on a

Visibility layer? Another new term. After this introduction it is the only instance of this term in all kernel source.

Quoted 51 lines
fs/resctrl/rdtgroup.c +40 -1
+	 * non-bound group, but file descriptors opened while the group was
+	 * bound stay valid across an info/kernel_mode change.  Reject those
+	 * stale-fd writes so they cannot corrupt the now-active binding.
+	 */
+	if (resctrl_kcfg.k_rdtgrp != rdtgrp) {
+		ret = -EBUSY;
+		rdt_last_cmd_puts("Group is not the active kernel-mode binding\n");
+		goto unlock;
+	}
+
+	if (is_cpu_list(of))
+		ret = cpulist_parse(buf, newmask);
+	else
+		ret = cpumask_parse(buf, newmask);
+
+	if (ret) {
+		rdt_last_cmd_puts("Bad CPU list/mask\n");
+		goto unlock;
+	}
+
+	/* kernel-mode binding is only programmed on online CPUs. */
+	cpumask_andnot(tmpmask, newmask, cpu_online_mask);
+	if (!cpumask_empty(tmpmask)) {
+		ret = -EINVAL;
+		rdt_last_cmd_puts("Can only assign online CPUs\n");
+		goto unlock;
+	}
+
+	kmode_cpus_write(rdtgrp, resctrl_kcfg.kmode_cur, newmask, tmpmask);
+
+unlock:
+	rdtgroup_kn_unlock(of->kn);
+	free_cpumask_var(tmpmask);
+	free_cpumask_var(newmask);
+
+	return ret ?: nbytes;
+}
+
 /*
  * Update the PGR_ASSOC MSR on all cpus in @cpu_mask,
  *
@@ -2531,15 +2676,17 @@ static struct rftype res_common_files[] = {
 	},
 	{
 		.name		= "kmode_cpus",
-		.mode		= 0444,
+		.mode		= 0644,
 		.kf_ops		= &rdtgroup_kf_single_ops,
+		.write		= rdtgroup_kmode_cpus_write,
 		.seq_show	= rdtgroup_kmode_cpus_show,
 		.fflags		= RFTYPE_BASE,

fs/resctrl/rdtgroup.c static struct rftype res_common_files[] = { · line 2692

Quoted 10 lines
fs/resctrl/rdtgroup.c +2 -1
 	},
 	{
 		.name		= "kmode_cpus_list",
-		.mode		= 0444,
+		.mode		= 0644,
 		.kf_ops		= &rdtgroup_kf_single_ops,
+		.write		= rdtgroup_kmode_cpus_write,
 		.seq_show	= rdtgroup_kmode_cpus_show,
 		.flags		= RFTYPE_FLAGS_CPUS_LIST,
 		.fflags		= RFTYPE_BASE,

Reinette

#77 lore raw

Re: [RESEND PATCH v4 14/15] fs/resctrl: Allow user space to write kmode_cpus/kmode_cpus_list

Hi Reinette,

Quoted 41 lines · Reinette Chatre

Hi Babu,

Quoted 38 lines · Babu Moger

kmode_cpus and kmode_cpus_list expose the CPU scope for the rdtgroup bound to the active kernel-mode policy. They are currently read-only, so changing the scope requires rebinding through info/kernel_mode, which reprograms the whole binding instead of only the CPUs whose state changes.

Make kmode_cpus and kmode_cpus_list writable. Parse writes as a bitmap or CPU range list. Reject pseudo-locked and pseudo-lock-setup groups, writes to a group other than resctrl_kcfg.k_rdtgrp (including stale file descriptors left open across an info/kernel_mode change), malformed input, and masks that name offline CPUs.

Update the bound group's kmode_cpu_mask and reprogram hardware
incrementally: disable kernel-mode association on CPUs in the old mask but not the new mask, and enable it on CPUs in the new mask but not the old mask.

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

---
v4: Empty masks are now allowed and updated masks are in rdtgroup->kmode_cpu_mask.
Updated the changelog.

v3: New patch to add "kmode_cpus" and "kmode_cpus_list" to support
kernel_modes.

---
  Documentation/filesystems/resctrl.rst |  30 +++++
  fs/resctrl/rdtgroup.c                 | 151 +++++++++++++++++++++++++-
  2 files changed, 179 insertions(+), 2 deletions(-)
Documentation/filesystems/resctrl.rst +0 -0
index 5a13814d1325..4a2bdd74d4aa 100644
@@ -676,6 +676,36 @@ All groups contain the following files:
  "cpus_list":
  	Just like "cpus", only using ranges of CPUs instead of bitmasks.
 
Quoted 8 lines

Documentation/filesystems/resctrl.rst All groups contain the following files: · line 680

Quoted 2 lines
Documentation/filesystems/resctrl.rst +2 -0
+"kmode_cpus":
+	Visible only on the rdtgroup currently bound to the active kernel

"Visible" -> "Accessible"?
"on" -> "within"?

rdtgroup -> "resource group"
bound -> "assigned"

Sure.

Quoted 5 lines

Documentation/filesystems/resctrl.rst All groups contain the following files: · line 682

Quoted 3 lines
Documentation/filesystems/resctrl.rst +2 -0
+	mode (see "info/kernel_mode"); hidden on every other rdtgroup,
+	including when "inherit_ctrl_and_mon" is active.

No need to mention that it is hidden in other groups.

ok

Quoted 5 lines

Documentation/filesystems/resctrl.rst All groups contain the following files: · line 684

Quoted 3 lines
Documentation/filesystems/resctrl.rst +2 -0
+
+	Bitmask of the logical CPUs scoped for this group's kernel-mode

What does the "scoped" distinction mean?

"assigned"

Quoted 5 lines

Documentation/filesystems/resctrl.rst All groups contain the following files: · line 685

Quoted 2 lines
Documentation/filesystems/resctrl.rst +1 -0
+	binding.  At bind time through info/kernel_mode, every currently

What is "bind time"? Could "bind time through" be replaced with "assigned via"? Can "assign" be used instead of "bind" throughout this text?

Sure.

Quoted 5 lines

Documentation/filesystems/resctrl.rst All groups contain the following files: · line 687

Quoted 3 lines
Documentation/filesystems/resctrl.rst +2 -0
+	online CPU is included in the scope.  CPUs that come online later
+	are automatically added to the scope and programmed with the binding.

I do not think "scope" is the right term here.

ack

Quoted 6 lines

Documentation/filesystems/resctrl.rst All groups contain the following files: · line 689

Quoted 3 lines
Documentation/filesystems/resctrl.rst +2 -0
+
+	Writing a mask reprograms the binding incrementally: it enables on

I interpret "incrementally" as the write _adds_ the new CPUs to the mask, which is not what the implementation does.

Will change it.

Quoted 6 lines

Documentation/filesystems/resctrl.rst All groups contain the following files: · line 692

Quoted 4 lines
Documentation/filesystems/resctrl.rst +3 -0
+	the CPUs newly added by the write and disables on the CPUs dropped
+	from the previous mask.  An empty mask disables the binding on all
+	CPUs in the current scope.  The mask must contain only online CPUs;

"CPUs in the current scope" what does "in the current scope" refer to?

Will change it to "assigned"

Quoted 28 lines
Quoted 28 lines
Documentation/filesystems/resctrl.rst +16 -0
+	masks naming offline CPUs are rejected.
+	Errors are reported in "info/last_cmd_status".  Example::
+
+	  # mkdir ctrl1
+	  # echo "global_assign_ctrl_inherit_mon_per_cpu:group=ctrl1//" \
+	        > info/kernel_mode
+	  # echo 0-3 > ctrl1/kmode_cpus_list
+	  # cat ctrl1/kmode_cpus
+	  f
+	  # cat ctrl1/kmode_cpus_list
+	  0-3
+
+"kmode_cpus_list":
+	Just like "kmode_cpus", only using ranges of CPUs instead of bitmasks.
+	Writable with the same semantics and restrictions as "kmode_cpus".
+
 
  When control is enabled all CTRL_MON groups will also contain:
 
fs/resctrl/rdtgroup.c +0 -0
index 7b06c3b3f00e..8ecd107368b3 100644
@@ -423,6 +423,151 @@ static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of,
  	return ret;
  }
 
Quoted 11 lines

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 433

Quoted 8 lines
fs/resctrl/rdtgroup.c +8 -0
+/**
+ * kmode_cpus_write() - Update @rdtgrp's kmode_cpu_mask from @newmask
+ * @rdtgrp:	Resctrl group whose kmode_cpu_mask is being updated.
+ * @kmode:	Kernel-mode policy currently active on @rdtgrp.
+ * @newmask:	Set of online CPUs scoped for @rdtgrp's kernel-mode binding.
+ * @tmpmask:	Caller-allocated scratch cpumask used to compute the
+ *		incremental enable/disable deltas; contents on entry are
+ *		ignored and on return are unspecified.

ah - this is where "incremental" comes from. I think this is an implementation detail that should be invisible to user space.

Ok. Will change.

Quoted 12 lines

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 443

Quoted 11 lines
fs/resctrl/rdtgroup.c +10 -0
+ *
+ * Compute the difference between @rdtgrp->kmode_cpu_mask and @newmask
+ * and call resctrl_arch_configure_kmode() only on the CPUs whose enable
+ * state actually changes:
+ *
+ *   - disable on (old & ~new)
+ *   - enable on (new & ~old)
+ *
+ * Then copy @newmask into @rdtgrp->kmode_cpu_mask so subsequent
+ * show/write operations reflect the updated scope.
Quoted 1 line

This can be seen from the code.

ack.

Quoted 33 lines
Quoted 33 lines
fs/resctrl/rdtgroup.c +32 -0
+ */
+static void kmode_cpus_write(struct rdtgroup *rdtgrp, enum resctrl_kernel_mode kmode,
+			     cpumask_var_t newmask, cpumask_var_t tmpmask)
+{
+	bool assign_mon = (kmode == GLOBAL_ASSIGN_CTRL_ASSIGN_MON_PER_CPU);
+	u32 closid, rmid;
+
+	closid = rdtgrp->closid;
+	rmid = rdtgrp->mon.rmid;
+
+	/* CPUs dropped from this group: old & ~newmask. */
+	cpumask_andnot(tmpmask, &rdtgrp->kmode_cpu_mask, newmask);
+	if (!cpumask_empty(tmpmask))
+		resctrl_arch_configure_kmode(tmpmask, closid, rmid, assign_mon, false);
+
+	/* CPUs newly added: newmask & ~old. */
+	cpumask_andnot(tmpmask, newmask, &rdtgrp->kmode_cpu_mask);
+	if (!cpumask_empty(tmpmask))
+		resctrl_arch_configure_kmode(tmpmask, closid, rmid, assign_mon, true);
+
+	cpumask_copy(&rdtgrp->kmode_cpu_mask, newmask);
+}
+
+/**
+ * rdtgroup_kmode_cpus_write() - Sysfs write handler for kmode_cpus[_list]
+ * @of:		kernfs open file (selects bitmap vs range-list parsing via
+ *		is_cpu_list()).
+ * @buf:	NUL-terminated input from userspace.
+ * @nbytes:	Length of @buf, returned on success.
+ * @off:	File offset (unused).
+ *
+ * Parses @buf into a cpumask and rejects:
Quoted 8 lines

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 481

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+ *   - pseudo-locked / pseudo-lock-setup groups,
+ *   - writes when INHERIT_CTRL_AND_MON is active or to a group other than
+ *     resctrl_kcfg.k_rdtgrp (stale fds opened before an info/kernel_mode
+ *     change),
+ *   - malformed input,
+ *   - masks containing offline CPUs.

This just describes the code and seems unnecessarry.

ok. will remove.

Quoted 33 lines
Quoted 19 lines
fs/resctrl/rdtgroup.c +17 -0
+ *
+ * Validated masks are passed to kmode_cpus_write() to update
+ * @rdtgrp->kmode_cpu_mask and reprogram hardware incrementally.
+ * Errors are reported in last_cmd_status.
+ *
+ * Return: @nbytes on success, -ENOENT if the group has been deleted,
+ * -EINVAL for pseudo-locked or pseudo-lock-setup groups, malformed input, or
+ * offline CPUs in the requested mask, -EBUSY if INHERIT_CTRL_AND_MON is active
+ * or the group is not resctrl_kcfg.k_rdtgrp, and -ENOMEM if the scratch
+ * cpumasks cannot be allocated.
+ */
+static ssize_t rdtgroup_kmode_cpus_write(struct kernfs_open_file *of,
+					 char *buf, size_t nbytes, loff_t off)
+{
+	cpumask_var_t tmpmask, newmask;
+	struct rdtgroup *rdtgrp;
+	int ret;

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 508

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+
+	if (!buf)
+		return -EINVAL;
+
+	if (!zalloc_cpumask_var(&tmpmask, GFP_KERNEL))
+		return -ENOMEM;
+	if (!zalloc_cpumask_var(&newmask, GFP_KERNEL)) {
+		free_cpumask_var(tmpmask);
+		return -ENOMEM;
+	}

Please see related recent changes to resctrl:
commit 242c0ab4d51d ("fs/resctrl: Change last_cmd_status custom during input parsing")

Quoted 2 lines

For comparison you can view latest
implementation of rdtgroup_cpus_write().

Ok. Will look into it.

Quoted 11 lines

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 516

Quoted 9 lines
fs/resctrl/rdtgroup.c +8 -0
+
+	rdtgrp = rdtgroup_kn_lock_live(of->kn);
+	if (!rdtgrp) {
+		ret = -ENOENT;
+		goto unlock;
+	}
+
+	rdt_last_cmd_clear();

rdtgroup_kn_lock_live() now calls rdt_last_cmd_clear().

Yes. Will update.

Quoted 13 lines

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 523

Quoted 8 lines
fs/resctrl/rdtgroup.c +7 -0
+
+	if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED ||
+	    rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
+		ret = -EINVAL;
+		rdt_last_cmd_puts("Pseudo-locked group cannot host kernel-mode binding\n");
+		goto unlock;
+	}

Similar to previous comment I believe this sprinkling of pseudo-locked mode checks can be avoided by ensuring that (a) a pseudo-locked/locksetup group cannot be assigned to a kernel mode, and (b) a group assigned to a kernel mode cannot have its mode changed.

ack.

Quoted 3 lines

In this case then resctrl_kmode_cfg::k_rdtgroup can never be a pseudo-locked group and the if (resctrl_kcfg.k_rdtgrp != rdtgrp) check below would be sufficient?

Yes.

Quoted 9 lines

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 527

Quoted 5 lines
fs/resctrl/rdtgroup.c +4 -0
+
+	if (resctrl_kcfg.kmode_cur == INHERIT_CTRL_AND_MON) {
+		ret = -EBUSY;
+		rdt_last_cmd_puts("No active kernel-mode binding\n");

I do not know where this "binding" term came from and all of a sudden it is everywhere. The inconsistent constantly changing terms used in this series makes it difficult to follow.

Yes. Will change it to "assigned"

Quoted 9 lines

fs/resctrl/rdtgroup.c static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, · line 532

Quoted 6 lines
fs/resctrl/rdtgroup.c +5 -0
+		goto unlock;
+	}
+
+	/*
+	 * The visibility layer (kernfs_show()) prevents fresh open() on a

Visibility layer? Another new term. After this introduction it is the only instance of this term in all kernel source.

Will remove this. Let me rewrite the comment.

Thanks
Babu

author reviewer
#78 lore raw

PATCH RESEND v4 15/15 fs/resctrl: Add documentation on kernel_mode with example

In reply to Babu Moger

The kernel-mode resctrl interface now includes multiple related controls:
info/kernel_mode selects the active kernel-mode policy and bound rdtgroup, while kmode_cpus and kmode_cpus_list adjust the CPU scope for that binding.

The individual file descriptions document the formats and error cases, but there is no end-to-end example showing how user space should discover the supported policies, bind kernel-mode allocation or monitoring to a group, adjust the CPU scope, and return to the default inherit mode.

Add an "Examples on working with kernel_mode" section to Documentation/filesystems/resctrl.rst.

---
v4: New patch. Added examples in the documentation.

---
 Documentation/filesystems/resctrl.rst | 84 +++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)
Documentation/filesystems/resctrl.rst +84 -0
index 4a2bdd74d4aa..e9f7048a62e2 100644
@@ -1891,6 +1891,90 @@ View the llc occupancy snapshot::
   11234000
 
 
+Examples on working with kernel_mode
+====================================
+
+The resctrl file, ``info/kernel_mode``, holds the global policy for
+resource allocation and monitoring of kernel work and the resource group
+(when applicable) associated with the policy. The bound group's
+``kmode_cpus`` and ``kmode_cpus_list`` files adjust the CPU scope for that
+binding when a global-assign policy is active.
+
+a. Check the kernel-mode policies supported by the platform.
+::
+
+  # mount -t resctrl resctrl /sys/fs/resctrl/
+
+  # cat /sys/fs/resctrl/info/kernel_mode
+  [inherit_ctrl_and_mon]
+  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
+  global_assign_ctrl_assign_mon_per_cpu:group=uninitialized
+
+The "inherit_ctrl_and_mon" policy is active. Kernel work inherits the
+resource allocation and monitoring of the current user-space task.
+
+b. Create a CTRL_MON group and bind kernel-mode allocation to it.
+::
+
+  # mkdir /sys/fs/resctrl/ctrl1
+  # echo "global_assign_ctrl_inherit_mon_per_cpu:group=ctrl1//" > \
+        /sys/fs/resctrl/info/kernel_mode
+
+  # cat /sys/fs/resctrl/info/kernel_mode
+  inherit_ctrl_and_mon
+  [global_assign_ctrl_inherit_mon_per_cpu:group=ctrl1//]
+  global_assign_ctrl_assign_mon_per_cpu:group=uninitialized
+
+The "global_assign_ctrl_inherit_mon_per_cpu" policy globally assigns resource
+allocation for kernel work; monitoring is inherited from the user task.
+The group path format is "<ctrl>/<mon>/". A control group has no monitor
+group component, so it is written as "ctrl1//". When a global-assign policy is
+selected, the bound group's "kmode_cpus" and "kmode_cpus_list" files become
+visible.
+
+c. Restrict the kernel-mode binding to CPUs 0-3.
+::
+
+  # echo 0-3 > /sys/fs/resctrl/ctrl1/kmode_cpus_list
+  # cat /sys/fs/resctrl/ctrl1/kmode_cpus
+  f
+  # cat /sys/fs/resctrl/ctrl1/kmode_cpus_list
+  0-3
+
+The write updates the CPU scope incrementally. CPUs added to the mask have the
+kernel-mode association enabled, and CPUs removed from the mask have it
+disabled. The mask must not name offline CPUs.
+
+d. Bind kernel-mode allocation and monitoring to a monitor group.
+::
+
+  # mkdir /sys/fs/resctrl/ctrl1/mon_groups/mon1
+  # echo "global_assign_ctrl_assign_mon_per_cpu:group=ctrl1/mon1/" > \
+        /sys/fs/resctrl/info/kernel_mode
+
+  # cat /sys/fs/resctrl/info/kernel_mode
+  inherit_ctrl_and_mon
+  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
+  [global_assign_ctrl_assign_mon_per_cpu:group=ctrl1/mon1/]
+
+The "global_assign_ctrl_assign_mon_per_cpu" policy assigns a dedicated
+resource allocation and monitoring for kernel work.  Rebinding through
+info/kernel_mode resets the CPU scope to all currently online CPUs, and
+the "kmode_cpus" and "kmode_cpus_list" files move from ctrl1 to mon1.
+
+e. Return to the default inherit mode.
+::
+
+  # echo "inherit_ctrl_and_mon" > /sys/fs/resctrl/info/kernel_mode
+  # cat /sys/fs/resctrl/info/kernel_mode
+  [inherit_ctrl_and_mon]
+  global_assign_ctrl_inherit_mon_per_cpu:group=uninitialized
+  global_assign_ctrl_assign_mon_per_cpu:group=uninitialized
+
+Switching back to "inherit_ctrl_and_mon" clears the active kernel-mode
+binding. The "kmode_cpus" and "kmode_cpus_list" files are hidden again because
+no rdtgroup owns kernel-mode.
+
 Examples on working with mbm_assign_mode
 ========================================
 
Signature · 1 line
2.43.0