Skip to contentSkip to conversation

x86/resctrl: Support L3 Smart Data Cache Injection Allocation Enforcement (SDCIAE)

PATCH Superseded Babu Moger 4 participants 30 messages Jun 11, 2025 – Jun 20, 2025

Subsystems (3)

v6 of 12 Superseded Latest is v12 →

lore
Share & tools
lore

Babu Moger

author reviewer
#0 lore raw

v6 cover x86/resctrl: Support L3 Smart Data Cache Injection Allocation Enforcement (SDCIAE)

This series adds the support for L3 Smart Data Cache Injection Allocation Enforcement (SDCIAE) to resctrl infrastructure. It is refered to as "io_alloc" in resctrl subsystem.

Upcoming AMD hardware implements Smart Data Cache Injection (SDCI). Smart Data Cache Injection (SDCI) is a mechanism that enables direct insertion of data from I/O devices into the L3 cache. By directly caching data from I/O devices rather than first storing the I/O data in DRAM, SDCI reduces demands on DRAM bandwidth and reduces latency to the processor consuming the I/O data.

The SDCIAE (SDCI Allocation Enforcement) PQE feature allows system software to control the portion of the L3 cache used for SDCI devices.

When enabled, SDCIAE forces all SDCI lines to be placed into the L3 cache partitions identified by the highest-supported L3_MASK_n register, where n is the maximum supported CLOSID.

The feature details are documented in the APM listed below [1].
[1] AMD64 Architecture Programmer's Manual Volume 2: System Programming Publication # 24593 Revision 3.41 section 19.4.7 L3 Smart Data Cache Injection Allocation Enforcement (SDCIAE)

The feature requires linux support of TPH (TLP Processing Hints). The support is available in linux kernel after the commit 48d0fd2b903e3 ("PCI/TPH: Add TPH documentation")

The patches are based on top of commit
ae3e6a17ca7aa8 (tip/master) Merge branch into tip/master: 'sched/core'

# Linux Implementation

Feature adds following interface files when the resctrl "io_alloc" feature is supported on L3 resource:

/sys/fs/resctrl/info/L3/io_alloc: Report the feature status. Enable/disable the
feature by writing to the interface.

/sys/fs/resctrl/info/L3/io_alloc_cbm: List the Capacity Bit Masks (CBMs) available
for I/O devices when io_alloc feature is enabled. Configure the CBM by writing to the interface.

When CDP is enabled, these files will be created both in L3CODE and L3DATA.

# Examples:

a. Check if io_alloc feature is available
#mount -t resctrl resctrl /sys/fs/resctrl/

# cat /sys/fs/resctrl/info/L3/io_alloc
disabled

b. Enable the io_alloc feature.

	# echo 1 > /sys/fs/resctrl/info/L3/io_alloc 
	# cat /sys/fs/resctrl/info/L3/io_alloc
	enabled

c. Check the CBM values for the io_alloc feature.

	# cat /sys/fs/resctrl/info/L3/io_alloc_cbm 
	0=ffff;1=ffff

d. Change the CBM value for the domain 1:

	# echo 1=FF > /sys/fs/resctrl/info/L3/io_alloc_cbm
	# cat /sys/fs/resctrl/info/L3/io_alloc_cbm 
	0=ffff;1=00ff

d. Disable io_alloc feature and exit.

	# echo 0 > /sys/fs/resctrl/info/L3/io_alloc 
	# cat /sys/fs/resctrl/info/L3/io_alloc
	disabled

#umount /sys/fs/resctrl/

---
v6:
Sorry if you see this series duplicate. Messed up the emails [email protected] and [email protected].

Sent v5 by mistake before completing all testing.
Most of the changes are in resctrl.rst user doc.
The resource name is no longer printed in io_alloc_cbms. Updated the related documentation accordingly.
Resolved conflicts in cpufeatures.h
Added lockdep_assert_cpus_held() in _resctrl_sdciae_enable() to protect r->ctrl_domains.

Added more comments in include/linux/resctrl.h.

Updated "io_alloc_cbm" details in user doc resctrl.rst. Resource name is not printed in CBM now.

Updated subjects to fs/resctrl: where applicable.

v5:
Patches are created on top of recent resctrl FS/ARCH code restructure. The files monitor.c/rdtgroup.c have been split between FS and ARCH directories. Resolved the conflict due to the merge.

Updated bit_usage to reflect the io_alloc CBM as discussed in the thread:
https://lore.kernel.org/lkml/[email protected]/
Modified rdt_bit_usage_show() to read io_alloc_cbm in hw_shareable, ensuring that bit_usage accurately represents the CBMs.

Moved prototypes of resctrl_arch_io_alloc_enable() and resctrl_arch_get_io_alloc_enabled() to include/linux/resctrl.h.

Used rdt_kn_name to get the rdtgroup name instead of accesssing it directly while printing group name used by the io_alloc_closid.

Updated show_doms() to print the resource if only it is valid. Pass NULL while printing io_alloc CBM.

Changed the code to access io_alloc CBMs via either L3CODE or L3DATA resources.

v4: The "io_alloc" interface will report "enabled/disabled/not supported"
instead of 0 or 1..

Updated resctrl_io_alloc_closid_get() to verify the max closid availability using closids_supported().

Updated the documentation for "shareable_bits" and "bit_usage".

NOTE: io_alloc is about specific CLOS. rdt_bit_usage_show() is not designed handle bit_usage for specific CLOS. Its about overall system. So, we cannot really tell the user which CLOS is shared across both hardware and software. This is something we need to discuss.

Introduced io_alloc_init() to initialize fflags.

Printed the group name when io_alloc enablement fails to help user.

Added rdtgroup_mutex before rdt_last_cmd_puts() in resctrl_io_alloc_cbm_show(). Returned -ENODEV when resource type is CDP_DATA.

Kept the resource name while printing the CBM (L3:0=ffff) that way we dont have to change show_doms() just for this feature and it is consistant across all the schemata display.

Added new patch to call parse_cbm() directly to avoid code duplication.

Checked all the series(v1-v3) again to verify if I missed any comment.

v3: Rewrote commit log for the last 3 patches. Changed the text to bit
more generic than the AMD specific feature. Added AMD feature specifics in the end.

Renamed the rdt_get_sdciae_alloc_cfg() to rdt_set_io_alloc_capable(). Renamed the _resctrl_io_alloc_enable() to _resctrl_sdciae_enable() as it is arch specific.

Changed the return to void in _resctrl_sdciae_enable() instead of int.

The number of CLOSIDs is determined based on the minimum supported across all resources (in closid_init). It needs to match the max supported on the resource. Added the check to verify if MAX CLOSID availability on the system.

Added CDP check to make sure io_alloc is configured in CDP_CODE. Highest CLOSID corresponds to CDP_CODE.

Added resctrl_io_alloc_closid_free() to free the io_alloc CLOSID.

Added errors in few cases when CLOSID allocation fails.
Fixes splat reported when info/L3/bit_usage is accesed when io_alloc is enabled.
https://lore.kernel.org/lkml/SJ1PR11MB60837B532254E7B23BC27E84FC052@SJ1PR11MB6083.namprd11.prod.outlook.com/

v2: Added dependancy on X86_FEATURE_CAT_L3
Removed the "" in CPU feature definition.

Changed sdciae_capable to io_alloc_capable to make it as generic feature. Moved io_alloc_capable field in struct resctrl_cache.

Changed the name of few arch functions similar to ABMC series. resctrl_arch_get_io_alloc_enabled() resctrl_arch_io_alloc_enable()

Renamed the feature to "io_alloc".
Added generic texts for the feature in commit log and resctrl.rst doc. Added resctrl_io_alloc_init_cat() to initialize io_alloc to default values when enabled.
Fixed io_alloc interface to show only on L3 resource.
Added the locks while processing io_alloc CBMs.

Previous versions:
v5: https://lore.kernel.org/lkml/[email protected]/
v4: https://lore.kernel.org/lkml/[email protected]/
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 (8):
x86/cpufeatures: Add support for L3 Smart Data Cache Injection
Allocation Enforcement
x86/resctrl: Add SDCIAE feature in the command line options x86/resctrl: Detect io_alloc feature
x86/resctrl: Implement "io_alloc" enable/disable handlers fs/resctrl: Add user interface to enable/disable io_alloc feature fs/resctrl: Introduce interface to display io_alloc CBMs fs/resctrl: Modify rdt_parse_data to pass mode and CLOSID fs/resctrl: Introduce interface to modify io_alloc Capacity Bit Masks

 .../admin-guide/kernel-parameters.txt         |   2 +-
 Documentation/filesystems/resctrl.rst         |  60 +++
 arch/x86/include/asm/cpufeatures.h            |   1 +
 arch/x86/include/asm/msr-index.h              |   1 +
 arch/x86/kernel/cpu/cpuid-deps.c              |   1 +
 arch/x86/kernel/cpu/resctrl/core.c            |   9 +
 arch/x86/kernel/cpu/resctrl/internal.h        |   5 +
 arch/x86/kernel/cpu/resctrl/rdtgroup.c        |  40 ++
 arch/x86/kernel/cpu/scattered.c               |   1 +
 fs/resctrl/ctrlmondata.c                      |  41 +-
 fs/resctrl/internal.h                         |  10 +
 fs/resctrl/rdtgroup.c                         | 352 +++++++++++++++++-
 include/linux/resctrl.h                       |  24 ++
 13 files changed, 523 insertions(+), 24 deletions(-)
Signature · 1 line
2.34.1
author reviewer
#1 lore raw

PATCH v6 1/8 x86/cpufeatures: Add support for L3 Smart Data Cache Injection Allocation Enforcement

Smart Data Cache Injection (SDCI) is a mechanism that enables direct insertion of data from I/O devices into the L3 cache. By directly caching data from I/O devices rather than first storing the I/O data in DRAM, SDCI reduces demands on DRAM bandwidth and reduces latency to the processor consuming the I/O data.

The SDCIAE (SDCI Allocation Enforcement) PQE feature allows system software to control the portion of the L3 cache used for SDCI.

When enabled, SDCIAE forces all SDCI lines to be placed into the L3 cache partitions identified by the highest-supported L3_MASK_n register, where n is the maximum supported CLOSID.

Add CPUID feature bit that can be used to configure SDCIAE.

The feature details are documented in APM listed below [1].
[1] AMD64 Architecture Programmer's Manual Volume 2: System Programming Publication # 24593 Revision 3.41 section 19.4.7 L3 Smart Data Cache Injection Allocation Enforcement (SDCIAE)

---
v6: Resolved conflicts in cpufeatures.h.

v5: No changes.

v4: Resolved a minor conflict in cpufeatures.h.

v3: No changes.

v2: Added dependancy on X86_FEATURE_CAT_L3
Removed the "" in CPU feature definition.
Minor text changes.

---
 arch/x86/include/asm/cpufeatures.h | 1 +
 arch/x86/kernel/cpu/cpuid-deps.c   | 1 +
 arch/x86/kernel/cpu/scattered.c    | 1 +
 3 files changed, 3 insertions(+)
arch/x86/include/asm/cpufeatures.h +1 -0
index ee176236c2be..1e3d4d8a45ec 100644
@@ -487,6 +487,7 @@
 #define X86_FEATURE_PREFER_YMM		(21*32+ 8) /* Avoid ZMM registers due to downclocking */
 #define X86_FEATURE_APX			(21*32+ 9) /* Advanced Performance Extensions */
 #define X86_FEATURE_INDIRECT_THUNK_ITS	(21*32+10) /* Use thunk for indirect branches in lower half of cacheline */
+#define X86_FEATURE_SDCIAE		(21*32+11) /* L3 Smart Data Cache Injection Allocation Enforcement */
 
 /*
  * BUG word(s)
arch/x86/kernel/cpu/cpuid-deps.c +1 -0
index 46efcbd6afa4..87e78586395b 100644
@@ -72,6 +72,7 @@ static const struct cpuid_dep cpuid_deps[] = {
 	{ X86_FEATURE_CQM_MBM_LOCAL,		X86_FEATURE_CQM_LLC   },
 	{ X86_FEATURE_BMEC,			X86_FEATURE_CQM_MBM_TOTAL   },
 	{ X86_FEATURE_BMEC,			X86_FEATURE_CQM_MBM_LOCAL   },
+	{ X86_FEATURE_SDCIAE,			X86_FEATURE_CAT_L3    },
 	{ X86_FEATURE_AVX512_BF16,		X86_FEATURE_AVX512VL  },
 	{ X86_FEATURE_AVX512_FP16,		X86_FEATURE_AVX512BW  },
 	{ X86_FEATURE_ENQCMD,			X86_FEATURE_XSAVES    },
arch/x86/kernel/cpu/scattered.c +1 -0
index dbf6d71bdf18..3d1f4d718a84 100644
@@ -50,6 +50,7 @@ static const struct cpuid_bit cpuid_bits[] = {
 	{ X86_FEATURE_MBA,			CPUID_EBX,  6, 0x80000008, 0 },
 	{ X86_FEATURE_SMBA,			CPUID_EBX,  2, 0x80000020, 0 },
 	{ X86_FEATURE_BMEC,			CPUID_EBX,  3, 0x80000020, 0 },
+	{ X86_FEATURE_SDCIAE,			CPUID_EBX,  6, 0x80000020, 0 },
 	{ X86_FEATURE_AMD_WORKLOAD_CLASS,	CPUID_EAX, 22, 0x80000021, 0 },
 	{ X86_FEATURE_PERFMON_V2,		CPUID_EAX,  0, 0x80000022, 0 },
 	{ X86_FEATURE_AMD_LBR_V2,		CPUID_EAX,  1, 0x80000022, 0 },
Signature · 1 line
2.34.1
author reviewer
#2 lore raw

PATCH v6 2/8 x86/resctrl: Add SDCIAE feature in the command line options

In reply to Babu Moger

Add the command line options to enable or disable the new resctrl feature L3 Smart Data Cache Injection Allocation Enforcement (SDCIAE).

---
v6: No changes.

v5: No changes.

v4: No changes.

v3: No changes.

v2: No changes.

---
 Documentation/admin-guide/kernel-parameters.txt | 2 +-
 arch/x86/kernel/cpu/resctrl/core.c              | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)
Documentation/admin-guide/kernel-parameters.txt +1 -1
index f1f2c0874da9..95d89f881e10 100644
@@ -6066,7 +6066,7 @@
 	rdt=		[HW,X86,RDT]
 			Turn on/off individual RDT features. List is:
 			cmt, mbmtotal, mbmlocal, l3cat, l3cdp, l2cat, l2cdp,
-			mba, smba, bmec.
+			mba, smba, bmec, sdciae.
 			E.g. to turn on cmt and turn off mba use:
 				rdt=cmt,!mba
 
arch/x86/kernel/cpu/resctrl/core.c +2 -0
index 7109cbfcad4f..326c679ade5c 100644
@@ -705,6 +705,7 @@ enum {
 	RDT_FLAG_MBA,
 	RDT_FLAG_SMBA,
 	RDT_FLAG_BMEC,
+	RDT_FLAG_SDCIAE,
 };
 
 #define RDT_OPT(idx, n, f)	\
@@ -730,6 +731,7 @@ static struct rdt_options rdt_options[]  __ro_after_init = {
 	RDT_OPT(RDT_FLAG_MBA,	    "mba",	X86_FEATURE_MBA),
 	RDT_OPT(RDT_FLAG_SMBA,	    "smba",	X86_FEATURE_SMBA),
 	RDT_OPT(RDT_FLAG_BMEC,	    "bmec",	X86_FEATURE_BMEC),
+	RDT_OPT(RDT_FLAG_SDCIAE,    "sdciae",	X86_FEATURE_SDCIAE),
 };
 #define NUM_RDT_OPTIONS ARRAY_SIZE(rdt_options)
 
Signature · 1 line
2.34.1
author reviewer
#3 lore raw

PATCH v6 3/8 x86/resctrl: Detect io_alloc feature

In reply to Babu Moger

Smart Data Cache Injection (SDCI) is a mechanism that enables direct insertion of data from I/O devices into the L3 cache. It can the demands on DRAM bandwidth and reduces latency to the processor consuming the I/O data.

Introduce cache resource property "io_alloc_capable" that an architecture can set if a portion of the L3 cache can be allocated for I/O traffic.

Set this property on x86 systems that support SDCIAE (L3 Smart Data Cache Injection Allocation Enforcement).

---
v6: No changes.

v5: No changes.

v4: Updated the commit message and code comment based on feedback.

v3: Rewrote commit log. Changed the text to bit generic than the AMD specific.
Renamed the rdt_get_sdciae_alloc_cfg() to rdt_set_io_alloc_capable(). Removed leftover comment from v2.

v2: Changed sdciae_capable to io_alloc_capable to make it generic feature.
Also moved the io_alloc_capable in struct resctrl_cache.

---
 arch/x86/kernel/cpu/resctrl/core.c | 7 +++++++
 include/linux/resctrl.h            | 3 +++
 2 files changed, 10 insertions(+)
arch/x86/kernel/cpu/resctrl/core.c +7 -0
index 326c679ade5c..a3d174362249 100644
@@ -274,6 +274,11 @@ static void rdt_get_cdp_config(int level)
 	rdt_resources_all[level].r_resctrl.cdp_capable = true;
 }
 
+static void rdt_set_io_alloc_capable(struct rdt_resource *r)
+{
+	r->cache.io_alloc_capable = true;
+}
+
 static void rdt_get_cdp_l3_config(void)
 {
 	rdt_get_cdp_config(RDT_RESOURCE_L3);
@@ -840,6 +845,8 @@ static __init bool get_rdt_alloc_resources(void)
 		rdt_get_cache_alloc_cfg(1, r);
 		if (rdt_cpu_has(X86_FEATURE_CDP_L3))
 			rdt_get_cdp_l3_config();
+		if (rdt_cpu_has(X86_FEATURE_SDCIAE))
+			rdt_set_io_alloc_capable(r);
 		ret = true;
 	}
 	if (rdt_cpu_has(X86_FEATURE_CAT_L2)) {
include/linux/resctrl.h +3 -0
index 9ba771f2ddea..0e8641e41100 100644
@@ -191,6 +191,8 @@ struct rdt_mon_domain {
  * @arch_has_sparse_bitmasks:	True if a bitmask like f00f is valid.
  * @arch_has_per_cpu_cfg:	True if QOS_CFG register for this cache
  *				level has CPU scope.
+ * @io_alloc_capable:	True if portion of the cache can be allocated
+ *			for I/O traffic.
  */
 struct resctrl_cache {
 	unsigned int	cbm_len;
@@ -198,6 +200,7 @@ struct resctrl_cache {
 	unsigned int	shareable_bits;
 	bool		arch_has_sparse_bitmasks;
 	bool		arch_has_per_cpu_cfg;
+	bool		io_alloc_capable;
 };
 
 /**
Signature · 1 line
2.34.1
maintainer
#4 lore raw

Re: [PATCH v6 3/8] x86/resctrl: Detect io_alloc feature

Hi Babu,

Please modify subject prefix to "x86,fs/resctrl" since this adds new arch API called by resctrl fs.

Quoted 2 lines · Babu Moger

Smart Data Cache Injection (SDCI) is a mechanism that enables direct insertion of data from I/O devices into the L3 cache. It can the demands

"It can the demands" -> "It can reduce demands"?

Quoted 5 lines

on DRAM bandwidth and reduces latency to the processor consuming the I/O data.

Introduce cache resource property "io_alloc_capable" that an architecture can set if a portion of the L3 cache can be allocated for I/O traffic.

I think "L3" should be dropped because the cache resource property is not unique to L3. It is a property of all cache resources.

Quoted 2 lines

Set this property on x86 systems that support SDCIAE (L3 Smart Data Cache Injection Allocation Enforcement).

Here it can be mentioned that this property is only set for the L3 cache resource on systems that supports SDCIAE.

Quoted 50 lines

---
v6: No changes.

v5: No changes.

v4: Updated the commit message and code comment based on feedback.

v3: Rewrote commit log. Changed the text to bit generic than the AMD specific.
Renamed the rdt_get_sdciae_alloc_cfg() to rdt_set_io_alloc_capable(). Removed leftover comment from v2.

v2: Changed sdciae_capable to io_alloc_capable to make it generic feature.
Also moved the io_alloc_capable in struct resctrl_cache.

---
 arch/x86/kernel/cpu/resctrl/core.c | 7 +++++++
 include/linux/resctrl.h            | 3 +++
 2 files changed, 10 insertions(+)
arch/x86/kernel/cpu/resctrl/core.c +7 -0
index 326c679ade5c..a3d174362249 100644
@@ -274,6 +274,11 @@ static void rdt_get_cdp_config(int level)
 	rdt_resources_all[level].r_resctrl.cdp_capable = true;
 }
 
+static void rdt_set_io_alloc_capable(struct rdt_resource *r)
+{
+	r->cache.io_alloc_capable = true;
+}
+
 static void rdt_get_cdp_l3_config(void)
 {
 	rdt_get_cdp_config(RDT_RESOURCE_L3);
@@ -840,6 +845,8 @@ static __init bool get_rdt_alloc_resources(void)
 		rdt_get_cache_alloc_cfg(1, r);
 		if (rdt_cpu_has(X86_FEATURE_CDP_L3))
 			rdt_get_cdp_l3_config();
+		if (rdt_cpu_has(X86_FEATURE_SDCIAE))
+			rdt_set_io_alloc_capable(r);
 		ret = true;
 	}
 	if (rdt_cpu_has(X86_FEATURE_CAT_L2)) {
include/linux/resctrl.h +0 -0
index 9ba771f2ddea..0e8641e41100 100644

include/linux/resctrl.h struct rdt_mon_domain { · line 195

Quoted 5 lines
include/linux/resctrl.h +2 -0
@@ -191,6 +191,8 @@ struct rdt_mon_domain {
  * @arch_has_sparse_bitmasks:	True if a bitmask like f00f is valid.
  * @arch_has_per_cpu_cfg:	True if QOS_CFG register for this cache
  *				level has CPU scope.
+ * @io_alloc_capable:	True if portion of the cache can be allocated
+ *			for I/O traffic.

Reading this again I think the description can be improved since technically resctrl does not allocate a portion of cache but instead configures the portion of cache that device can allocate into.
So perhaps this can be: "True if portion of the cache can be configured for I/O traffic allocation."

include/linux/resctrl.h struct resctrl_cache { · line 206

Quoted 11 lines
include/linux/resctrl.h +1 -0
  */
 struct resctrl_cache {
 	unsigned int	cbm_len;
@@ -198,6 +200,7 @@ struct resctrl_cache {
 	unsigned int	shareable_bits;
 	bool		arch_has_sparse_bitmasks;
 	bool		arch_has_per_cpu_cfg;
+	bool		io_alloc_capable;
 };
 
 /**

Reinette

author reviewer
#5 lore raw

Re: [PATCH v6 3/8] x86/resctrl: Detect io_alloc feature

Hi Reinette,

Quoted 4 lines · Reinette Chatre

Hi Babu,

Please modify subject prefix to "x86,fs/resctrl" since this adds new arch API called by resctrl fs.

Sure.

Quoted 6 lines · Babu Moger
Quoted 2 lines

Smart Data Cache Injection (SDCI) is a mechanism that enables direct insertion of data from I/O devices into the L3 cache. It can the demands

"It can the demands" -> "It can reduce demands"?

Sure.

Quoted 69 lines
Quoted 6 lines

on DRAM bandwidth and reduces latency to the processor consuming the I/O data.

Introduce cache resource property "io_alloc_capable" that an architecture can set if a portion of the L3 cache can be allocated for I/O traffic.

I think "L3" should be dropped because the cache resource property is not unique to L3. It is a property of all cache resources.

Quoted 2 lines

Set this property on x86 systems that support SDCIAE (L3 Smart Data Cache Injection Allocation Enforcement).

Here it can be mentioned that this property is only set for the L3 cache resource on systems that supports SDCIAE.

Quoted 53 lines

---
v6: No changes.

v5: No changes.

v4: Updated the commit message and code comment based on feedback.

v3: Rewrote commit log. Changed the text to bit generic than the AMD specific.
Renamed the rdt_get_sdciae_alloc_cfg() to rdt_set_io_alloc_capable(). Removed leftover comment from v2.

v2: Changed sdciae_capable to io_alloc_capable to make it generic feature.
Also moved the io_alloc_capable in struct resctrl_cache.

---
 arch/x86/kernel/cpu/resctrl/core.c | 7 +++++++
 include/linux/resctrl.h            | 3 +++
 2 files changed, 10 insertions(+)
arch/x86/kernel/cpu/resctrl/core.c +7 -0
index 326c679ade5c..a3d174362249 100644
@@ -274,6 +274,11 @@ static void rdt_get_cdp_config(int level)
 	rdt_resources_all[level].r_resctrl.cdp_capable = true;
 }
 
+static void rdt_set_io_alloc_capable(struct rdt_resource *r)
+{
+	r->cache.io_alloc_capable = true;
+}
+
 static void rdt_get_cdp_l3_config(void)
 {
 	rdt_get_cdp_config(RDT_RESOURCE_L3);
@@ -840,6 +845,8 @@ static __init bool get_rdt_alloc_resources(void)
 		rdt_get_cache_alloc_cfg(1, r);
 		if (rdt_cpu_has(X86_FEATURE_CDP_L3))
 			rdt_get_cdp_l3_config();
+		if (rdt_cpu_has(X86_FEATURE_SDCIAE))
+			rdt_set_io_alloc_capable(r);
 		ret = true;
 	}
 	if (rdt_cpu_has(X86_FEATURE_CAT_L2)) {
include/linux/resctrl.h +0 -0
index 9ba771f2ddea..0e8641e41100 100644
@@ -191,6 +191,8 @@ struct rdt_mon_domain {
  * @arch_has_sparse_bitmasks:	True if a bitmask like f00f is valid.
  * @arch_has_per_cpu_cfg:	True if QOS_CFG register for this cache
  *				level has CPU scope.
Quoted 8 lines

include/linux/resctrl.h struct rdt_mon_domain { · line 195

Quoted 2 lines
include/linux/resctrl.h +2 -0
+ * @io_alloc_capable:	True if portion of the cache can be allocated
+ *			for I/O traffic.

Reading this again I think the description can be improved since technically resctrl does not allocate a portion of cache but instead configures the portion of cache that device can allocate into.
So perhaps this can be: "True if portion of the cache can be configured for I/O traffic allocation."

Sure.

Quoted 15 lines

include/linux/resctrl.h struct resctrl_cache { · line 206

Quoted 12 lines
include/linux/resctrl.h +1 -0
  */
 struct resctrl_cache {
 	unsigned int	cbm_len;
@@ -198,6 +200,7 @@ struct resctrl_cache {
 	unsigned int	shareable_bits;
 	bool		arch_has_sparse_bitmasks;
 	bool		arch_has_per_cpu_cfg;
+	bool		io_alloc_capable;
 };
 
 /**

Reinette

Signature · 2 lines
Thanks
Babu Moger
author reviewer
#6 lore raw

PATCH v6 4/8 x86/resctrl: Implement "io_alloc" enable/disable handlers

In reply to Babu Moger

"io_alloc" enables direct insertion of data from I/O devices into the L3 cache.

On AMD, "io_alloc" feature is backed by L3 Smart Data Cache Injection Allocation Enforcement (SDCIAE). Change SDCIAE state by setting (to enable) or clearing (to disable) bit 1 of MSR L3_QOS_EXT_CFG on all logical processors within the cache domain.

Introduce architecture-specific handlers to enable and disable the feature.

The SDCIAE feature details are available in APM listed below [1].
[1] AMD64 Architecture Programmer's Manual Volume 2: System Programming Publication # 24593 Revision 3.41 section 19.4.7 L3 Smart Data Cache Injection Allocation Enforcement (SDCIAE)

---
v6: Added lockdep_assert_cpus_held() in _resctrl_sdciae_enable() to protect
r->ctrl_domains.
Added more comments in include/linux/resctrl.h.

v5: Resolved conflicts due to recent resctrl FS/ARCH code restructure.
The files monitor.c/rdtgroup.c have been split between FS and ARCH directories. Moved prototypes of resctrl_arch_io_alloc_enable() and resctrl_arch_get_io_alloc_enabled() to include/linux/resctrl.h.

v4: Updated the commit log to address the feedback.

v3: Passed the struct rdt_resource to resctrl_arch_get_io_alloc_enabled() instead of resource id.
Renamed the _resctrl_io_alloc_enable() to _resctrl_sdciae_enable() as it is arch specific. Changed the return to void in _resctrl_sdciae_enable() instead of int.
Added more context in commit log and fixed few typos.

v2: Renamed the functions to simplify the code.
Renamed sdciae_capable to io_alloc_capable.

Changed the name of few arch functions similar to ABMC series. resctrl_arch_get_io_alloc_enabled() resctrl_arch_io_alloc_enable()

---
 arch/x86/include/asm/msr-index.h       |  1 +
 arch/x86/kernel/cpu/resctrl/internal.h |  5 ++++
 arch/x86/kernel/cpu/resctrl/rdtgroup.c | 40 ++++++++++++++++++++++++++
 include/linux/resctrl.h                | 21 ++++++++++++++
 4 files changed, 67 insertions(+)
arch/x86/include/asm/msr-index.h +1 -0
index b7dded3c8113..b92b04fa9888 100644
@@ -1215,6 +1215,7 @@
 /* - AMD: */
 #define MSR_IA32_MBA_BW_BASE		0xc0000200
 #define MSR_IA32_SMBA_BW_BASE		0xc0000280
+#define MSR_IA32_L3_QOS_EXT_CFG		0xc00003ff
 #define MSR_IA32_EVT_CFG_BASE		0xc0000400
 
 /* AMD-V MSRs */
arch/x86/kernel/cpu/resctrl/internal.h +5 -0
index 5e3c41b36437..cfa519ea2875 100644
@@ -37,6 +37,9 @@ struct arch_mbm_state {
 	u64	prev_msr;
 };
 
+/* Setting bit 1 in L3_QOS_EXT_CFG enables the SDCIAE feature. */
+#define SDCIAE_ENABLE_BIT		1
+
 /**
  * struct rdt_hw_ctrl_domain - Arch private attributes of a set of CPUs that share
  *			       a resource for a control function
@@ -102,6 +105,7 @@ struct msr_param {
  * @mon_scale:		cqm counter * mon_scale = occupancy in bytes
  * @mbm_width:		Monitor width, to detect and correct for overflow.
  * @cdp_enabled:	CDP state of this resource
+ * @sdciae_enabled:	SDCIAE feature is enabled
  *
  * Members of this structure are either private to the architecture
  * e.g. mbm_width, or accessed via helpers that provide abstraction. e.g.
@@ -115,6 +119,7 @@ struct rdt_hw_resource {
 	unsigned int		mon_scale;
 	unsigned int		mbm_width;
 	bool			cdp_enabled;
+	bool			sdciae_enabled;
 };
 
 static inline struct rdt_hw_resource *resctrl_to_arch_res(struct rdt_resource *r)
arch/x86/kernel/cpu/resctrl/rdtgroup.c +40 -0
index 885026468440..3bdcd53b3ce3 100644
@@ -229,6 +229,46 @@ bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level l)
 	return rdt_resources_all[l].cdp_enabled;
 }
 
+inline bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r)
+{
+	return resctrl_to_arch_res(r)->sdciae_enabled;
+}
+
+static void resctrl_sdciae_set_one_amd(void *arg)
+{
+	bool *enable = arg;
+
+	if (*enable)
+		msr_set_bit(MSR_IA32_L3_QOS_EXT_CFG, SDCIAE_ENABLE_BIT);
+	else
+		msr_clear_bit(MSR_IA32_L3_QOS_EXT_CFG, SDCIAE_ENABLE_BIT);
+}
+
+static void _resctrl_sdciae_enable(struct rdt_resource *r, bool enable)
+{
+	struct rdt_ctrl_domain *d;
+
+	/* Walking r->ctrl_domains, ensure it can't race with cpuhp */
+	lockdep_assert_cpus_held();
+
+	/* Update L3_QOS_EXT_CFG MSR on all the CPUs in all domains */
+	list_for_each_entry(d, &r->ctrl_domains, hdr.list)
+		on_each_cpu_mask(&d->hdr.cpu_mask, resctrl_sdciae_set_one_amd, &enable, 1);
+}
+
+int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable)
+{
+	struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
+
+	if (hw_res->r_resctrl.cache.io_alloc_capable &&
+	    hw_res->sdciae_enabled != enable) {
+		_resctrl_sdciae_enable(r, enable);
+		hw_res->sdciae_enabled = enable;
+	}
+
+	return 0;
+}
+
 void resctrl_arch_reset_all_ctrls(struct rdt_resource *r)
 {
 	struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
include/linux/resctrl.h +21 -0
index 0e8641e41100..06e8a1821702 100644
@@ -531,6 +531,27 @@ void resctrl_arch_reset_rmid_all(struct rdt_resource *r, struct rdt_mon_domain *
  */
 void resctrl_arch_reset_all_ctrls(struct rdt_resource *r);
 
+/**
+ * resctrl_arch_io_alloc_enable() - Enable/disable io_alloc feature.
+ * @r:		The resctrl resource.
+ * @enable:	Enable (true) or disable (false) io_alloc on resource @r.
+ *
+ * This can be called from any CPU.
+ *
+ * Return:
+ * 0 on success, or non-zero on error.
+ */
+int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable);
+
+/**
+ * resctrl_arch_get_io_alloc_enabled() - Get io_alloc feature state.
+ * @r:		The resctrl resource.
+ *
+ * Return:
+ * true if io_alloc is enabled or false if disabled.
+ */
+inline bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r);
+
 extern unsigned int resctrl_rmid_realloc_threshold;
 extern unsigned int resctrl_rmid_realloc_limit;
 
Signature · 1 line
2.34.1
maintainer
#7 lore raw

Re: [PATCH v6 4/8] x86/resctrl: Implement "io_alloc" enable/disable handlers

Hi Babu,

Quoted 2 lines · Babu Moger

"io_alloc" enables direct insertion of data from I/O devices into the L3 cache.

Above is from resctrl perspective and resctrl does not limit this to L3. Here also I think L3 should be dropped.

Quoted 16 lines

On AMD, "io_alloc" feature is backed by L3 Smart Data Cache Injection Allocation Enforcement (SDCIAE). Change SDCIAE state by setting (to enable) or clearing (to disable) bit 1 of MSR L3_QOS_EXT_CFG on all logical processors within the cache domain.

Introduce architecture-specific handlers to enable and disable the feature.

The SDCIAE feature details are available in APM listed below [1].
[1] AMD64 Architecture Programmer's Manual Volume 2: System Programming Publication # 24593 Revision 3.41 section 19.4.7 L3 Smart Data Cache Injection Allocation Enforcement (SDCIAE)

---

...

Quoted 5 lines
---
 arch/x86/include/asm/msr-index.h       |  1 +
 arch/x86/kernel/cpu/resctrl/internal.h |  5 ++++
 arch/x86/kernel/cpu/resctrl/rdtgroup.c | 40 ++++++++++++++++++++++++++
 include/linux/resctrl.h                | 21 ++++++++++++++

This hints the subject prefix should be "x86,fs/resctrl".

Quoted 29 lines
 4 files changed, 67 insertions(+)
arch/x86/include/asm/msr-index.h +1 -0
index b7dded3c8113..b92b04fa9888 100644
@@ -1215,6 +1215,7 @@
 /* - AMD: */
 #define MSR_IA32_MBA_BW_BASE		0xc0000200
 #define MSR_IA32_SMBA_BW_BASE		0xc0000280
+#define MSR_IA32_L3_QOS_EXT_CFG		0xc00003ff
 #define MSR_IA32_EVT_CFG_BASE		0xc0000400
 
 /* AMD-V MSRs */
arch/x86/kernel/cpu/resctrl/internal.h +3 -0
index 5e3c41b36437..cfa519ea2875 100644
@@ -37,6 +37,9 @@ struct arch_mbm_state {
 	u64	prev_msr;
 };
 
+/* Setting bit 1 in L3_QOS_EXT_CFG enables the SDCIAE feature. */
+#define SDCIAE_ENABLE_BIT		1
+
 /**
  * struct rdt_hw_ctrl_domain - Arch private attributes of a set of CPUs that share
  *			       a resource for a control function

arch/x86/kernel/cpu/resctrl/internal.h struct msr_param { · line 108

Quoted 4 lines
arch/x86/kernel/cpu/resctrl/internal.h +1 -0
@@ -102,6 +105,7 @@ struct msr_param {
  * @mon_scale:		cqm counter * mon_scale = occupancy in bytes
  * @mbm_width:		Monitor width, to detect and correct for overflow.
  * @cdp_enabled:	CDP state of this resource
+ * @sdciae_enabled:	SDCIAE feature is enabled

nit: "SDCIAE feature (backing "io_alloc") is enabled"

Quoted 16 lines
arch/x86/kernel/cpu/resctrl/internal.h +1 -0
  *
  * Members of this structure are either private to the architecture
  * e.g. mbm_width, or accessed via helpers that provide abstraction. e.g.
@@ -115,6 +119,7 @@ struct rdt_hw_resource {
 	unsigned int		mon_scale;
 	unsigned int		mbm_width;
 	bool			cdp_enabled;
+	bool			sdciae_enabled;
 };
 
 static inline struct rdt_hw_resource *resctrl_to_arch_res(struct rdt_resource *r)
arch/x86/kernel/cpu/resctrl/rdtgroup.c +0 -0
index 885026468440..3bdcd53b3ce3 100644

arch/x86/kernel/cpu/resctrl/rdtgroup.c bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level l) · line 232

Quoted 4 lines
arch/x86/kernel/cpu/resctrl/rdtgroup.c +1 -0
@@ -229,6 +229,46 @@ bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level l)
 	return rdt_resources_all[l].cdp_enabled;
 }
 
+inline bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r)

As indicated by lkp the inline usage needs to be fixed.

Quoted 49 lines
arch/x86/kernel/cpu/resctrl/rdtgroup.c +39 -0
+{
+	return resctrl_to_arch_res(r)->sdciae_enabled;
+}
+
+static void resctrl_sdciae_set_one_amd(void *arg)
+{
+	bool *enable = arg;
+
+	if (*enable)
+		msr_set_bit(MSR_IA32_L3_QOS_EXT_CFG, SDCIAE_ENABLE_BIT);
+	else
+		msr_clear_bit(MSR_IA32_L3_QOS_EXT_CFG, SDCIAE_ENABLE_BIT);
+}
+
+static void _resctrl_sdciae_enable(struct rdt_resource *r, bool enable)
+{
+	struct rdt_ctrl_domain *d;
+
+	/* Walking r->ctrl_domains, ensure it can't race with cpuhp */
+	lockdep_assert_cpus_held();
+
+	/* Update L3_QOS_EXT_CFG MSR on all the CPUs in all domains */
+	list_for_each_entry(d, &r->ctrl_domains, hdr.list)
+		on_each_cpu_mask(&d->hdr.cpu_mask, resctrl_sdciae_set_one_amd, &enable, 1);
+}
+
+int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable)
+{
+	struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
+
+	if (hw_res->r_resctrl.cache.io_alloc_capable &&
+	    hw_res->sdciae_enabled != enable) {
+		_resctrl_sdciae_enable(r, enable);
+		hw_res->sdciae_enabled = enable;
+	}
+
+	return 0;
+}
+
 void resctrl_arch_reset_all_ctrls(struct rdt_resource *r)
 {
 	struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
include/linux/resctrl.h +0 -0
index 0e8641e41100..06e8a1821702 100644
@@ -531,6 +531,27 @@ void resctrl_arch_reset_rmid_all(struct rdt_resource *r, struct rdt_mon_domain *
  */
 void resctrl_arch_reset_all_ctrls(struct rdt_resource *r);

include/linux/resctrl.h void resctrl_arch_reset_rmid_all(struct rdt_resource *r, struct rdt_mon_domain * · line 542

Quoted 10 lines
include/linux/resctrl.h +9 -0
 
+/**
+ * resctrl_arch_io_alloc_enable() - Enable/disable io_alloc feature.
+ * @r:		The resctrl resource.
+ * @enable:	Enable (true) or disable (false) io_alloc on resource @r.
+ *
+ * This can be called from any CPU.
+ *
+ * Return:
+ * 0 on success, or non-zero on error.

Please change to "0 on success, <0 on error" to make clear it needs to be non-zero *and* negative to be considered error by resctrl fs.

Quoted 5 lines
include/linux/resctrl.h +5 -0
+ */
+int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable);
+
+/**
+ * resctrl_arch_get_io_alloc_enabled() - Get io_alloc feature state.

include/linux/resctrl.h void resctrl_arch_reset_rmid_all(struct rdt_resource *r, struct rdt_mon_domain * · line 557

Quoted 10 lines
include/linux/resctrl.h +7 -0
+ * @r:		The resctrl resource.
+ *
+ * Return:
+ * true if io_alloc is enabled or false if disabled.
+ */
+inline bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r);
+
 extern unsigned int resctrl_rmid_realloc_threshold;
 extern unsigned int resctrl_rmid_realloc_limit;
 

Reinette

author reviewer
#8 lore raw

Re: [PATCH v6 4/8] x86/resctrl: Implement "io_alloc" enable/disable handlers

Hi Reinette,

Quoted 8 lines · Reinette Chatre

Hi Babu,

Quoted 2 lines · Babu Moger

"io_alloc" enables direct insertion of data from I/O devices into the L3 cache.

Above is from resctrl perspective and resctrl does not limit this to L3. Here also I think L3 should be dropped.

Sure.

Quoted 20 lines
Quoted 17 lines

On AMD, "io_alloc" feature is backed by L3 Smart Data Cache Injection Allocation Enforcement (SDCIAE). Change SDCIAE state by setting (to enable) or clearing (to disable) bit 1 of MSR L3_QOS_EXT_CFG on all logical processors within the cache domain.

Introduce architecture-specific handlers to enable and disable the feature.

The SDCIAE feature details are available in APM listed below [1].
[1] AMD64 Architecture Programmer's Manual Volume 2: System Programming Publication # 24593 Revision 3.41 section 19.4.7 L3 Smart Data Cache Injection Allocation Enforcement (SDCIAE)

---

...

Quoted 7 lines
Quoted 5 lines
---
 arch/x86/include/asm/msr-index.h       |  1 +
 arch/x86/kernel/cpu/resctrl/internal.h |  5 ++++
 arch/x86/kernel/cpu/resctrl/rdtgroup.c | 40 ++++++++++++++++++++++++++
 include/linux/resctrl.h                | 21 ++++++++++++++

This hints the subject prefix should be "x86,fs/resctrl".

Sure.

Quoted 23 lines
Quoted 23 lines
 4 files changed, 67 insertions(+)
arch/x86/include/asm/msr-index.h +1 -0
index b7dded3c8113..b92b04fa9888 100644
@@ -1215,6 +1215,7 @@
 /* - AMD: */
 #define MSR_IA32_MBA_BW_BASE		0xc0000200
 #define MSR_IA32_SMBA_BW_BASE		0xc0000280
+#define MSR_IA32_L3_QOS_EXT_CFG		0xc00003ff
 #define MSR_IA32_EVT_CFG_BASE		0xc0000400
 
 /* AMD-V MSRs */
arch/x86/kernel/cpu/resctrl/internal.h +0 -0
index 5e3c41b36437..cfa519ea2875 100644
@@ -37,6 +37,9 @@ struct arch_mbm_state {
 	u64	prev_msr;
 };
 
Quoted 13 lines

arch/x86/kernel/cpu/resctrl/internal.h struct msr_param { · line 108

Quoted 11 lines
arch/x86/kernel/cpu/resctrl/internal.h +4 -0
+/* Setting bit 1 in L3_QOS_EXT_CFG enables the SDCIAE feature. */
+#define SDCIAE_ENABLE_BIT		1
+
 /**
  * struct rdt_hw_ctrl_domain - Arch private attributes of a set of CPUs that share
  *			       a resource for a control function
@@ -102,6 +105,7 @@ struct msr_param {
  * @mon_scale:		cqm counter * mon_scale = occupancy in bytes
  * @mbm_width:		Monitor width, to detect and correct for overflow.
  * @cdp_enabled:	CDP state of this resource
+ * @sdciae_enabled:	SDCIAE feature is enabled

nit: "SDCIAE feature (backing "io_alloc") is enabled"

Sure.

Quoted 20 lines
Quoted 20 lines
arch/x86/kernel/cpu/resctrl/internal.h +1 -0
  *
  * Members of this structure are either private to the architecture
  * e.g. mbm_width, or accessed via helpers that provide abstraction. e.g.
@@ -115,6 +119,7 @@ struct rdt_hw_resource {
 	unsigned int		mon_scale;
 	unsigned int		mbm_width;
 	bool			cdp_enabled;
+	bool			sdciae_enabled;
 };
 
 static inline struct rdt_hw_resource *resctrl_to_arch_res(struct rdt_resource *r)
arch/x86/kernel/cpu/resctrl/rdtgroup.c +0 -0
index 885026468440..3bdcd53b3ce3 100644
@@ -229,6 +229,46 @@ bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level l)
 	return rdt_resources_all[l].cdp_enabled;
 }
 
Quoted 3 lines

arch/x86/kernel/cpu/resctrl/rdtgroup.c bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level l) · line 232

Quoted 1 line
arch/x86/kernel/cpu/resctrl/rdtgroup.c +1 -0
+inline bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r)

As indicated by lkp the inline usage needs to be fixed.

I am assuming that you are referring to
https://www.kernel.org/doc/html/next/process/coding-style.html#the-inline-disease

I will remove inline attribute.

Quoted 51 lines
Quoted 51 lines
arch/x86/kernel/cpu/resctrl/rdtgroup.c +39 -0
+{
+	return resctrl_to_arch_res(r)->sdciae_enabled;
+}
+
+static void resctrl_sdciae_set_one_amd(void *arg)
+{
+	bool *enable = arg;
+
+	if (*enable)
+		msr_set_bit(MSR_IA32_L3_QOS_EXT_CFG, SDCIAE_ENABLE_BIT);
+	else
+		msr_clear_bit(MSR_IA32_L3_QOS_EXT_CFG, SDCIAE_ENABLE_BIT);
+}
+
+static void _resctrl_sdciae_enable(struct rdt_resource *r, bool enable)
+{
+	struct rdt_ctrl_domain *d;
+
+	/* Walking r->ctrl_domains, ensure it can't race with cpuhp */
+	lockdep_assert_cpus_held();
+
+	/* Update L3_QOS_EXT_CFG MSR on all the CPUs in all domains */
+	list_for_each_entry(d, &r->ctrl_domains, hdr.list)
+		on_each_cpu_mask(&d->hdr.cpu_mask, resctrl_sdciae_set_one_amd, &enable, 1);
+}
+
+int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable)
+{
+	struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
+
+	if (hw_res->r_resctrl.cache.io_alloc_capable &&
+	    hw_res->sdciae_enabled != enable) {
+		_resctrl_sdciae_enable(r, enable);
+		hw_res->sdciae_enabled = enable;
+	}
+
+	return 0;
+}
+
 void resctrl_arch_reset_all_ctrls(struct rdt_resource *r)
 {
 	struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
include/linux/resctrl.h +0 -0
index 0e8641e41100..06e8a1821702 100644
@@ -531,6 +531,27 @@ void resctrl_arch_reset_rmid_all(struct rdt_resource *r, struct rdt_mon_domain *
  */
 void resctrl_arch_reset_all_ctrls(struct rdt_resource *r);
 
Quoted 12 lines

include/linux/resctrl.h void resctrl_arch_reset_rmid_all(struct rdt_resource *r, struct rdt_mon_domain * · line 542

Quoted 9 lines
include/linux/resctrl.h +9 -0
+/**
+ * resctrl_arch_io_alloc_enable() - Enable/disable io_alloc feature.
+ * @r:		The resctrl resource.
+ * @enable:	Enable (true) or disable (false) io_alloc on resource @r.
+ *
+ * This can be called from any CPU.
+ *
+ * Return:
+ * 0 on success, or non-zero on error.

Please change to "0 on success, <0 on error" to make clear it needs to be non-zero *and* negative to be considered error by resctrl fs.

Sure.

Quoted 19 lines
Quoted 6 lines
include/linux/resctrl.h +5 -0
+ */
+int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable);
+
+/**
+ * resctrl_arch_get_io_alloc_enabled() - Get io_alloc feature state.

include/linux/resctrl.h void resctrl_arch_reset_rmid_all(struct rdt_resource *r, struct rdt_mon_domain * · line 557

Quoted 10 lines
include/linux/resctrl.h +7 -0
+ * @r:		The resctrl resource.
+ *
+ * Return:
+ * true if io_alloc is enabled or false if disabled.
+ */
+inline bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r);
+
 extern unsigned int resctrl_rmid_realloc_threshold;
 extern unsigned int resctrl_rmid_realloc_limit;
 

Reinette

Signature · 2 lines
Thanks
Babu Moger
maintainer
#9 lore raw

Re: [PATCH v6 4/8] x86/resctrl: Implement "io_alloc" enable/disable handlers

Hi Babu,

Quoted 13 lines · Babu
Quoted 11 lines · Reinette Chatre
Quoted 9 lines · Babu Moger

static inline struct rdt_hw_resource *resctrl_to_arch_res(struct rdt_resource *r)

arch/x86/kernel/cpu/resctrl/rdtgroup.c +0 -0
index 885026468440..3bdcd53b3ce3 100644
@@ -229,6 +229,46 @@ bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level l)
 	return rdt_resources_all[l].cdp_enabled;
 }
 
Quoted 6 lines
Quoted 3 lines

arch/x86/kernel/cpu/resctrl/rdtgroup.c bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level l) · line 232

Quoted 1 line
arch/x86/kernel/cpu/resctrl/rdtgroup.c +1 -0
+inline bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r)

As indicated by lkp the inline usage needs to be fixed.

I am assuming that you are referring to
https://www.kernel.org/doc/html/next/process/coding-style.html#the-inline-disease

No. I am referring to the lkp test report of an issue detected by sparse. Looks like the message was not cc'd to lkml so I cannot provide link. I paste it below. You are in "To:".

Quoted 2 lines

I will remove inline attribute.

The goal was to fix the broken usage of inline, but you are right that it may not be needed here.

Here is the original report:

Quoted 49 lines

Date: Fri, 13 Jun 2025 12:18:35 +0800
From: kernel test robot <[email protected]>
To: Babu Moger <[email protected]>, [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
CC: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
Subject: Re: [PATCH v6 5/8] fs/resctrl: Add user interface to enable/disable io_alloc feature
Message-ID: <[email protected]>
In-Reply-To: <b3d8e2ccd23b295f3735fc9f5420458cfc18a896.1749677012.git.babu.moger@amd.com>

Hi Babu,

kernel test robot noticed the following build warnings:

[auto build test WARNING on brauner-vfs/vfs.all]
[also build test WARNING on linus/master v6.16-rc1 next-20250612] [cannot apply to tip/x86/core aegl/next]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Babu-Moger/x86-cpufeatures-Add-support-for-L3-Smart-Data-Cache-Injection-Allocation-Enforcement/20250612-053050
base:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git vfs.all
patch link:    https://lore.kernel.org/r/b3d8e2ccd23b295f3735fc9f5420458cfc18a896.1749677012.git.babu.moger%40amd.com
patch subject: [PATCH v6 5/8] fs/resctrl: Add user interface to enable/disable io_alloc feature
config: i386-randconfig-061-20250613 (https://download.01.org/0day-ci/archive/20250613/[email protected]/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250613/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

sparse warnings: (new ones prefixed by >>)
fs/resctrl/rdtgroup.c: note: in included file:

Quoted 4 lines
Quoted 4 lines

include/linux/resctrl.h:553:46: sparse: sparse: marked inline, but without a definition include/linux/resctrl.h:553:46: sparse: sparse: marked inline, but without a definition include/linux/resctrl.h:553:46: sparse: sparse: marked inline, but without a definition include/linux/resctrl.h:553:46: sparse: sparse: marked inline, but without a definition

vim +553 include/linux/resctrl.h

48e63934badb71 Babu Moger 2025-06-11  545  
48e63934badb71 Babu Moger 2025-06-11  546  /**
48e63934badb71 Babu Moger 2025-06-11  547   * resctrl_arch_get_io_alloc_enabled() - Get io_alloc feature state.
48e63934badb71 Babu Moger 2025-06-11  548   * @r:		The resctrl resource.
48e63934badb71 Babu Moger 2025-06-11  549   *
48e63934badb71 Babu Moger 2025-06-11  550   * Return:
48e63934badb71 Babu Moger 2025-06-11  551   * true if io_alloc is enabled or false if disabled.
48e63934badb71 Babu Moger 2025-06-11  552   */
Quoted 6 lines

48e63934badb71 Babu Moger 2025-06-11 @553 inline bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r); 48e63934badb71 Babu Moger 2025-06-11 554

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

Reinette

#10 lore raw

Re: [PATCH v6 4/8] x86/resctrl: Implement "io_alloc" enable/disable handlers

Hi Reinette,

Quoted 21 lines · Reinette Chatre

Hi Babu,

Quoted 17 lines · Babu
Quoted 14 lines · Reinette Chatre

arch/x86/kernel/cpu/resctrl/rdtgroup.c bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level l) · line 232

Quoted 10 lines · Babu Moger

static inline struct rdt_hw_resource *resctrl_to_arch_res(struct rdt_resource *r)

arch/x86/kernel/cpu/resctrl/rdtgroup.c +1 -0
index 885026468440..3bdcd53b3ce3 100644
@@ -229,6 +229,46 @@ bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level l)
  	return rdt_resources_all[l].cdp_enabled;
  }
 
+inline bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r)

As indicated by lkp the inline usage needs to be fixed.

Quoted 6 lines
Quoted 2 lines

I am assuming that you are referring to
https://www.kernel.org/doc/html/next/process/coding-style.html#the-inline-disease

No. I am referring to the lkp test report of an issue detected by sparse. Looks like the message was not cc'd to lkml so I cannot provide link. I paste it below. You are in "To:".

Yes. I saw that report. It's strange why it was not cc'd to lkml. Happened few times before.

Quoted 6 lines
Quoted 3 lines

I will remove inline attribute.

The goal was to fix the broken usage of inline, but you are right that it may not be needed here.

Sure. Will remove inline.

Quoted 2 lines

Here is the original report:

Thanks

Babu

Quoted 59 lines
Quoted 50 lines

Date: Fri, 13 Jun 2025 12:18:35 +0800
From: kernel test robot <[email protected]>
To: Babu Moger <[email protected]>, [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
CC: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
Subject: Re: [PATCH v6 5/8] fs/resctrl: Add user interface to enable/disable io_alloc feature
Message-ID: <[email protected]>
In-Reply-To: <b3d8e2ccd23b295f3735fc9f5420458cfc18a896.1749677012.git.babu.moger@amd.com>

Hi Babu,

kernel test robot noticed the following build warnings:

[auto build test WARNING on brauner-vfs/vfs.all]
[also build test WARNING on linus/master v6.16-rc1 next-20250612] [cannot apply to tip/x86/core aegl/next]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Babu-Moger/x86-cpufeatures-Add-support-for-L3-Smart-Data-Cache-Injection-Allocation-Enforcement/20250612-053050
base:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git vfs.all
patch link:    https://lore.kernel.org/r/b3d8e2ccd23b295f3735fc9f5420458cfc18a896.1749677012.git.babu.moger%40amd.com
patch subject: [PATCH v6 5/8] fs/resctrl: Add user interface to enable/disable io_alloc feature
config: i386-randconfig-061-20250613 (https://download.01.org/0day-ci/archive/20250613/[email protected]/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250613/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

sparse warnings: (new ones prefixed by >>)
fs/resctrl/rdtgroup.c: note: in included file:

Quoted 4 lines
Quoted 4 lines

include/linux/resctrl.h:553:46: sparse: sparse: marked inline, but without a definition include/linux/resctrl.h:553:46: sparse: sparse: marked inline, but without a definition include/linux/resctrl.h:553:46: sparse: sparse: marked inline, but without a definition include/linux/resctrl.h:553:46: sparse: sparse: marked inline, but without a definition

vim +553 include/linux/resctrl.h

48e63934badb71 Babu Moger 2025-06-11  545
48e63934badb71 Babu Moger 2025-06-11  546  /**
48e63934badb71 Babu Moger 2025-06-11  547   * resctrl_arch_get_io_alloc_enabled() - Get io_alloc feature state.
48e63934badb71 Babu Moger 2025-06-11  548   * @r:		The resctrl resource.
48e63934badb71 Babu Moger 2025-06-11  549   *
48e63934badb71 Babu Moger 2025-06-11  550   * Return:
48e63934badb71 Babu Moger 2025-06-11  551   * true if io_alloc is enabled or false if disabled.
48e63934badb71 Babu Moger 2025-06-11  552   */
Quoted 6 lines

48e63934badb71 Babu Moger 2025-06-11 @553 inline bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r); 48e63934badb71 Babu Moger 2025-06-11 554

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

Reinette

author reviewer
#11 lore raw

PATCH v6 5/8 fs/resctrl: Add user interface to enable/disable io_alloc feature

In reply to Babu Moger

The io_alloc feature in resctrl is a mechanism that enables direct insertion of data from I/O devices into the L3 cache.

On AMD systems, io_alloc feature is backed by SDCIAE (L3 Smart Data Cache Injection Allocation Enforcement). When enabled, SDCIAE forces all SDCI lines to be placed into the L3 cache partitions identified by the highest-supported L3_MASK_n register as reported by CPUID Fn0000_0010_EDX_x1.MAX_COS. For example, if MAX_COS=15, SDCI lines will be allocated into the L3 cache partitions determined by the bitmask in the L3_MASK_15 register.

When CDP is enabled, io_alloc routes I/O traffic using the highest CLOSID allocated for the instruction cache (L3CODE).

Introduce user interface to enable/disable "io_alloc" feature.

---
v6: Changed the subject to fs/resctrl:

v5: Resolved conflicts due to recent resctrl FS/ARCH code restructure.
Used rdt_kn_name to get the rdtgroup name instead of accesssing it directly while printing group name used by the io_alloc_closid.

Updated bit_usage to reflect the io_alloc CBM as discussed in the thread:
https://lore.kernel.org/lkml/[email protected]/
Modified rdt_bit_usage_show() to read io_alloc_cbm in hw_shareable, ensuring that bit_usage accurately represents the CBMs.

Updated the code to modify io_alloc either with L3CODE or L3DATA.
https://lore.kernel.org/lkml/[email protected]/

v4: Updated the change log.
Updated the user doc.
The "io_alloc" interface will report "enabled/disabled/not supported". Updated resctrl_io_alloc_closid_get() to verify the max closid availability. Updated the documentation for "shareable_bits" and "bit_usage". Introduced io_alloc_init() to initialize fflags.
Printed the group name when io_alloc enablement fails.

NOTE: io_alloc is about specific CLOS. rdt_bit_usage_show() is not designed handle bit_usage for specific CLOS. Its about overall system. So, we cannot really tell the user which CLOS is shared across both hardware and software. We need to discuss this.

v3: Rewrote the change to make it generic.
Rewrote the documentation in resctrl.rst to be generic and added AMD feature details in the end.
Added the check to verify if MAX CLOSID availability on the system. Added CDP check to make sure io_alloc is configured in CDP_CODE. Added resctrl_io_alloc_closid_free() to free the io_alloc CLOSID. Added errors in few cases when CLOSID allocation fails. Fixes splat reported when info/L3/bit_usage is accesed when io_alloc is enabled.
https://lore.kernel.org/lkml/SJ1PR11MB60837B532254E7B23BC27E84FC052@SJ1PR11MB6083.namprd11.prod.outlook.com/

v2: Renamed the feature to "io_alloc".
Added generic texts for the feature in commit log and resctrl.rst doc. Added resctrl_io_alloc_init_cat() to initialize io_alloc to default values when enabled.
Fixed io_alloc show functinality to display only on L3 resource.

---
 Documentation/filesystems/resctrl.rst |  34 ++++
 fs/resctrl/rdtgroup.c                 | 216 +++++++++++++++++++++++++-
 2 files changed, 248 insertions(+), 2 deletions(-)
Documentation/filesystems/resctrl.rst +34 -0
index c7949dd44f2f..03c829b2c276 100644
@@ -95,6 +95,11 @@ related to allocation:
 		some platforms support devices that have their
 		own settings for cache use which can over-ride
 		these bits.
+
+		When the "io_alloc" feature is enabled, a portion of the cache
+		is reserved for shared use between hardware and software. Refer
+		to "bit_usage" to see which portion is allocated for this purpose.
+
 "bit_usage":
 		Annotated capacity bitmasks showing how all
 		instances of the resource are used. The legend is:
@@ -135,6 +140,35 @@ related to allocation:
 			"1":
 			      Non-contiguous 1s value in CBM is supported.
 
+"io_alloc":
+		The "io_alloc" enables system software to configure the portion
+		of the L3 cache allocated for I/O traffic.
+
+		The feature routes the I/O traffic via specific CLOSID reserved
+		for io_alloc feature. By configuring the CBM (Capacity Bit Mask)
+		for the CLOSID, users can control the L3 portions available for
+		I/0 traffic. The reserved CLOSID will be excluded for group creation.
+
+		The interface provides a means to query the status of the feature.
+
+		Example::
+
+			# cat /sys/fs/resctrl/info/L3/io_alloc
+			disabled
+
+		Feature can be enabled/disabled by writing to the interface.
+		Example::
+
+			# echo 1 > /sys/fs/resctrl/info/L3/io_alloc
+			# cat /sys/fs/resctrl/info/L3/io_alloc
+			enabled
+
+		On AMD systems, the io_alloc feature is supported by the L3 Smart
+		Data Cache Injection Allocation Enforcement (SDCIAE). The CLOSID for
+		io_alloc is determined by the highest CLOSID supported by the resource.
+		When CDP is enabled, io_alloc routes I/O traffic using the highest
+		CLOSID allocated for the instruction cache (L3CODE).
+
 Memory bandwidth(MB) subdirectory contains the following files
 with respect to allocation:
 
fs/resctrl/rdtgroup.c +214 -2

282 lines not on this page · raw message

Signature · 1 line
2.34.1
#12 lore raw

Re: [PATCH v6 5/8] fs/resctrl: Add user interface to enable/disable io_alloc feature

kernel test robot noticed the following build warnings:

Hi Babu,

kernel test robot noticed the following build warnings:

[auto build test WARNING on brauner-vfs/vfs.all]
[also build test WARNING on linus/master v6.16-rc1 next-20250612] [cannot apply to tip/x86/core aegl/next]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Babu-Moger/x86-cpufeatures-Add-support-for-L3-Smart-Data-Cache-Injection-Allocation-Enforcement/20250612-053050
base:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git vfs.all
patch link:    https://lore.kernel.org/r/b3d8e2ccd23b295f3735fc9f5420458cfc18a896.1749677012.git.babu.moger%40amd.com
patch subject: [PATCH v6 5/8] fs/resctrl: Add user interface to enable/disable io_alloc feature
config: x86_64-randconfig-r071-20250612 (https://download.01.org/0day-ci/archive/20250613/[email protected]/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

smatch warnings:
fs/resctrl/rdtgroup.c:1961 resctrl_io_alloc_write() warn: unsigned 'io_alloc_closid' is never less than zero. fs/resctrl/rdtgroup.c:1961 resctrl_io_alloc_write() warn: error code type promoted to positive: 'io_alloc_closid'

vim +/io_alloc_closid +1961 fs/resctrl/rdtgroup.c

1934
1935 static ssize_t resctrl_io_alloc_write(struct kernfs_open_file *of, char *buf,
1936 size_t nbytes, loff_t off)
1937 {
1938 struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
1939 struct rdt_resource *r = s->res;
1940 char const *grp_name;
1941 u32 io_alloc_closid;
1942 bool enable;
1943 int ret;
1944
1945 ret = kstrtobool(buf, &enable);
1946 if (ret)
1947 return ret;
1948
1949 cpus_read_lock();
1950 mutex_lock(&rdtgroup_mutex);
1951
1952 rdt_last_cmd_clear();
1953
1954 if (!r->cache.io_alloc_capable) {
1955 rdt_last_cmd_puts("io_alloc feature is not supported on the resource\n");
1956 ret = -ENODEV;
1957 goto out_io_alloc;
1958 }
1959
1960 io_alloc_closid = resctrl_io_alloc_closid_get(r);

> 1961		if (io_alloc_closid < 0) {

1962 rdt_last_cmd_puts("Max CLOSID to support io_alloc is not available\n");
1963 ret = -EINVAL;
1964 goto out_io_alloc;
1965 }
1966
1967 if (resctrl_arch_get_io_alloc_enabled(r) != enable) {
1968 if (enable) {
1969 ret = resctrl_io_alloc_closid_alloc(io_alloc_closid);
1970 if (ret < 0) {
1971 grp_name = rdtgroup_name_by_closid(io_alloc_closid);
1972 rdt_last_cmd_printf("CLOSID for io_alloc is used by %s group\n",
1973 grp_name ? grp_name : "another");
1974 ret = -EINVAL;
1975 goto out_io_alloc;
1976 }
1977
1978 ret = resctrl_io_alloc_init_cat(r, resctrl_schema_io_alloc(s),
1979 io_alloc_closid);
1980 if (ret) {
1981 rdt_last_cmd_puts("Failed to initialize io_alloc allocations\n");
1982 resctrl_io_alloc_closid_free(io_alloc_closid);
1983 goto out_io_alloc;
1984 }
1985
1986 } else {
1987 resctrl_io_alloc_closid_free(io_alloc_closid);
1988 }
1989
1990 ret = resctrl_arch_io_alloc_enable(r, enable);
1991 }
1992
1993 out_io_alloc:
1994 mutex_unlock(&rdtgroup_mutex);
1995 cpus_read_unlock();
1996
1997 return ret ?: nbytes;
1998 }
1999

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
#13 lore raw

Re: [PATCH v6 5/8] fs/resctrl: Add user interface to enable/disable io_alloc feature

In reply to Babu Moger
kernel test robot noticed the following build warnings:

Hi Babu,

kernel test robot noticed the following build warnings:

[auto build test WARNING on brauner-vfs/vfs.all]
[also build test WARNING on linus/master v6.16-rc1 next-20250612] [cannot apply to tip/x86/core aegl/next]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Babu-Moger/x86-cpufeatures-Add-support-for-L3-Smart-Data-Cache-Injection-Allocation-Enforcement/20250612-053050
base:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git vfs.all
patch link:    https://lore.kernel.org/r/b3d8e2ccd23b295f3735fc9f5420458cfc18a896.1749677012.git.babu.moger%40amd.com
patch subject: [PATCH v6 5/8] fs/resctrl: Add user interface to enable/disable io_alloc feature
config: i386-randconfig-061-20250613 (https://download.01.org/0day-ci/archive/20250613/[email protected]/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250613/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

sparse warnings: (new ones prefixed by >>)
fs/resctrl/rdtgroup.c: note: in included file:

>> include/linux/resctrl.h:553:46: sparse: sparse: marked inline, but without a definition
>> include/linux/resctrl.h:553:46: sparse: sparse: marked inline, but without a definition
>> include/linux/resctrl.h:553:46: sparse: sparse: marked inline, but without a definition
>> include/linux/resctrl.h:553:46: sparse: sparse: marked inline, but without a definition

vim +553 include/linux/resctrl.h

48e63934badb71 Babu Moger 2025-06-11  545  
48e63934badb71 Babu Moger 2025-06-11  546  /**
48e63934badb71 Babu Moger 2025-06-11  547   * resctrl_arch_get_io_alloc_enabled() - Get io_alloc feature state.
48e63934badb71 Babu Moger 2025-06-11  548   * @r:		The resctrl resource.
48e63934badb71 Babu Moger 2025-06-11  549   *
48e63934badb71 Babu Moger 2025-06-11  550   * Return:
48e63934badb71 Babu Moger 2025-06-11  551   * true if io_alloc is enabled or false if disabled.
48e63934badb71 Babu Moger 2025-06-11  552   */

48e63934badb71 Babu Moger 2025-06-11 @553 inline bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r); 48e63934badb71 Babu Moger 2025-06-11 554

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
maintainer
#14 lore raw

Re: [PATCH v6 5/8] fs/resctrl: Add user interface to enable/disable io_alloc feature

In reply to Babu Moger

Hi Babu,

Quoted 1 line · Babu Moger

The io_alloc feature in resctrl is a mechanism that enables direct

"The ... feature ... is a mechanism"? What does it mean when a feature is a mechanism? How about just "The io_alloc feature in resctrl enables ..."?

Quoted 1 line

insertion of data from I/O devices into the L3 cache.

Drop "L3"?

Quoted 8 lines

On AMD systems, io_alloc feature is backed by SDCIAE (L3 Smart Data Cache Injection Allocation Enforcement). When enabled, SDCIAE forces all SDCI lines to be placed into the L3 cache partitions identified by the highest-supported L3_MASK_n register as reported by CPUID Fn0000_0010_EDX_x1.MAX_COS. For example, if MAX_COS=15, SDCI lines will be allocated into the L3 cache partitions determined by the bitmask in the L3_MASK_15 register.

This is a resctrl fs patch but most of changelog so far is about AMD's implementation details. I do think it is relevant, but all the register details can probably be dropped since it is too low level to support the goal. I believe the goal here is to motivate resctrl fs's implementation that needs to pick highest CLOSID. So, essentially the changelog needs to hightlight that AMD's implementation requires highest CLOSID and without any other reference that is what resctrl fs's implementation supports. I think it is important to highlight that the user interface is not tied to this implementation decision to avoid future issues if another architecture support "io_alloc" "differently". Internals of resctrl fs can then be changed.

Quoted 3 lines

When CDP is enabled, io_alloc routes I/O traffic using the highest CLOSID allocated for the instruction cache (L3CODE).

Again, this is a resctrl fs patch and above is an AMD implementation detail. resctrl fs should not be limited by how AMD implements the feature but can use it as first reference.

Quoted 2 lines

Introduce user interface to enable/disable "io_alloc" feature.

This patch does more than this.

Quoted 3 lines

---

...

Quoted 3 lines
---
 Documentation/filesystems/resctrl.rst |  34 ++++
 fs/resctrl/rdtgroup.c                 | 216 +++++++++++++++++++++++++-

This patch contains several logical changes that are not adequately described in changelog.
I think the following can be separate patches:
- rdt_bit_usage_show() change
- io_alloc_init() definition and usage
- show() and write() helpers
- possibly the io_alloc_closid helpers (more later)

Documentation/filesystems/resctrl.rst related to allocation: · line 100

Quoted 13 lines
 2 files changed, 248 insertions(+), 2 deletions(-)
Documentation/filesystems/resctrl.rst +3 -0
index c7949dd44f2f..03c829b2c276 100644
@@ -95,6 +95,11 @@ related to allocation:
 		some platforms support devices that have their
 		own settings for cache use which can over-ride
 		these bits.
+
+		When the "io_alloc" feature is enabled, a portion of the cache
+		is reserved for shared use between hardware and software. Refer

"reserved" and "shared" sounds like a contradiction. How about "is reserved" -> "can be configured"?

Documentation/filesystems/resctrl.rst related to allocation: · line 101

Quoted 1 line
Documentation/filesystems/resctrl.rst +1 -0
+		to "bit_usage" to see which portion is allocated for this purpose.

This is the "shareable_bits" section and the reason why user is pointed to "bit_usage" is because "shareable_bits" is a global CBM that applies to all cache domains/instances while "bit_usage" is per cache domain/instance. I think it will be helpful to point this out to the user.
Perhaps second sentence can be replaced with something like:
""bit_usage" should be used to see which portions of each cache instance
is configured for hardware use via the "io_alloc" feature because every cache instance can have its "io_alloc" bitmask configured independently".

Please do improve this.

To complete this the first part of the "shareable_bits" doc can be amended:
"Bitmask of shareable resource" -> "Bitmask (applicable to all instances of this resource) of shareable resource" What do you think?

Documentation/filesystems/resctrl.rst related to allocation: · line 144

Quoted 10 lines
Documentation/filesystems/resctrl.rst +3 -0
+
 "bit_usage":
 		Annotated capacity bitmasks showing how all
 		instances of the resource are used. The legend is:
@@ -135,6 +140,35 @@ related to allocation:
 			"1":
 			      Non-contiguous 1s value in CBM is supported.
 
+"io_alloc":
+		The "io_alloc" enables system software to configure the portion

"The "io_alloc" enables"? Maybe just ""io_alloc" enables"?

Documentation/filesystems/resctrl.rst related to allocation: · line 145

Quoted 1 line
Documentation/filesystems/resctrl.rst +1 -0
+		of the L3 cache allocated for I/O traffic.

Drop "L3"?

Can append, for example, "File may only exist if the system supports this feature on some of its cache resources".

Documentation/filesystems/resctrl.rst related to allocation: · line 150

Quoted 5 lines
Documentation/filesystems/resctrl.rst +5 -0
+
+		The feature routes the I/O traffic via specific CLOSID reserved
+		for io_alloc feature. By configuring the CBM (Capacity Bit Mask)
+		for the CLOSID, users can control the L3 portions available for
+		I/0 traffic. The reserved CLOSID will be excluded for group creation.

Looking back I've commented *four* times already about how resctrl fs user interface should not be made specific to AMD's implementation.
This paragraph just be dropped?

The rest can be something like:

"disabled": Portions of cache used for allocation of I/O traffic cannot be configured. "enabled": Portions of cache used for allocation of I/O traffic can be configured using "io_alloc_cbm" "not supported": ...

The underlying implementation may reduce resources available to general (CPU) cache allocation. See architecture specific notes below. Depending on usage requirements the feature can be enabled or disabled:

To enable:
# echo 1 > /sys/fs/resctrl/info/L3/io_alloc

To disable:
# echo 0 > /sys/fs/resctrl/info/L3/io_alloc

Quoted 57 lines
Documentation/filesystems/resctrl.rst +21 -0
+
+		The interface provides a means to query the status of the feature.
+
+		Example::
+
+			# cat /sys/fs/resctrl/info/L3/io_alloc
+			disabled
+
+		Feature can be enabled/disabled by writing to the interface.
+		Example::
+
+			# echo 1 > /sys/fs/resctrl/info/L3/io_alloc
+			# cat /sys/fs/resctrl/info/L3/io_alloc
+			enabled
+
+		On AMD systems, the io_alloc feature is supported by the L3 Smart
+		Data Cache Injection Allocation Enforcement (SDCIAE). The CLOSID for
+		io_alloc is determined by the highest CLOSID supported by the resource.
+		When CDP is enabled, io_alloc routes I/O traffic using the highest
+		CLOSID allocated for the instruction cache (L3CODE).
+
 Memory bandwidth(MB) subdirectory contains the following files
 with respect to allocation:
 
fs/resctrl/rdtgroup.c +14 -0
index 1beb124e25f6..bbc032b4d0e9 100644
@@ -70,6 +70,7 @@ static struct seq_buf last_cmd_status;
 static char last_cmd_status_buf[512];
 
 static int rdtgroup_setup_root(struct rdt_fs_context *ctx);
+static int rdtgroup_init_cat(struct resctrl_schema *s, u32 closid);
 
 static void rdtgroup_destroy_root(void);
 
@@ -232,6 +233,19 @@ bool closid_allocated(unsigned int closid)
 	return !test_bit(closid, closid_free_map);
 }
 
+static int resctrl_io_alloc_closid_alloc(u32 io_alloc_closid)
+{
+	if (__test_and_clear_bit(io_alloc_closid, closid_free_map))
+		return io_alloc_closid;
+	else
+		return -ENOSPC;
+}
+
+static void resctrl_io_alloc_closid_free(u32 io_alloc_closid)
+{
+	closid_free(io_alloc_closid);
+}
+
 /**
  * rdtgroup_mode_by_closid - Return mode of resource group with closid
  * @closid: closid if the resource group

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

Quoted 6 lines
fs/resctrl/rdtgroup.c +3 -0
@@ -1030,6 +1044,29 @@ static int rdt_shareable_bits_show(struct kernfs_open_file *of,
 	return 0;
 }
 
+/*
+ * resctrl_io_alloc_closid_get - io_alloc feature uses max CLOSID to route
+ * the IO traffic. Get the max CLOSID and verify if the CLOSID is available.

The function name should be followed by a *brief* description.

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

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+ *
+ * The total number of CLOSIDs is determined in closid_init(),  based on the
+ * minimum supported across all resources. If CDP (Code Data Prioritization)
+ * is enabled, the number of CLOSIDs is halved. The final value is returned
+ * by closids_supported(). Make sure this value aligns with the maximum
+ * CLOSID supported by the respective resource.

All but the last sentence is unrelated to this function and the last sentence is very vague. What is "this value" that it refers to?

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

Quoted 13 lines
fs/resctrl/rdtgroup.c +13 -0
+ */
+static int resctrl_io_alloc_closid_get(struct rdt_resource *r)
+{
+	int num_closids = closids_supported();
+
+	if (resctrl_arch_get_cdp_enabled(r->rid))
+		num_closids *= 2;
+
+	if (num_closids != resctrl_arch_get_num_closid(r))
+		return -ENOSPC;
+
+	return closids_supported() - 1;
+}

resctrl_io_alloc_closid_get() seems to be trying to do two things:
- determine what the io_alloc_closid is
- make sure the io_alloc_closid is supported

I think this should be split into two functions. Once the io_alloc_closid is determined to be supported and io_alloc enabled then there is no reason to keep checking if it is supported whenever the io_alloc_closid is queried.

How about simplifying this to:

/*
* note how this returns u32 that will eliminate
* unnecessary error checking in usages where io_alloc_closid
* needs to be determined after an resctrl_arch_get_io_alloc_enabled(r)
* already confirmed io_alloc is enabled
* function comment could note that this returns the CLOSID
* required by io_alloc but not whether the CLOSID can
* be supported, for this resctrl_io_alloc_closid_supported() should
* be used.
* Can also note that returned value will always be valid if
* resctrl_arch_get_io_alloc_enabled(r) is true.
*/
u32 resctrl_io_alloc_closid(struct rdt_resource *r) {
if (resctrl_arch_get_cdp_enabled(r->rid))
return resctrl_arch_get_num_closid(r)/2 - 1
else
return resctrl_arch_get_num_closid(r) -1
}

/*
* note how below already makes resctrl's io_alloc implementation
* more generic
*/
resctrl_io_alloc_closid_supported(u32 io_alloc_closid) {
return io_alloc_closid < closids_supported()
}

Quoted 31 lines
fs/resctrl/rdtgroup.c +6 -2
+
 /*
  * rdt_bit_usage_show - Display current usage of resources
  *
@@ -1058,20 +1095,23 @@ static int rdt_bit_usage_show(struct kernfs_open_file *of,
 	struct rdt_ctrl_domain *dom;
 	int i, hwb, swb, excl, psl;
 	enum rdtgrp_mode mode;
+	int io_alloc_closid;
 	bool sep = false;
 	u32 ctrl_val;
 
 	cpus_read_lock();
 	mutex_lock(&rdtgroup_mutex);
-	hw_shareable = r->cache.shareable_bits;
 	list_for_each_entry(dom, &r->ctrl_domains, hdr.list) {
 		if (sep)
 			seq_putc(seq, ';');
+		hw_shareable = r->cache.shareable_bits;
 		sw_shareable = 0;
 		exclusive = 0;
 		seq_printf(seq, "%d=", dom->hdr.id);
 		for (i = 0; i < closids_supported(); i++) {
-			if (!closid_allocated(i))
+			if (!closid_allocated(i) ||
+			    (resctrl_arch_get_io_alloc_enabled(r) &&
+			     i == resctrl_io_alloc_closid_get(r)))
 				continue;
 			ctrl_val = resctrl_arch_get_config(r, dom, i,
 							   s->conf_type);

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

Quoted 10 lines
fs/resctrl/rdtgroup.c +7 -0
@@ -1099,6 +1139,24 @@ static int rdt_bit_usage_show(struct kernfs_open_file *of,
 				break;
 			}
 		}
+
+		/*
+		 * When the "io_alloc" feature is enabled, a portion of the
+		 * cache is reserved for shared use between hardware and software.
+		 */
+		if (resctrl_arch_get_io_alloc_enabled(r)) {
+			io_alloc_closid = resctrl_io_alloc_closid_get(r);

In this implementation io_alloc_closid can be negative and the static checker I used complained about the subsequent usage in resctrl_arch_get_config() that must be unsigned.
Since resctrl_arch_get_io_alloc_enabled(r) already passed this is one example where resctrl_io_alloc_closid() can be used.

Quoted 15 lines
fs/resctrl/rdtgroup.c +11 -0
+			if (resctrl_arch_get_cdp_enabled(r->rid))
+				ctrl_val = resctrl_arch_get_config(r, dom,
+								   io_alloc_closid,
+								   CDP_CODE);
+			else
+				ctrl_val = resctrl_arch_get_config(r, dom,
+								   io_alloc_closid,
+								   CDP_NONE);
+			hw_shareable |= ctrl_val;
+		}
+
 		for (i = r->cache.cbm_len - 1; i >= 0; i--) {
 			pseudo_locked = dom->plr ? dom->plr->cbm : 0;
 			hwb = test_bit(i, &hw_shareable);

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1869

Quoted 9 lines
fs/resctrl/rdtgroup.c +6 -0
@@ -1803,6 +1861,142 @@ static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of,
 	return ret ?: nbytes;
 }
 
+static int resctrl_io_alloc_show(struct kernfs_open_file *of,
+				 struct seq_file *seq, void *v)
+{
+	struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+	struct rdt_resource *r = s->res;
+

Needs rdtgroup_mutex

Quoted 4 lines
fs/resctrl/rdtgroup.c +4 -0
+	if (r->cache.io_alloc_capable) {
+		if (resctrl_arch_get_io_alloc_enabled(r))
+			seq_puts(seq, "enabled\n");
+		else

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1883

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+			seq_puts(seq, "disabled\n");
+	} else {
+		seq_puts(seq, "not supported\n");
+	}
+
+	return 0;
+}
+
+/*
+ * Initialize io_alloc CLOSID cache resource with default CBM values.

It is unclear what "default" means.
Could be "Initialize io_alloc CLOSID cache resource CBM with all usable (shared and unused) cache portions".

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1894

Quoted 11 lines
fs/resctrl/rdtgroup.c +11 -0
+ */
+static int resctrl_io_alloc_init_cat(struct rdt_resource *r,
+				     struct resctrl_schema *s, u32 closid)
+{
+	int ret;
+
+	rdt_staged_configs_clear();
+
+	ret = rdtgroup_init_cat(s, closid);
+	if (ret < 0)
+		goto out_init_cat;

The "out" label should reflect what is done at target, not the source. Consider all the usages of "out_unlock" in resctrl.
Since this is the only label it can just be "out".

Quoted 16 lines
fs/resctrl/rdtgroup.c +16 -0
+
+	ret = resctrl_arch_update_domains(r, closid);
+
+out_init_cat:
+	rdt_staged_configs_clear();
+	return ret;
+}
+
+static const char *rdtgroup_name_by_closid(int closid)
+{
+	struct rdtgroup *rdtgrp;
+
+	list_for_each_entry(rdtgrp, &rdt_all_groups, rdtgroup_list) {
+		if (rdtgrp->closid == closid)
+			return rdt_kn_name(rdtgrp->kn);
+	}

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1920

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+
+	return NULL;
+}
+
+/*
+ * When CDP is enabled, io_alloc directs traffic using the highest CLOSID
+ * linked to an L3CODE resource. Although CBMs can be accessed through
+ * either L3CODE or L3DATA resources, any updates to the schemata must
+ * always be performed on L3CODE.
+ */

I think that updates to the schemata needs to be made on *both* L3DATA and L3CODE. Consider how __init_one_rdt_domain() works when a new resource group is created ... the algorithm looks through all allocated CLOSID and the associated schemata impact the CBM of the new group. If an allocated CLOSID is associated with L3CODE then its "peer" L3DATA is also taken into account, similar for L3DATA. If only L3CODE is updated for the io_alloc_closid then it looks to me that whatever the original L3DATA schema was will keep impacting new resource groups. To avoid that and ensure only accurate CBMs are used it looks to me as though the L3DATA and L3CODE schema needs to be kept in sync.

Quoted 25 lines
fs/resctrl/rdtgroup.c +25 -0
+static struct resctrl_schema *resctrl_schema_io_alloc(struct resctrl_schema *s)
+{
+	struct resctrl_schema *schema;
+
+	if (s->conf_type == CDP_DATA) {
+		list_for_each_entry(schema, &resctrl_schema_all, list) {
+			if (schema->conf_type == CDP_CODE)
+				return schema;
+		}
+	}
+
+	return s;
+}
+
+static ssize_t resctrl_io_alloc_write(struct kernfs_open_file *of, char *buf,
+				      size_t nbytes, loff_t off)
+{
+	struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+	struct rdt_resource *r = s->res;
+	char const *grp_name;
+	u32 io_alloc_closid;
+	bool enable;
+	int ret;
+
+	ret = kstrtobool(buf, &enable);

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1955

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+	if (ret)
+		return ret;
+
+	cpus_read_lock();
+	mutex_lock(&rdtgroup_mutex);
+
+	rdt_last_cmd_clear();
+
+	if (!r->cache.io_alloc_capable) {
+		rdt_last_cmd_puts("io_alloc feature is not supported on the resource\n");

This could be more useful with a small change:
"io_alloc is not supported on %s\n", s->name

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1957

Quoted 2 lines
fs/resctrl/rdtgroup.c +2 -0
+		ret = -ENODEV;
+		goto out_io_alloc;

out_io_alloc -> out_unlock

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1962

Quoted 5 lines
fs/resctrl/rdtgroup.c +5 -0
+	}
+
+	io_alloc_closid = resctrl_io_alloc_closid_get(r);
+	if (io_alloc_closid < 0) {
+		rdt_last_cmd_puts("Max CLOSID to support io_alloc is not available\n");

This could be more useful to help debug by printing the value of io_alloc_closid that user can compare against output of num_closids files. Here the terms become a bit complicated since ideally we want to use ctrl_hw_id but that does not match "num_closids", so perhaps use both terms, for example "CLOSID (ctrl_hw_id)"? I am not sure here.

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1971

Quoted 9 lines
fs/resctrl/rdtgroup.c +9 -0
+		ret = -EINVAL;
+		goto out_io_alloc;
+	}
+
+	if (resctrl_arch_get_io_alloc_enabled(r) != enable) {
+		if (enable) {
+			ret = resctrl_io_alloc_closid_alloc(io_alloc_closid);
+			if (ret < 0) {
+				grp_name = rdtgroup_name_by_closid(io_alloc_closid);

Below handles !grp_name but that would be a kernel bug, no? Maybe WARN_ON_ONCE()?

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1973

Quoted 2 lines
fs/resctrl/rdtgroup.c +2 -0
+				rdt_last_cmd_printf("CLOSID for io_alloc is used by %s group\n",
+						    grp_name ? grp_name : "another");

CLOSID -> ctrl_hw_id

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+				ret = -EINVAL;
+				goto out_io_alloc;
+			}
+
+			ret = resctrl_io_alloc_init_cat(r, resctrl_schema_io_alloc(s),
+							io_alloc_closid);
+			if (ret) {
+				rdt_last_cmd_puts("Failed to initialize io_alloc allocations\n");
+				resctrl_io_alloc_closid_free(io_alloc_closid);
+				goto out_io_alloc;

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1993

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+			}
+
+		} else {
+			resctrl_io_alloc_closid_free(io_alloc_closid);
+		}
+
+		ret = resctrl_arch_io_alloc_enable(r, enable);
+	}
+
+out_io_alloc:

out_unlock ... to match the other places in resctrl.

Quoted 10 lines
fs/resctrl/rdtgroup.c +6 -0
+	mutex_unlock(&rdtgroup_mutex);
+	cpus_read_unlock();
+
+	return ret ?: nbytes;
+}
+
 /* rdtgroup information files for one cache resource. */
 static struct rftype res_common_files[] = {
 	{

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

Quoted 10 lines
fs/resctrl/rdtgroup.c +7 -0
@@ -1955,6 +2149,13 @@ static struct rftype res_common_files[] = {
 		.seq_show	= rdtgroup_schemata_show,
 		.fflags		= RFTYPE_CTRL_BASE,
 	},
+	{
+		.name           = "io_alloc",
+		.mode           = 0644,
+		.kf_ops         = &rdtgroup_kf_single_ops,
+		.seq_show       = resctrl_io_alloc_show,
+		.write          = resctrl_io_alloc_write,
+	},

Please match existing code wrt tab usage.

Quoted 5 lines
fs/resctrl/rdtgroup.c +0 -0
 	{
 		.name		= "mba_MBps_event",
 		.mode		= 0644,
@@ -2062,6 +2263,15 @@ static void thread_throttle_mode_init(void)
 				 RFTYPE_CTRL_INFO | RFTYPE_RES_MB);

fs/resctrl/rdtgroup.c static void thread_throttle_mode_init(void) · line 2273

Quoted 10 lines
fs/resctrl/rdtgroup.c +8 -0
 }
 
+static void io_alloc_init(void)
+{
+	struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
+
+	if (r->cache.io_alloc_capable)
+		resctrl_file_fflags_init("io_alloc",
+					 RFTYPE_CTRL_INFO | RFTYPE_RES_CACHE);
+}

Note that even if it only checks the L3 cache resource, this will make the file visible to all cache resource, also L2. This is why it is important to ensure documentation and implementation also accommodates resources that do not support io_alloc.

fs/resctrl/rdtgroup.c int resctrl_init(void) · line 4466

Quoted 13 lines
fs/resctrl/rdtgroup.c +3 -0
+
 void resctrl_file_fflags_init(const char *config, unsigned long fflags)
 {
 	struct rftype *rft;
@@ -4249,6 +4459,8 @@ int resctrl_init(void)
 
 	thread_throttle_mode_init();
 
+	io_alloc_init();
+
 	ret = resctrl_mon_resource_init();
 	if (ret)
 		return ret;

Reinette

author reviewer
#15 lore raw

Re: [PATCH v6 5/8] fs/resctrl: Add user interface to enable/disable io_alloc feature

Hi Reinette,

Quoted 7 lines · Reinette Chatre

Hi Babu,

Quoted 1 line · Babu Moger

The io_alloc feature in resctrl is a mechanism that enables direct

"The ... feature ... is a mechanism"? What does it mean when a feature is a mechanism? How about just "The io_alloc feature in resctrl enables ..."?

Sure.

Quoted 5 lines
Quoted 2 lines

insertion of data from I/O devices into the L3 cache.

Drop "L3"?

Sure.

Quoted 9 lines
Quoted 8 lines

On AMD systems, io_alloc feature is backed by SDCIAE (L3 Smart Data Cache Injection Allocation Enforcement). When enabled, SDCIAE forces all SDCI lines to be placed into the L3 cache partitions identified by the highest-supported L3_MASK_n register as reported by CPUID Fn0000_0010_EDX_x1.MAX_COS. For example, if MAX_COS=15, SDCI lines will be allocated into the L3 cache partitions determined by the bitmask in the L3_MASK_15 register.

Quoted 11 lines

This is a resctrl fs patch but most of changelog so far is about AMD's implementation details. I do think it is relevant, but all the register details can probably be dropped since it is too low level to support the goal. I believe the goal here is to motivate resctrl fs's implementation that needs to pick highest CLOSID. So, essentially the changelog needs to hightlight that AMD's implementation requires highest CLOSID and without any other reference that is what resctrl fs's implementation supports. I think it is important to highlight that the user interface is not tied to this implementation decision to avoid future issues if another architecture support "io_alloc" "differently". Internals of resctrl fs can then be changed.

Sure. Will split these patches. Will try make the text more generic.

Quoted 7 lines
Quoted 3 lines

When CDP is enabled, io_alloc routes I/O traffic using the highest CLOSID allocated for the instruction cache (L3CODE).

Again, this is a resctrl fs patch and above is an AMD implementation detail. resctrl fs should not be limited by how AMD implements the feature but can use it as first reference.

Sure.

Quoted 5 lines
Quoted 3 lines

Introduce user interface to enable/disable "io_alloc" feature.

This patch does more than this.

Sure.

Quoted 10 lines
Quoted 4 lines

---

...

Quoted 3 lines
---
 Documentation/filesystems/resctrl.rst |  34 ++++
 fs/resctrl/rdtgroup.c                 | 216 +++++++++++++++++++++++++-
Quoted 7 lines

This patch contains several logical changes that are not adequately described in changelog.
I think the following can be separate patches:
- rdt_bit_usage_show() change
- io_alloc_init() definition and usage
- show() and write() helpers
- possibly the io_alloc_closid helpers (more later)

Yes. Splitting this into 3 patches.
1. rdt_bit_usage_show() change
Updates shareable_bits section.
It calls - resctrl_io_alloc_closid().

2. io_alloc_init() definition and usage
Introdce the inteface and add show()

3. Add io_alloc write().
Calls resctrl_io_alloc_closid_supported() and
resctrl_io_alloc_closid_get().

Quoted 18 lines
Quoted 8 lines
 2 files changed, 248 insertions(+), 2 deletions(-)
Documentation/filesystems/resctrl.rst +0 -0
index c7949dd44f2f..03c829b2c276 100644

Documentation/filesystems/resctrl.rst related to allocation: · line 100

Quoted 6 lines
Documentation/filesystems/resctrl.rst +3 -0
@@ -95,6 +95,11 @@ related to allocation:
 		some platforms support devices that have their
 		own settings for cache use which can over-ride
 		these bits.
+
+		When the "io_alloc" feature is enabled, a portion of the cache
+		is reserved for shared use between hardware and software. Refer

"reserved" and "shared" sounds like a contradiction. How about "is reserved" -> "can be configured"?

Quoted 10 lines

Documentation/filesystems/resctrl.rst related to allocation: · line 101

Quoted 1 line
Documentation/filesystems/resctrl.rst +1 -0
+		to "bit_usage" to see which portion is allocated for this purpose.

This is the "shareable_bits" section and the reason why user is pointed to "bit_usage" is because "shareable_bits" is a global CBM that applies to all cache domains/instances while "bit_usage" is per cache domain/instance. I think it will be helpful to point this out to the user.
Perhaps second sentence can be replaced with something like:
""bit_usage" should be used to see which portions of each cache instance
is configured for hardware use via the "io_alloc" feature because every cache instance can have its "io_alloc" bitmask configured independently".

Sure.

""bit_usage" should be used to see which portions of each cache instance is configured for hardware use via the "io_alloc" feature because every cache instance can have its "io_alloc" bitmask configured independently.

Quoted 6 lines

Please do improve this.

To complete this the first part of the "shareable_bits" doc can be amended:
"Bitmask of shareable resource" -> "Bitmask (applicable to all instances of this resource) of shareable resource" What do you think?

Sure. Added one sentance for that.

Bitmask of shareable resource with other executing entities (e.g. I/O). Applies to all instances of this resource.

Quoted 42 lines

Documentation/filesystems/resctrl.rst related to allocation: · line 144

Quoted 11 lines
Documentation/filesystems/resctrl.rst +3 -0
+
 "bit_usage":
 		Annotated capacity bitmasks showing how all
 		instances of the resource are used. The legend is:
@@ -135,6 +140,35 @@ related to allocation:
 			"1":
 			      Non-contiguous 1s value in CBM is supported.
 
+"io_alloc":
+		The "io_alloc" enables system software to configure the portion

"The "io_alloc" enables"? Maybe just ""io_alloc" enables"?

Documentation/filesystems/resctrl.rst related to allocation: · line 145

Quoted 1 line
Documentation/filesystems/resctrl.rst +1 -0
+		of the L3 cache allocated for I/O traffic.

Drop "L3"?

Can append, for example, "File may only exist if the system supports this feature on some of its cache resources".

Documentation/filesystems/resctrl.rst related to allocation: · line 150

Quoted 5 lines
Documentation/filesystems/resctrl.rst +5 -0
+
+		The feature routes the I/O traffic via specific CLOSID reserved
+		for io_alloc feature. By configuring the CBM (Capacity Bit Mask)
+		for the CLOSID, users can control the L3 portions available for
+		I/0 traffic. The reserved CLOSID will be excluded for group creation.

Looking back I've commented *four* times already about how resctrl fs user interface should not be made specific to AMD's implementation.
This paragraph just be dropped?

The rest can be something like:

"disabled": Portions of cache used for allocation of I/O traffic cannot be configured. "enabled": Portions of cache used for allocation of I/O traffic can be configured using "io_alloc_cbm" "not supported": ...

The underlying implementation may reduce resources available to general (CPU) cache allocation. See architecture specific notes below. Depending on usage requirements the feature can be enabled or disabled:

Quoted 5 lines

To enable:
# echo 1 > /sys/fs/resctrl/info/L3/io_alloc

To disable:
# echo 0 > /sys/fs/resctrl/info/L3/io_alloc

Sure.

Quoted 61 lines
Quoted 61 lines
Documentation/filesystems/resctrl.rst +21 -0
+
+		The interface provides a means to query the status of the feature.
+
+		Example::
+
+			# cat /sys/fs/resctrl/info/L3/io_alloc
+			disabled
+
+		Feature can be enabled/disabled by writing to the interface.
+		Example::
+
+			# echo 1 > /sys/fs/resctrl/info/L3/io_alloc
+			# cat /sys/fs/resctrl/info/L3/io_alloc
+			enabled
+
+		On AMD systems, the io_alloc feature is supported by the L3 Smart
+		Data Cache Injection Allocation Enforcement (SDCIAE). The CLOSID for
+		io_alloc is determined by the highest CLOSID supported by the resource.
+		When CDP is enabled, io_alloc routes I/O traffic using the highest
+		CLOSID allocated for the instruction cache (L3CODE).
+
 Memory bandwidth(MB) subdirectory contains the following files
 with respect to allocation:
 
fs/resctrl/rdtgroup.c +14 -0
index 1beb124e25f6..bbc032b4d0e9 100644
@@ -70,6 +70,7 @@ static struct seq_buf last_cmd_status;
 static char last_cmd_status_buf[512];
 
 static int rdtgroup_setup_root(struct rdt_fs_context *ctx);
+static int rdtgroup_init_cat(struct resctrl_schema *s, u32 closid);
 
 static void rdtgroup_destroy_root(void);
 
@@ -232,6 +233,19 @@ bool closid_allocated(unsigned int closid)
 	return !test_bit(closid, closid_free_map);
 }
 
+static int resctrl_io_alloc_closid_alloc(u32 io_alloc_closid)
+{
+	if (__test_and_clear_bit(io_alloc_closid, closid_free_map))
+		return io_alloc_closid;
+	else
+		return -ENOSPC;
+}
+
+static void resctrl_io_alloc_closid_free(u32 io_alloc_closid)
+{
+	closid_free(io_alloc_closid);
+}
+
 /**
  * rdtgroup_mode_by_closid - Return mode of resource group with closid
  * @closid: closid if the resource group
@@ -1030,6 +1044,29 @@ static int rdt_shareable_bits_show(struct kernfs_open_file *of,
 	return 0;
 }
 
Quoted 5 lines

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

Quoted 3 lines
fs/resctrl/rdtgroup.c +3 -0
+/*
+ * resctrl_io_alloc_closid_get - io_alloc feature uses max CLOSID to route
+ * the IO traffic. Get the max CLOSID and verify if the CLOSID is available.

The function name should be followed by a *brief* description.

Sure.

Quoted 10 lines

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

Quoted 7 lines
fs/resctrl/rdtgroup.c +6 -0
+ *
+ * The total number of CLOSIDs is determined in closid_init(),  based on the
+ * minimum supported across all resources. If CDP (Code Data Prioritization)
+ * is enabled, the number of CLOSIDs is halved. The final value is returned
+ * by closids_supported(). Make sure this value aligns with the maximum
+ * CLOSID supported by the respective resource.

All but the last sentence is unrelated to this function and the last sentence is very vague. What is "this value" that it refers to?

Removed it.

Quoted 45 lines
Quoted 4 lines
fs/resctrl/rdtgroup.c +3 -0
+ */
+static int resctrl_io_alloc_closid_get(struct rdt_resource *r)
+{

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

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+	int num_closids = closids_supported();
+
+	if (resctrl_arch_get_cdp_enabled(r->rid))
+		num_closids *= 2;
+
+	if (num_closids != resctrl_arch_get_num_closid(r))
+		return -ENOSPC;
+
+	return closids_supported() - 1;
+}

resctrl_io_alloc_closid_get() seems to be trying to do two things:
- determine what the io_alloc_closid is
- make sure the io_alloc_closid is supported

I think this should be split into two functions. Once the io_alloc_closid is determined to be supported and io_alloc enabled then there is no reason to keep checking if it is supported whenever the io_alloc_closid is queried.

How about simplifying this to:

/*
* note how this returns u32 that will eliminate
* unnecessary error checking in usages where io_alloc_closid
* needs to be determined after an resctrl_arch_get_io_alloc_enabled(r)
* already confirmed io_alloc is enabled
* function comment could note that this returns the CLOSID
* required by io_alloc but not whether the CLOSID can
* be supported, for this resctrl_io_alloc_closid_supported() should
* be used.
* Can also note that returned value will always be valid if
* resctrl_arch_get_io_alloc_enabled(r) is true.
*/
u32 resctrl_io_alloc_closid(struct rdt_resource *r) {
if (resctrl_arch_get_cdp_enabled(r->rid))
return resctrl_arch_get_num_closid(r)/2 - 1
else
return resctrl_arch_get_num_closid(r) -1
}

Quoted 8 lines

/*
* note how below already makes resctrl's io_alloc implementation
* more generic
*/
resctrl_io_alloc_closid_supported(u32 io_alloc_closid) {
return io_alloc_closid < closids_supported()
}

Sure.
Changed the check to

    return io_alloc_closid == (closids_supported() -1)
Quoted 41 lines
Quoted 41 lines
fs/resctrl/rdtgroup.c +11 -2
+
 /*
  * rdt_bit_usage_show - Display current usage of resources
  *
@@ -1058,20 +1095,23 @@ static int rdt_bit_usage_show(struct kernfs_open_file *of,
 	struct rdt_ctrl_domain *dom;
 	int i, hwb, swb, excl, psl;
 	enum rdtgrp_mode mode;
+	int io_alloc_closid;
 	bool sep = false;
 	u32 ctrl_val;
 
 	cpus_read_lock();
 	mutex_lock(&rdtgroup_mutex);
-	hw_shareable = r->cache.shareable_bits;
 	list_for_each_entry(dom, &r->ctrl_domains, hdr.list) {
 		if (sep)
 			seq_putc(seq, ';');
+		hw_shareable = r->cache.shareable_bits;
 		sw_shareable = 0;
 		exclusive = 0;
 		seq_printf(seq, "%d=", dom->hdr.id);
 		for (i = 0; i < closids_supported(); i++) {
-			if (!closid_allocated(i))
+			if (!closid_allocated(i) ||
+			    (resctrl_arch_get_io_alloc_enabled(r) &&
+			     i == resctrl_io_alloc_closid_get(r)))
 				continue;
 			ctrl_val = resctrl_arch_get_config(r, dom, i,
 							   s->conf_type);
@@ -1099,6 +1139,24 @@ static int rdt_bit_usage_show(struct kernfs_open_file *of,
 				break;
 			}
 		}
+
+		/*
+		 * When the "io_alloc" feature is enabled, a portion of the
+		 * cache is reserved for shared use between hardware and software.
+		 */
Quoted 8 lines

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

Quoted 2 lines
fs/resctrl/rdtgroup.c +2 -0
+		if (resctrl_arch_get_io_alloc_enabled(r)) {
+			io_alloc_closid = resctrl_io_alloc_closid_get(r);

In this implementation io_alloc_closid can be negative and the static checker I used complained about the subsequent usage in resctrl_arch_get_config() that must be unsigned.
Since resctrl_arch_get_io_alloc_enabled(r) already passed this is one example where resctrl_io_alloc_closid() can be used.

Sure.

Quoted 19 lines
Quoted 19 lines
fs/resctrl/rdtgroup.c +11 -0
+			if (resctrl_arch_get_cdp_enabled(r->rid))
+				ctrl_val = resctrl_arch_get_config(r, dom,
+								   io_alloc_closid,
+								   CDP_CODE);
+			else
+				ctrl_val = resctrl_arch_get_config(r, dom,
+								   io_alloc_closid,
+								   CDP_NONE);
+			hw_shareable |= ctrl_val;
+		}
+
 		for (i = r->cache.cbm_len - 1; i >= 0; i--) {
 			pseudo_locked = dom->plr ? dom->plr->cbm : 0;
 			hwb = test_bit(i, &hw_shareable);
@@ -1803,6 +1861,142 @@ static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of,
 	return ret ?: nbytes;
 }
 
Quoted 8 lines

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1869

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+static int resctrl_io_alloc_show(struct kernfs_open_file *of,
+				 struct seq_file *seq, void *v)
+{
+	struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+	struct rdt_resource *r = s->res;
+

Needs rdtgroup_mutex

Sure.

Quoted 10 lines
Quoted 10 lines
fs/resctrl/rdtgroup.c +9 -0
+	if (r->cache.io_alloc_capable) {
+		if (resctrl_arch_get_io_alloc_enabled(r))
+			seq_puts(seq, "enabled\n");
+		else
+			seq_puts(seq, "disabled\n");
+	} else {
+		seq_puts(seq, "not supported\n");
+	}
+
Quoted 8 lines

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1883

Quoted 5 lines
fs/resctrl/rdtgroup.c +5 -0
+	return 0;
+}
+
+/*
+ * Initialize io_alloc CLOSID cache resource with default CBM values.

It is unclear what "default" means.
Could be "Initialize io_alloc CLOSID cache resource CBM with all usable (shared and unused) cache portions".

Sure.

Quoted 16 lines

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1894

Quoted 12 lines
fs/resctrl/rdtgroup.c +11 -0
+ */
+static int resctrl_io_alloc_init_cat(struct rdt_resource *r,
+				     struct resctrl_schema *s, u32 closid)
+{
+	int ret;
+
+	rdt_staged_configs_clear();
+
+	ret = rdtgroup_init_cat(s, closid);
+	if (ret < 0)
+		goto out_init_cat;

The "out" label should reflect what is done at target, not the source. Consider all the usages of "out_unlock" in resctrl.
Since this is the only label it can just be "out".

Sure.

Quoted 29 lines
Quoted 17 lines
fs/resctrl/rdtgroup.c +16 -0
+
+	ret = resctrl_arch_update_domains(r, closid);
+
+out_init_cat:
+	rdt_staged_configs_clear();
+	return ret;
+}
+
+static const char *rdtgroup_name_by_closid(int closid)
+{
+	struct rdtgroup *rdtgrp;
+
+	list_for_each_entry(rdtgrp, &rdt_all_groups, rdtgroup_list) {
+		if (rdtgrp->closid == closid)
+			return rdt_kn_name(rdtgrp->kn);
+	}

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1920

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+
+	return NULL;
+}
+
+/*
+ * When CDP is enabled, io_alloc directs traffic using the highest CLOSID
+ * linked to an L3CODE resource. Although CBMs can be accessed through
+ * either L3CODE or L3DATA resources, any updates to the schemata must
+ * always be performed on L3CODE.
+ */

I think that updates to the schemata needs to be made on *both* L3DATA and L3CODE.

Quoted 8 lines

Consider how __init_one_rdt_domain() works when a new resource group is created ... the algorithm looks through all allocated CLOSID and the associated schemata impact the CBM of the new group. If an allocated CLOSID is associated with L3CODE then its "peer" L3DATA is also taken into account, similar for L3DATA. If only L3CODE is updated for the io_alloc_closid then it looks to me that whatever the original L3DATA schema was will keep impacting new resource groups. To avoid that and ensure only accurate CBMs are used it looks to me as though the L3DATA and L3CODE schema needs to be kept in sync.

Sure. Will verify this.

Quoted 31 lines
Quoted 31 lines
fs/resctrl/rdtgroup.c +30 -0
+static struct resctrl_schema *resctrl_schema_io_alloc(struct resctrl_schema *s)
+{
+	struct resctrl_schema *schema;
+
+	if (s->conf_type == CDP_DATA) {
+		list_for_each_entry(schema, &resctrl_schema_all, list) {
+			if (schema->conf_type == CDP_CODE)
+				return schema;
+		}
+	}
+
+	return s;
+}
+
+static ssize_t resctrl_io_alloc_write(struct kernfs_open_file *of, char *buf,
+				      size_t nbytes, loff_t off)
+{
+	struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+	struct rdt_resource *r = s->res;
+	char const *grp_name;
+	u32 io_alloc_closid;
+	bool enable;
+	int ret;
+
+	ret = kstrtobool(buf, &enable);
+	if (ret)
+		return ret;
+
+	cpus_read_lock();
+	mutex_lock(&rdtgroup_mutex);
Quoted 8 lines

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1955

Quoted 5 lines
fs/resctrl/rdtgroup.c +5 -0
+
+	rdt_last_cmd_clear();
+
+	if (!r->cache.io_alloc_capable) {
+		rdt_last_cmd_puts("io_alloc feature is not supported on the resource\n");

This could be more useful with a small change:
"io_alloc is not supported on %s\n", s->name

Yes.

Quoted 5 lines

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1957

Quoted 3 lines
fs/resctrl/rdtgroup.c +2 -0
+		ret = -ENODEV;
+		goto out_io_alloc;

out_io_alloc -> out_unlock

Sure.

Quoted 12 lines

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1962

Quoted 6 lines
fs/resctrl/rdtgroup.c +5 -0
+	}
+
+	io_alloc_closid = resctrl_io_alloc_closid_get(r);
+	if (io_alloc_closid < 0) {
+		rdt_last_cmd_puts("Max CLOSID to support io_alloc is not available\n");

This could be more useful to help debug by printing the value of io_alloc_closid that user can compare against output of num_closids files. Here the terms become a bit complicated since ideally we want to use ctrl_hw_id but that does not match "num_closids", so perhaps use both terms, for example "CLOSID (ctrl_hw_id)"? I am not sure here.

Fine with me.

Quoted 12 lines

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1971

Quoted 10 lines
fs/resctrl/rdtgroup.c +9 -0
+		ret = -EINVAL;
+		goto out_io_alloc;
+	}
+
+	if (resctrl_arch_get_io_alloc_enabled(r) != enable) {
+		if (enable) {
+			ret = resctrl_io_alloc_closid_alloc(io_alloc_closid);
+			if (ret < 0) {
+				grp_name = rdtgroup_name_by_closid(io_alloc_closid);

Below handles !grp_name but that would be a kernel bug, no? Maybe WARN_ON_ONCE()?

Sure.

Quoted 7 lines

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1973

Quoted 3 lines
fs/resctrl/rdtgroup.c +2 -0
+				rdt_last_cmd_printf("CLOSID for io_alloc is used by %s group\n",
+						    grp_name ? grp_name : "another");

CLOSID -> ctrl_hw_id

sure.

Quoted 14 lines
Quoted 14 lines
fs/resctrl/rdtgroup.c +14 -0
+				ret = -EINVAL;
+				goto out_io_alloc;
+			}
+
+			ret = resctrl_io_alloc_init_cat(r, resctrl_schema_io_alloc(s),
+							io_alloc_closid);
+			if (ret) {
+				rdt_last_cmd_puts("Failed to initialize io_alloc allocations\n");
+				resctrl_io_alloc_closid_free(io_alloc_closid);
+				goto out_io_alloc;
+			}
+
+		} else {
+			resctrl_io_alloc_closid_free(io_alloc_closid);
Quoted 8 lines

fs/resctrl/rdtgroup.c static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, · line 1993

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+		}
+
+		ret = resctrl_arch_io_alloc_enable(r, enable);
+	}
+
+out_io_alloc:

out_unlock ... to match the other places in resctrl.

Sure.

Quoted 15 lines
Quoted 15 lines
fs/resctrl/rdtgroup.c +7 -0
+	mutex_unlock(&rdtgroup_mutex);
+	cpus_read_unlock();
+
+	return ret ?: nbytes;
+}
+
 /* rdtgroup information files for one cache resource. */
 static struct rftype res_common_files[] = {
 	{
@@ -1955,6 +2149,13 @@ static struct rftype res_common_files[] = {
 		.seq_show	= rdtgroup_schemata_show,
 		.fflags		= RFTYPE_CTRL_BASE,
 	},
+	{
Quoted 8 lines

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

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+		.name           = "io_alloc",
+		.mode           = 0644,
+		.kf_ops         = &rdtgroup_kf_single_ops,
+		.seq_show       = resctrl_io_alloc_show,
+		.write          = resctrl_io_alloc_write,
+	},

Please match existing code wrt tab usage.

Sure.

Quoted 8 lines
Quoted 8 lines
fs/resctrl/rdtgroup.c +0 -0
 	{
 		.name		= "mba_MBps_event",
 		.mode		= 0644,
@@ -2062,6 +2263,15 @@ static void thread_throttle_mode_init(void)
 				 RFTYPE_CTRL_INFO | RFTYPE_RES_MB);
 }
 
Quoted 13 lines

fs/resctrl/rdtgroup.c static void thread_throttle_mode_init(void) · line 2273

Quoted 8 lines
fs/resctrl/rdtgroup.c +8 -0
+static void io_alloc_init(void)
+{
+	struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
+
+	if (r->cache.io_alloc_capable)
+		resctrl_file_fflags_init("io_alloc",
+					 RFTYPE_CTRL_INFO | RFTYPE_RES_CACHE);
+}

Note that even if it only checks the L3 cache resource, this will make the file visible to all cache resource, also L2. This is why it is important to ensure documentation and implementation also accommodates resources that do not support io_alloc.

Agree.

Quoted 17 lines
Quoted 6 lines
fs/resctrl/rdtgroup.c +1 -0
+
 void resctrl_file_fflags_init(const char *config, unsigned long fflags)
 {
 	struct rftype *rft;

fs/resctrl/rdtgroup.c int resctrl_init(void) · line 4466

Quoted 8 lines
fs/resctrl/rdtgroup.c +2 -0
@@ -4249,6 +4459,8 @@ int resctrl_init(void)
 
 	thread_throttle_mode_init();
 
+	io_alloc_init();
+
 	ret = resctrl_mon_resource_init();
 	if (ret)
 		return ret;

Reinette

Signature · 2 lines
Thanks
Babu Moger
maintainer
#16 lore raw

Re: [PATCH v6 5/8] fs/resctrl: Add user interface to enable/disable io_alloc feature

Hi Babu,

Quoted 2 lines · Babu
Quoted 1 line · Reinette Chatre

On 6/11/25 2:23 PM, Babu Moger wrote:

...

Quoted 53 lines
Quoted 44 lines

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

Quoted 13 lines

+ */

fs/resctrl/rdtgroup.c +12 -0
+static int resctrl_io_alloc_closid_get(struct rdt_resource *r)
+{
+	int num_closids = closids_supported();
+
+	if (resctrl_arch_get_cdp_enabled(r->rid))
+		num_closids *= 2;
+
+	if (num_closids != resctrl_arch_get_num_closid(r))
+		return -ENOSPC;
+
+	return closids_supported() - 1;
+}

resctrl_io_alloc_closid_get() seems to be trying to do two things:
- determine what the io_alloc_closid is
- make sure the io_alloc_closid is supported

I think this should be split into two functions. Once the io_alloc_closid is determined to be supported and io_alloc enabled then there is no reason to keep checking if it is supported whenever the io_alloc_closid is queried.

How about simplifying this to:

/*
* note how this returns u32 that will eliminate
* unnecessary error checking in usages where io_alloc_closid
* needs to be determined after an resctrl_arch_get_io_alloc_enabled(r)
* already confirmed io_alloc is enabled
* function comment could note that this returns the CLOSID
* required by io_alloc but not whether the CLOSID can
* be supported, for this resctrl_io_alloc_closid_supported() should
* be used.
* Can also note that returned value will always be valid if
* resctrl_arch_get_io_alloc_enabled(r) is true.
*/
u32 resctrl_io_alloc_closid(struct rdt_resource *r) {
if (resctrl_arch_get_cdp_enabled(r->rid))
return resctrl_arch_get_num_closid(r)/2 - 1
else
return resctrl_arch_get_num_closid(r) -1
}

Quoted 8 lines

/*
* note how below already makes resctrl's io_alloc implementation
* more generic
*/
resctrl_io_alloc_closid_supported(u32 io_alloc_closid) {
return io_alloc_closid < closids_supported()
}

Quoted 5 lines

Sure.
Changed the check to

    return io_alloc_closid == (closids_supported() -1)

resctrl_io_alloc_closid_supported() is not intended to reflect what the value is but just check if provided value is supported. By changing the check to above resctrl_io_alloc_closid_supported() does two things again (what the move to new functions aimed to avoid): checking that the CLOSID is supported while requiring that it is the highest supported CLOSID. What issue(s) do you see with using "io_alloc_closid < closids_supported()" as the check?

Reinette

#17 lore raw

Re: [PATCH v6 5/8] fs/resctrl: Add user interface to enable/disable io_alloc feature

Hi Reinette,

Quoted 67 lines · Reinette Chatre

Hi Babu,

Quoted 2 lines · Babu
Quoted 1 line · Reinette Chatre

On 6/11/25 2:23 PM, Babu Moger wrote:

...

Quoted 53 lines
Quoted 44 lines

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

Quoted 13 lines

+ */

fs/resctrl/rdtgroup.c +12 -0
+static int resctrl_io_alloc_closid_get(struct rdt_resource *r)
+{
+	int num_closids = closids_supported();
+
+	if (resctrl_arch_get_cdp_enabled(r->rid))
+		num_closids *= 2;
+
+	if (num_closids != resctrl_arch_get_num_closid(r))
+		return -ENOSPC;
+
+	return closids_supported() - 1;
+}

resctrl_io_alloc_closid_get() seems to be trying to do two things:
- determine what the io_alloc_closid is
- make sure the io_alloc_closid is supported

I think this should be split into two functions. Once the io_alloc_closid is determined to be supported and io_alloc enabled then there is no reason to keep checking if it is supported whenever the io_alloc_closid is queried.

How about simplifying this to:

/*
* note how this returns u32 that will eliminate
* unnecessary error checking in usages where io_alloc_closid
* needs to be determined after an resctrl_arch_get_io_alloc_enabled(r)
* already confirmed io_alloc is enabled
* function comment could note that this returns the CLOSID
* required by io_alloc but not whether the CLOSID can
* be supported, for this resctrl_io_alloc_closid_supported() should
* be used.
* Can also note that returned value will always be valid if
* resctrl_arch_get_io_alloc_enabled(r) is true.
*/
u32 resctrl_io_alloc_closid(struct rdt_resource *r) {
if (resctrl_arch_get_cdp_enabled(r->rid))
return resctrl_arch_get_num_closid(r)/2 - 1
else
return resctrl_arch_get_num_closid(r) -1
}

Quoted 8 lines

/*
* note how below already makes resctrl's io_alloc implementation
* more generic
*/
resctrl_io_alloc_closid_supported(u32 io_alloc_closid) {
return io_alloc_closid < closids_supported()
}

Quoted 5 lines

Sure.
Changed the check to

return io_alloc_closid == (closids_supported() -1)

Quoted 7 lines

resctrl_io_alloc_closid_supported() is not intended to reflect what the value is but just check if provided value is supported. By changing the check to above resctrl_io_alloc_closid_supported() does two things again (what the move to new functions aimed to avoid): checking that the CLOSID is supported while requiring that it is the highest supported CLOSID. What issue(s) do you see with using "io_alloc_closid < closids_supported()" as the check?

I don't see any issue. It should be fine. Will test and verify it.

thanks
Babu

author reviewer
#18 lore raw

PATCH v6 6/8 fs/resctrl: Introduce interface to display io_alloc CBMs

In reply to Babu Moger

The io_alloc feature in resctrl enables system software to configure the portion of the L3 cache allocated for I/O traffic.

Add the interface to display CBMs (Capacity Bit Mask) of io_alloc feature.

The CBM interface file io_alloc_cbm will reside in the info directory (e.g., /sys/fs/resctrl/info/L3/). Displaying the resource name is not necessary. Pass the resource name to show_doms() and print it only if the name is valid. For io_alloc, pass NULL to suppress printing the resource name.

When CDP is enabled, io_alloc routes traffic using the highest CLOSID associated with an L3CODE resource. However, CBMs can be accessed via either L3CODE or L3DATA resources.

---
v6: Added "io_alloc_cbm" details in user doc resctrl.rst.
Resource name is not printed in CBM now. Corrected the texts about it in resctrl.rst.

v5: Resolved conflicts due to recent resctrl FS/ARCH code restructure.
Updated show_doms() to print the resource if only it is valid. Pass NULL while printing io_alloc CBM.
Changed the code to access the CBMs via either L3CODE or L3DATA resources.

v4: Updated the change log.
Added rdtgroup_mutex before rdt_last_cmd_puts(). Returned -ENODEV when resource type is CDP_DATA.
Kept the resource name while printing the CBM (L3:0=fff) that way I dont have to change show_doms() just for this feature and it is consistant across all the schemata display.

v3: Minor changes due to changes in resctrl_arch_get_io_alloc_enabled()
and resctrl_io_alloc_closid_get().
Added the check to verify CDP resource type.
Updated the commit log.

v2: Fixed to display only on L3 resources.
Added the locks while processing.
Rename the displat to io_alloc_cbm (from sdciae_cmd).

---
 Documentation/filesystems/resctrl.rst | 13 +++++++
 fs/resctrl/ctrlmondata.c              |  8 +++--
 fs/resctrl/internal.h                 |  2 ++
 fs/resctrl/rdtgroup.c                 | 51 ++++++++++++++++++++++++++-
 4 files changed, 70 insertions(+), 4 deletions(-)
Documentation/filesystems/resctrl.rst +13 -0
index 03c829b2c276..b31748ec8c61 100644
@@ -169,6 +169,19 @@ related to allocation:
 		When CDP is enabled, io_alloc routes I/O traffic using the highest
 		CLOSID allocated for the instruction cache (L3CODE).
 
+"io_alloc_cbm":
+		Capacity Bit Masks (CBMs) available to supported IO devices which
+		can directly insert cache lines in L3 which can help to reduce the
+		latency. CBMs are displayed in the following format:
+
+			<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
+
+		Example::
+
+			# cat /sys/fs/resctrl/info/L3/io_alloc_cbm
+			0=ffff;1=ffff
+
+
 Memory bandwidth(MB) subdirectory contains the following files
 with respect to allocation:
 
fs/resctrl/ctrlmondata.c +5 -3
index 6ed2dfd4dbbd..ea039852569a 100644
@@ -381,7 +381,8 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
 	return ret ?: nbytes;
 }
 
-static void show_doms(struct seq_file *s, struct resctrl_schema *schema, int closid)
+void show_doms(struct seq_file *s, struct resctrl_schema *schema, char *resource_name,
+	       int closid)
 {
 	struct rdt_resource *r = schema->res;
 	struct rdt_ctrl_domain *dom;
@@ -391,7 +392,8 @@ static void show_doms(struct seq_file *s, struct resctrl_schema *schema, int clo
 	/* Walking r->domains, ensure it can't race with cpuhp */
 	lockdep_assert_cpus_held();
 
-	seq_printf(s, "%*s:", max_name_width, schema->name);
+	if (resource_name)
+		seq_printf(s, "%*s:", max_name_width, resource_name);
 	list_for_each_entry(dom, &r->ctrl_domains, hdr.list) {
 		if (sep)
 			seq_puts(s, ";");
@@ -437,7 +439,7 @@ int rdtgroup_schemata_show(struct kernfs_open_file *of,
 			closid = rdtgrp->closid;
 			list_for_each_entry(schema, &resctrl_schema_all, list) {
 				if (closid < schema->num_closid)
-					show_doms(s, schema, closid);
+					show_doms(s, schema, schema->name, closid);
 			}
 		}
 	} else {
fs/resctrl/internal.h +2 -0
index 9a8cf6f11151..14f3697c1187 100644
@@ -374,6 +374,8 @@ void rdt_staged_configs_clear(void);
 bool closid_allocated(unsigned int closid);
 
 int resctrl_find_cleanest_closid(void);
+void show_doms(struct seq_file *s, struct resctrl_schema *schema,
+	       char *name, int closid);
 
 #ifdef CONFIG_RESCTRL_FS_PSEUDO_LOCK
 int rdtgroup_locksetup_enter(struct rdtgroup *rdtgrp);
fs/resctrl/rdtgroup.c +50 -1

71 lines not on this page · raw message

Signature · 1 line
2.34.1
#19 lore raw

Re: [PATCH v6 6/8] fs/resctrl: Introduce interface to display io_alloc CBMs

kernel test robot noticed the following build warnings:

Hi Babu,

kernel test robot noticed the following build warnings:

[auto build test WARNING on brauner-vfs/vfs.all]
[also build test WARNING on linus/master v6.16-rc1 next-20250612] [cannot apply to tip/x86/core aegl/next]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Babu-Moger/x86-cpufeatures-Add-support-for-L3-Smart-Data-Cache-Injection-Allocation-Enforcement/20250612-053050
base:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git vfs.all
patch link:    https://lore.kernel.org/r/16cebf7069e11e07c0d9e343aa72363325befafd.1749677012.git.babu.moger%40amd.com
patch subject: [PATCH v6 6/8] fs/resctrl: Introduce interface to display io_alloc CBMs
config: x86_64-randconfig-r071-20250612 (https://download.01.org/0day-ci/archive/20250613/[email protected]/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

New smatch warnings:
fs/resctrl/rdtgroup.c:2026 resctrl_io_alloc_cbm_show() warn: unsigned 'io_alloc_closid' is never less than zero. fs/resctrl/rdtgroup.c:2026 resctrl_io_alloc_cbm_show() warn: error code type promoted to positive: 'io_alloc_closid'

Old smatch warnings:
fs/resctrl/rdtgroup.c:1961 resctrl_io_alloc_write() warn: unsigned 'io_alloc_closid' is never less than zero. fs/resctrl/rdtgroup.c:1961 resctrl_io_alloc_write() warn: error code type promoted to positive: 'io_alloc_closid'

vim +/io_alloc_closid +2026 fs/resctrl/rdtgroup.c

1999
2000 static int resctrl_io_alloc_cbm_show(struct kernfs_open_file *of,
2001 struct seq_file *seq, void *v)
2002 {
2003 struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
2004 struct rdt_resource *r = s->res;
2005 u32 io_alloc_closid;
2006 int ret = 0;
2007
2008 cpus_read_lock();
2009 mutex_lock(&rdtgroup_mutex);
2010
2011 rdt_last_cmd_clear();
2012
2013 if (!r->cache.io_alloc_capable) {
2014 rdt_last_cmd_puts("io_alloc feature is not supported on the resource\n");
2015 ret = -ENODEV;
2016 goto cbm_show_out;
2017 }
2018
2019 if (!resctrl_arch_get_io_alloc_enabled(r)) {
2020 rdt_last_cmd_puts("io_alloc feature is not enabled\n");
2021 ret = -EINVAL;
2022 goto cbm_show_out;
2023 }
2024
2025 io_alloc_closid = resctrl_io_alloc_closid_get(r);

> 2026		if (io_alloc_closid < 0) {

2027 rdt_last_cmd_puts("Max CLOSID to support io_alloc is not available\n");
2028 ret = -EINVAL;
2029 goto cbm_show_out;
2030 }
2031
2032 show_doms(seq, resctrl_schema_io_alloc(s), NULL, io_alloc_closid);
2033
2034 cbm_show_out:
2035 mutex_unlock(&rdtgroup_mutex);
2036 cpus_read_unlock();
2037 return ret;
2038 }
2039

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
maintainer
#20 lore raw

Re: [PATCH v6 6/8] fs/resctrl: Introduce interface to display io_alloc CBMs

In reply to Babu Moger

Hi Babu,

Quoted 2 lines · Babu Moger

The io_alloc feature in resctrl enables system software to configure the portion of the L3 cache allocated for I/O traffic.

Drop L3?

Quoted 3 lines

Add the interface to display CBMs (Capacity Bit Mask) of io_alloc feature.

After the fs/arch split it is not always obvious what is meant with "interface" ... it could be new API between fs and arch or it could be new resctrl file.
This can be specific:
Add "io_alloc_cbm" resctrl file to display ...

Quoted 13 lines

The CBM interface file io_alloc_cbm will reside in the info directory (e.g., /sys/fs/resctrl/info/L3/). Displaying the resource name is not necessary. Pass the resource name to show_doms() and print it only if the name is valid. For io_alloc, pass NULL to suppress printing the resource name.

When CDP is enabled, io_alloc routes traffic using the highest CLOSID associated with an L3CODE resource. However, CBMs can be accessed via either L3CODE or L3DATA resources.

---

...

Quoted 12 lines
---
 Documentation/filesystems/resctrl.rst | 13 +++++++
 fs/resctrl/ctrlmondata.c              |  8 +++--
 fs/resctrl/internal.h                 |  2 ++
 fs/resctrl/rdtgroup.c                 | 51 ++++++++++++++++++++++++++-
 4 files changed, 70 insertions(+), 4 deletions(-)
Documentation/filesystems/resctrl.rst +0 -0
index 03c829b2c276..b31748ec8c61 100644

Documentation/filesystems/resctrl.rst related to allocation: · line 174

Quoted 6 lines
Documentation/filesystems/resctrl.rst +3 -0
@@ -169,6 +169,19 @@ related to allocation:
 		When CDP is enabled, io_alloc routes I/O traffic using the highest
 		CLOSID allocated for the instruction cache (L3CODE).
 
+"io_alloc_cbm":
+		Capacity Bit Masks (CBMs) available to supported IO devices which
+		can directly insert cache lines in L3 which can help to reduce the

"CBMs that describe the portions of cache instances to which I/O traffic from supported IO devices are routed."

Please check ... there seems to be some inconsistency in "IO" vs "I/O" use.

Also consider something like,
"When CDP is enabled "io_alloc_cbm" associated with the DATA
and CODE resources may reflect the same values. For example, values read from and written to /sys/fs/resctrl/info/L3DATA/io_alloc_cbm may be reflected by /sys/fs/resctrl/info/L3CODE/io_alloc_cbm and vice versa."
What do you think?

Quoted 74 lines
Documentation/filesystems/resctrl.rst +10 -0
+		latency. CBMs are displayed in the following format:
+
+			<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
+
+		Example::
+
+			# cat /sys/fs/resctrl/info/L3/io_alloc_cbm
+			0=ffff;1=ffff
+
+
 Memory bandwidth(MB) subdirectory contains the following files
 with respect to allocation:
 
fs/resctrl/ctrlmondata.c +5 -3
index 6ed2dfd4dbbd..ea039852569a 100644
@@ -381,7 +381,8 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
 	return ret ?: nbytes;
 }
 
-static void show_doms(struct seq_file *s, struct resctrl_schema *schema, int closid)
+void show_doms(struct seq_file *s, struct resctrl_schema *schema, char *resource_name,
+	       int closid)
 {
 	struct rdt_resource *r = schema->res;
 	struct rdt_ctrl_domain *dom;
@@ -391,7 +392,8 @@ static void show_doms(struct seq_file *s, struct resctrl_schema *schema, int clo
 	/* Walking r->domains, ensure it can't race with cpuhp */
 	lockdep_assert_cpus_held();
 
-	seq_printf(s, "%*s:", max_name_width, schema->name);
+	if (resource_name)
+		seq_printf(s, "%*s:", max_name_width, resource_name);
 	list_for_each_entry(dom, &r->ctrl_domains, hdr.list) {
 		if (sep)
 			seq_puts(s, ";");
@@ -437,7 +439,7 @@ int rdtgroup_schemata_show(struct kernfs_open_file *of,
 			closid = rdtgrp->closid;
 			list_for_each_entry(schema, &resctrl_schema_all, list) {
 				if (closid < schema->num_closid)
-					show_doms(s, schema, closid);
+					show_doms(s, schema, schema->name, closid);
 			}
 		}
 	} else {
fs/resctrl/internal.h +2 -0
index 9a8cf6f11151..14f3697c1187 100644
@@ -374,6 +374,8 @@ void rdt_staged_configs_clear(void);
 bool closid_allocated(unsigned int closid);
 
 int resctrl_find_cleanest_closid(void);
+void show_doms(struct seq_file *s, struct resctrl_schema *schema,
+	       char *name, int closid);
 
 #ifdef CONFIG_RESCTRL_FS_PSEUDO_LOCK
 int rdtgroup_locksetup_enter(struct rdtgroup *rdtgrp);
fs/resctrl/rdtgroup.c +7 -0
index bbc032b4d0e9..0c2d2cf4baa1 100644
@@ -1997,6 +1997,46 @@ static ssize_t resctrl_io_alloc_write(struct kernfs_open_file *of, char *buf,
 	return ret ?: nbytes;
 }
 
+static int resctrl_io_alloc_cbm_show(struct kernfs_open_file *of,
+				     struct seq_file *seq, void *v)
+{
+	struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+	struct rdt_resource *r = s->res;
+	u32 io_alloc_closid;
+	int ret = 0;

fs/resctrl/rdtgroup.c static ssize_t resctrl_io_alloc_write(struct kernfs_open_file *of, char *buf, · line 2016

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+
+	cpus_read_lock();
+	mutex_lock(&rdtgroup_mutex);
+
+	rdt_last_cmd_clear();
+
+	if (!r->cache.io_alloc_capable) {
+		rdt_last_cmd_puts("io_alloc feature is not supported on the resource\n");
+		ret = -ENODEV;
+		goto cbm_show_out;

out_unlock

fs/resctrl/rdtgroup.c static ssize_t resctrl_io_alloc_write(struct kernfs_open_file *of, char *buf, · line 2026

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+	}
+
+	if (!resctrl_arch_get_io_alloc_enabled(r)) {
+		rdt_last_cmd_puts("io_alloc feature is not enabled\n");
+		ret = -EINVAL;
+		goto cbm_show_out;
+	}
+
+	io_alloc_closid = resctrl_io_alloc_closid_get(r);
+	if (io_alloc_closid < 0) {

Another example where io_alloc_closid must be valid thanks to earlier resctrl_arch_get_io_alloc_enabled(r).

fs/resctrl/rdtgroup.c static ssize_t resctrl_io_alloc_write(struct kernfs_open_file *of, char *buf, · line 2034

Quoted 8 lines
fs/resctrl/rdtgroup.c +8 -0
+		rdt_last_cmd_puts("Max CLOSID to support io_alloc is not available\n");
+		ret = -EINVAL;
+		goto cbm_show_out;
+	}
+
+	show_doms(seq, resctrl_schema_io_alloc(s), NULL, io_alloc_closid);
+
+cbm_show_out:

out_unlock ... to match rest of resctrl

fs/resctrl/rdtgroup.c static ssize_t resctrl_io_alloc_write(struct kernfs_open_file *of, char *buf, · line 2042

Quoted 8 lines
fs/resctrl/rdtgroup.c +5 -0
+	mutex_unlock(&rdtgroup_mutex);
+	cpus_read_unlock();
+	return ret;
+}
+
 /* rdtgroup information files for one cache resource. */
 static struct rftype res_common_files[] = {
 	{

Reinette

#21 lore raw

Re: [PATCH v6 6/8] fs/resctrl: Introduce interface to display io_alloc CBMs

Hi Reinette,

Quoted 7 lines · Reinette Chatre

Hi Babu,

Quoted 2 lines · Babu Moger

The io_alloc feature in resctrl enables system software to configure the portion of the L3 cache allocated for I/O traffic.

Drop L3?

Sure.

Quoted 10 lines
Quoted 3 lines

Add the interface to display CBMs (Capacity Bit Mask) of io_alloc feature.

After the fs/arch split it is not always obvious what is meant with "interface" ... it could be new API between fs and arch or it could be new resctrl file.
This can be specific:
Add "io_alloc_cbm" resctrl file to display ...

Sure.

Quoted 31 lines
Quoted 13 lines

The CBM interface file io_alloc_cbm will reside in the info directory (e.g., /sys/fs/resctrl/info/L3/). Displaying the resource name is not necessary. Pass the resource name to show_doms() and print it only if the name is valid. For io_alloc, pass NULL to suppress printing the resource name.

When CDP is enabled, io_alloc routes traffic using the highest CLOSID associated with an L3CODE resource. However, CBMs can be accessed via either L3CODE or L3DATA resources.

---

...

Quoted 15 lines
---
  Documentation/filesystems/resctrl.rst | 13 +++++++
  fs/resctrl/ctrlmondata.c              |  8 +++--
  fs/resctrl/internal.h                 |  2 ++
  fs/resctrl/rdtgroup.c                 | 51 ++++++++++++++++++++++++++-
  4 files changed, 70 insertions(+), 4 deletions(-)
Documentation/filesystems/resctrl.rst +0 -0
index 03c829b2c276..b31748ec8c61 100644
@@ -169,6 +169,19 @@ related to allocation:
  		When CDP is enabled, io_alloc routes I/O traffic using the highest
  		CLOSID allocated for the instruction cache (L3CODE).
 
Quoted 6 lines

Documentation/filesystems/resctrl.rst related to allocation: · line 174

Quoted 3 lines
Documentation/filesystems/resctrl.rst +3 -0
+"io_alloc_cbm":
+		Capacity Bit Masks (CBMs) available to supported IO devices which
+		can directly insert cache lines in L3 which can help to reduce the

"CBMs that describe the portions of cache instances to which I/O traffic from supported IO devices are routed."

Sure.

Quoted 1 line

Please check ... there seems to be some inconsistency in "IO" vs "I/O" use.

Changed to "I/O" in all the places.

Quoted 7 lines

Also consider something like,
"When CDP is enabled "io_alloc_cbm" associated with the DATA
and CODE resources may reflect the same values. For example, values read from and written to /sys/fs/resctrl/info/L3DATA/io_alloc_cbm may be reflected by /sys/fs/resctrl/info/L3CODE/io_alloc_cbm and vice versa."
What do you think?

Looks good.

Quoted 79 lines
Quoted 79 lines
Documentation/filesystems/resctrl.rst +10 -0
+		latency. CBMs are displayed in the following format:
+
+			<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
+
+		Example::
+
+			# cat /sys/fs/resctrl/info/L3/io_alloc_cbm
+			0=ffff;1=ffff
+
+
  Memory bandwidth(MB) subdirectory contains the following files
  with respect to allocation:
 
fs/resctrl/ctrlmondata.c +5 -3
index 6ed2dfd4dbbd..ea039852569a 100644
@@ -381,7 +381,8 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
  	return ret ?: nbytes;
  }
 
-static void show_doms(struct seq_file *s, struct resctrl_schema *schema, int closid)
+void show_doms(struct seq_file *s, struct resctrl_schema *schema, char *resource_name,
+	       int closid)
  {
  	struct rdt_resource *r = schema->res;
  	struct rdt_ctrl_domain *dom;
@@ -391,7 +392,8 @@ static void show_doms(struct seq_file *s, struct resctrl_schema *schema, int clo
  	/* Walking r->domains, ensure it can't race with cpuhp */
  	lockdep_assert_cpus_held();
 
-	seq_printf(s, "%*s:", max_name_width, schema->name);
+	if (resource_name)
+		seq_printf(s, "%*s:", max_name_width, resource_name);
  	list_for_each_entry(dom, &r->ctrl_domains, hdr.list) {
  		if (sep)
  			seq_puts(s, ";");
@@ -437,7 +439,7 @@ int rdtgroup_schemata_show(struct kernfs_open_file *of,
  			closid = rdtgrp->closid;
  			list_for_each_entry(schema, &resctrl_schema_all, list) {
  				if (closid < schema->num_closid)
-					show_doms(s, schema, closid);
+					show_doms(s, schema, schema->name, closid);
  			}
  		}
  	} else {
fs/resctrl/internal.h +2 -0
index 9a8cf6f11151..14f3697c1187 100644
@@ -374,6 +374,8 @@ void rdt_staged_configs_clear(void);
  bool closid_allocated(unsigned int closid);
 
  int resctrl_find_cleanest_closid(void);
+void show_doms(struct seq_file *s, struct resctrl_schema *schema,
+	       char *name, int closid);
 
  #ifdef CONFIG_RESCTRL_FS_PSEUDO_LOCK
  int rdtgroup_locksetup_enter(struct rdtgroup *rdtgrp);
fs/resctrl/rdtgroup.c +11 -0
index bbc032b4d0e9..0c2d2cf4baa1 100644
@@ -1997,6 +1997,46 @@ static ssize_t resctrl_io_alloc_write(struct kernfs_open_file *of, char *buf,
  	return ret ?: nbytes;
  }
 
+static int resctrl_io_alloc_cbm_show(struct kernfs_open_file *of,
+				     struct seq_file *seq, void *v)
+{
+	struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+	struct rdt_resource *r = s->res;
+	u32 io_alloc_closid;
+	int ret = 0;
+
+	cpus_read_lock();
+	mutex_lock(&rdtgroup_mutex);
+
Quoted 9 lines

fs/resctrl/rdtgroup.c static ssize_t resctrl_io_alloc_write(struct kernfs_open_file *of, char *buf, · line 2016

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+	rdt_last_cmd_clear();
+
+	if (!r->cache.io_alloc_capable) {
+		rdt_last_cmd_puts("io_alloc feature is not supported on the resource\n");
+		ret = -ENODEV;
+		goto cbm_show_out;

out_unlock

Sure.

Quoted 4 lines
Quoted 4 lines
fs/resctrl/rdtgroup.c +4 -0
+	}
+
+	if (!resctrl_arch_get_io_alloc_enabled(r)) {
+		rdt_last_cmd_puts("io_alloc feature is not enabled\n");
Quoted 8 lines

fs/resctrl/rdtgroup.c static ssize_t resctrl_io_alloc_write(struct kernfs_open_file *of, char *buf, · line 2026

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+		ret = -EINVAL;
+		goto cbm_show_out;
+	}
+
+	io_alloc_closid = resctrl_io_alloc_closid_get(r);
+	if (io_alloc_closid < 0) {

Another example where io_alloc_closid must be valid thanks to earlier resctrl_arch_get_io_alloc_enabled(r).

Sure. Will remove this check.

Quoted 11 lines

fs/resctrl/rdtgroup.c static ssize_t resctrl_io_alloc_write(struct kernfs_open_file *of, char *buf, · line 2034

Quoted 9 lines
fs/resctrl/rdtgroup.c +8 -0
+		rdt_last_cmd_puts("Max CLOSID to support io_alloc is not available\n");
+		ret = -EINVAL;
+		goto cbm_show_out;
+	}
+
+	show_doms(seq, resctrl_schema_io_alloc(s), NULL, io_alloc_closid);
+
+cbm_show_out:

out_unlock ... to match rest of resctrl

sure.

Quoted 12 lines

fs/resctrl/rdtgroup.c static ssize_t resctrl_io_alloc_write(struct kernfs_open_file *of, char *buf, · line 2042

Quoted 9 lines
fs/resctrl/rdtgroup.c +5 -0
+	mutex_unlock(&rdtgroup_mutex);
+	cpus_read_unlock();
+	return ret;
+}
+
  /* rdtgroup information files for one cache resource. */
  static struct rftype res_common_files[] = {
  	{

Reinette

thanks
Babu

author reviewer
#22 lore raw

PATCH v6 7/8 fs/resctrl: Modify rdt_parse_data to pass mode and CLOSID

In reply to Babu Moger

The functions parse_cbm() and parse_bw() require mode and CLOSID to validate the Capacity Bit Mask (CBM). It is passed through struct rdtgroup in rdt_parse_data. Instead of passing them through struct rdtgroup, pass mode and closid directly.

This change enables parse_cbm() to be used for verifying CBM in io_alloc feature.

---
v6: Changed the subject line to fs/resctrl.

v5: Resolved conflicts due to recent resctrl FS/ARCH code restructure.

v4: New patch to call parse_cbm() directly to avoid code duplication.

---
 fs/resctrl/ctrlmondata.c | 29 +++++++++++++----------------
 fs/resctrl/internal.h    |  6 ++++++
 2 files changed, 19 insertions(+), 16 deletions(-)
fs/resctrl/ctrlmondata.c +13 -16
index ea039852569a..6409637b4de6 100644
@@ -23,11 +23,6 @@
 
 #include "internal.h"
 
-struct rdt_parse_data {
-	struct rdtgroup		*rdtgrp;
-	char			*buf;
-};
-
 typedef int (ctrlval_parser_t)(struct rdt_parse_data *data,
 			       struct resctrl_schema *s,
 			       struct rdt_ctrl_domain *d);
@@ -77,8 +72,8 @@ static int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s,
 		    struct rdt_ctrl_domain *d)
 {
 	struct resctrl_staged_config *cfg;
-	u32 closid = data->rdtgrp->closid;
 	struct rdt_resource *r = s->res;
+	u32 closid = data->closid;
 	u32 bw_val;
 
 	cfg = &d->staged_config[s->conf_type];
@@ -156,9 +151,10 @@ static bool cbm_validate(char *buf, u32 *data, struct rdt_resource *r)
 static int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
 		     struct rdt_ctrl_domain *d)
 {
-	struct rdtgroup *rdtgrp = data->rdtgrp;
+	enum rdtgrp_mode mode = data->mode;
 	struct resctrl_staged_config *cfg;
 	struct rdt_resource *r = s->res;
+	u32 closid = data->closid;
 	u32 cbm_val;
 
 	cfg = &d->staged_config[s->conf_type];
@@ -171,7 +167,7 @@ static int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
 	 * Cannot set up more than one pseudo-locked region in a cache
 	 * hierarchy.
 	 */
-	if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP &&
+	if (mode == RDT_MODE_PSEUDO_LOCKSETUP &&
 	    rdtgroup_pseudo_locked_in_hierarchy(d)) {
 		rdt_last_cmd_puts("Pseudo-locked region in hierarchy\n");
 		return -EINVAL;
@@ -180,9 +176,9 @@ static int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
 	if (!cbm_validate(data->buf, &cbm_val, r))
 		return -EINVAL;
 
-	if ((rdtgrp->mode == RDT_MODE_EXCLUSIVE ||
-	     rdtgrp->mode == RDT_MODE_SHAREABLE) &&
-	    rdtgroup_cbm_overlaps_pseudo_locked(d, cbm_val)) {
+	if ((mode == RDT_MODE_EXCLUSIVE ||
+	     mode == RDT_MODE_SHAREABLE) &&
+	     rdtgroup_cbm_overlaps_pseudo_locked(d, cbm_val)) {
 		rdt_last_cmd_puts("CBM overlaps with pseudo-locked region\n");
 		return -EINVAL;
 	}
@@ -191,14 +187,14 @@ static int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
 	 * The CBM may not overlap with the CBM of another closid if
 	 * either is exclusive.
 	 */
-	if (rdtgroup_cbm_overlaps(s, d, cbm_val, rdtgrp->closid, true)) {
+	if (rdtgroup_cbm_overlaps(s, d, cbm_val, closid, true)) {
 		rdt_last_cmd_puts("Overlaps with exclusive group\n");
 		return -EINVAL;
 	}
 
-	if (rdtgroup_cbm_overlaps(s, d, cbm_val, rdtgrp->closid, false)) {
-		if (rdtgrp->mode == RDT_MODE_EXCLUSIVE ||
-		    rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
+	if (rdtgroup_cbm_overlaps(s, d, cbm_val, closid, false)) {
+		if (mode == RDT_MODE_EXCLUSIVE ||
+		    mode == RDT_MODE_PSEUDO_LOCKSETUP) {
 			rdt_last_cmd_puts("Overlaps with other group\n");
 			return -EINVAL;
 		}
@@ -262,7 +258,8 @@ static int parse_line(char *line, struct resctrl_schema *s,
 	list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
 		if (d->hdr.id == dom_id) {
 			data.buf = dom;
-			data.rdtgrp = rdtgrp;
+			data.closid = rdtgrp->closid;
+			data.mode = rdtgrp->mode;
 			if (parse_ctrlval(&data, s, d))
 				return -EINVAL;
 			if (rdtgrp->mode ==  RDT_MODE_PSEUDO_LOCKSETUP) {
fs/resctrl/internal.h +6 -0
index 14f3697c1187..10a3188ffa54 100644
@@ -201,6 +201,12 @@ struct rdtgroup {
 	struct pseudo_lock_region	*plr;
 };
 
+struct rdt_parse_data {
+	u32			closid;
+	enum rdtgrp_mode	mode;
+	char			*buf;
+};
+
 /* rdtgroup.flags */
 #define	RDT_DELETED		1
 
Signature · 1 line
2.34.1
maintainer
#23 lore raw

Re: [PATCH v6 7/8] fs/resctrl: Modify rdt_parse_data to pass mode and CLOSID

Hi Babu,

Quoted 4 lines · Babu Moger

The functions parse_cbm() and parse_bw() require mode and CLOSID to validate the Capacity Bit Mask (CBM). It is passed through struct rdtgroup in rdt_parse_data. Instead of passing them through struct rdtgroup, pass mode and closid directly.

Above looks like a combination of context and solution description. Expectation is for context, problem, and solution to be in this order and in separate paragraphs.

Quoted 3 lines

This change enables parse_cbm() to be used for verifying CBM in io_alloc feature.

Is this the problem? It is not clear from changelog what problem is being solved.

Also, please drop "This change" that is semantically the same as "This patch".

Reinette

#24 lore raw

Re: [PATCH v6 7/8] fs/resctrl: Modify rdt_parse_data to pass mode and CLOSID

Hi Reinette,

Quoted 12 lines · Reinette Chatre

Hi Babu,

Quoted 4 lines · Babu Moger

The functions parse_cbm() and parse_bw() require mode and CLOSID to validate the Capacity Bit Mask (CBM). It is passed through struct rdtgroup in rdt_parse_data. Instead of passing them through struct rdtgroup, pass mode and closid directly.

Above looks like a combination of context and solution description. Expectation is for context, problem, and solution to be in this order and in separate paragraphs.

Will rephrase it.

Quoted 9 lines
Quoted 3 lines

This change enables parse_cbm() to be used for verifying CBM in io_alloc feature.

Is this the problem? It is not clear from changelog what problem is being solved.

Also, please drop "This change" that is semantically the same as "This patch".

Sure. Will change it.

Thanks
Babu

author reviewer
#25 lore raw

PATCH v6 8/8 fs/resctrl: Introduce interface to modify io_alloc Capacity Bit Masks

In reply to Babu Moger

"io_alloc" feature is a mechanism that enables direct insertion of data from I/O devices into the L3 cache. By directly caching data from I/O devices rather than first storing the I/O data in DRAM, it reduces the demands on DRAM bandwidth and reduces latency to the processor consuming the I/O data.

"io_alloc" feature uses the highest CLOSID to route the traffic from I/O devices. Provide the interface to modify io_alloc CBMs (Capacity Bit Mask) when feature is enabled.

---
v6: Updated the user doc restctr.doc for minor texts.
Changed the subject to fs/resctrl.

v5: Changes due to FS/ARCH code restructure. The files monitor.c/rdtgroup.c
have been split between FS and ARCH directories.
Changed the code to access the CBMs via either L3CODE or L3DATA resources.

v4: Removed resctrl_io_alloc_parse_cbm and called parse_cbm() directly.

v3: Minor changes due to changes in resctrl_arch_get_io_alloc_enabled()
and resctrl_io_alloc_closid_get().
Taken care of handling the CBM update when CDP is enabled. Updated the commit log to make it generic.

v2: Added more generic text in documentation.

---
 Documentation/filesystems/resctrl.rst | 13 ++++
 fs/resctrl/ctrlmondata.c              |  4 +-
 fs/resctrl/internal.h                 |  2 +
 fs/resctrl/rdtgroup.c                 | 89 ++++++++++++++++++++++++++-
 4 files changed, 105 insertions(+), 3 deletions(-)
Documentation/filesystems/resctrl.rst +13 -0
index b31748ec8c61..ae1157dcb4a3 100644
@@ -181,6 +181,19 @@ related to allocation:
 			# cat /sys/fs/resctrl/info/L3/io_alloc_cbm
 			0=ffff;1=ffff
 
+		CBM can be configured by writing to the interface.
+
+		Example::
+
+			# echo 1=FF > /sys/fs/resctrl/info/L3/io_alloc_cbm
+			# cat /sys/fs/resctrl/info/L3/io_alloc_cbm
+			0=ffff;1=00ff
+
+		When CDP is enabled, io_alloc directs traffic using the highest CLOSID
+		linked to an L3CODE resource. Although CBMs can be accessed through
+		either L3CODE or L3DATA resources, any updates to the schemata are
+		always routed through L3CODE.
+
 
 Memory bandwidth(MB) subdirectory contains the following files
 with respect to allocation:
fs/resctrl/ctrlmondata.c +2 -2
index 6409637b4de6..f3e5e697945c 100644
@@ -148,8 +148,8 @@ static bool cbm_validate(char *buf, u32 *data, struct rdt_resource *r)
  * Read one cache bit mask (hex). Check that it is valid for the current
  * resource type.
  */
-static int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
-		     struct rdt_ctrl_domain *d)
+int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
+	      struct rdt_ctrl_domain *d)
 {
 	enum rdtgrp_mode mode = data->mode;
 	struct resctrl_staged_config *cfg;
fs/resctrl/internal.h +2 -0
index 10a3188ffa54..755f23934295 100644
@@ -382,6 +382,8 @@ bool closid_allocated(unsigned int closid);
 int resctrl_find_cleanest_closid(void);
 void show_doms(struct seq_file *s, struct resctrl_schema *schema,
 	       char *name, int closid);
+int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
+	      struct rdt_ctrl_domain *d);
 
 #ifdef CONFIG_RESCTRL_FS_PSEUDO_LOCK
 int rdtgroup_locksetup_enter(struct rdtgroup *rdtgrp);
fs/resctrl/rdtgroup.c +88 -1

103 lines not on this page · raw message

Signature · 1 line
2.34.1
#26 lore raw

Re: [PATCH v6 8/8] fs/resctrl: Introduce interface to modify io_alloc Capacity Bit Masks

kernel test robot noticed the following build warnings:

Hi Babu,

kernel test robot noticed the following build warnings:

[auto build test WARNING on brauner-vfs/vfs.all]
[also build test WARNING on linus/master v6.16-rc1 next-20250612] [cannot apply to tip/x86/core aegl/next]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Babu-Moger/x86-cpufeatures-Add-support-for-L3-Smart-Data-Cache-Injection-Allocation-Enforcement/20250612-053050
base:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git vfs.all
patch link:    https://lore.kernel.org/r/6f8158ba0eebf41c9ec59e82dcdc28d4d3151c3b.1749677012.git.babu.moger%40amd.com
patch subject: [PATCH v6 8/8] fs/resctrl: Introduce interface to modify io_alloc Capacity Bit Masks
config: x86_64-randconfig-r071-20250612 (https://download.01.org/0day-ci/archive/20250613/[email protected]/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

New smatch warnings:
fs/resctrl/rdtgroup.c:2105 resctrl_io_alloc_cbm_write() warn: unsigned 'io_alloc_closid' is never less than zero. fs/resctrl/rdtgroup.c:2105 resctrl_io_alloc_cbm_write() warn: error code type promoted to positive: 'io_alloc_closid'

Old smatch warnings:
fs/resctrl/rdtgroup.c:1961 resctrl_io_alloc_write() warn: unsigned 'io_alloc_closid' is never less than zero. fs/resctrl/rdtgroup.c:1961 resctrl_io_alloc_write() warn: error code type promoted to positive: 'io_alloc_closid' fs/resctrl/rdtgroup.c:2026 resctrl_io_alloc_cbm_show() warn: unsigned 'io_alloc_closid' is never less than zero. fs/resctrl/rdtgroup.c:2026 resctrl_io_alloc_cbm_show() warn: error code type promoted to positive: 'io_alloc_closid'

vim +/io_alloc_closid +2105 fs/resctrl/rdtgroup.c

2072
2073 static ssize_t resctrl_io_alloc_cbm_write(struct kernfs_open_file *of,
2074 char *buf, size_t nbytes, loff_t off)
2075 {
2076 struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
2077 struct rdt_resource *r = s->res;
2078 u32 io_alloc_closid;
2079 int ret = 0;
2080
2081 /* Valid input requires a trailing newline */
2082 if (nbytes == 0 || buf[nbytes - 1] != '\n')
2083 return -EINVAL;
2084
2085 buf[nbytes - 1] = '\0';
2086
2087 if (!r->cache.io_alloc_capable) {
2088 rdt_last_cmd_puts("io_alloc feature is not supported on the resource\n");
2089 return -EINVAL;
2090 }
2091
2092 cpus_read_lock();
2093 mutex_lock(&rdtgroup_mutex);
2094
2095 rdt_last_cmd_clear();
2096 rdt_staged_configs_clear();
2097
2098 if (!resctrl_arch_get_io_alloc_enabled(r)) {
2099 rdt_last_cmd_puts("io_alloc feature is not enabled\n");
2100 ret = -EINVAL;
2101 goto cbm_write_out;
2102 }
2103
2104 io_alloc_closid = resctrl_io_alloc_closid_get(r);

> 2105		if (io_alloc_closid < 0) {

2106 rdt_last_cmd_puts("Max CLOSID to support io_alloc is not available\n");
2107 ret = -EINVAL;
2108 goto cbm_write_out;
2109 }
2110
2111 ret = resctrl_io_alloc_parse_line(buf, r, resctrl_schema_io_alloc(s),
2112 io_alloc_closid);
2113 if (ret)
2114 goto cbm_write_out;
2115
2116 ret = resctrl_arch_update_domains(r, io_alloc_closid);
2117
2118 cbm_write_out:
2119 rdt_staged_configs_clear();
2120 mutex_unlock(&rdtgroup_mutex);
2121 cpus_read_unlock();
2122
2123 return ret ?: nbytes;
2124 }
2125

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
author reviewer
#27 lore raw

Re: [PATCH v6 8/8] fs/resctrl: Introduce interface to modify io_alloc Capacity Bit Masks

Quoted 67 lines · kernel test robot

Hi Babu,

kernel test robot noticed the following build warnings:

[auto build test WARNING on brauner-vfs/vfs.all]
[also build test WARNING on linus/master v6.16-rc1 next-20250612] [cannot apply to tip/x86/core aegl/next]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Babu-Moger/x86-cpufeatures-Add-support-for-L3-Smart-Data-Cache-Injection-Allocation-Enforcement/20250612-053050
base:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git vfs.all
patch link:    https://lore.kernel.org/r/6f8158ba0eebf41c9ec59e82dcdc28d4d3151c3b.1749677012.git.babu.moger%40amd.com
patch subject: [PATCH v6 8/8] fs/resctrl: Introduce interface to modify io_alloc Capacity Bit Masks> config: x86_64-randconfig-r071-20250612 (https://download.01.org/0day-ci/archive/20250613/[email protected]/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

New smatch warnings:
fs/resctrl/rdtgroup.c:2105 resctrl_io_alloc_cbm_write() warn: unsigned 'io_alloc_closid' is never less than zero. fs/resctrl/rdtgroup.c:2105 resctrl_io_alloc_cbm_write() warn: error code type promoted to positive: 'io_alloc_closid'

Old smatch warnings:
fs/resctrl/rdtgroup.c:1961 resctrl_io_alloc_write() warn: unsigned 'io_alloc_closid' is never less than zero. fs/resctrl/rdtgroup.c:1961 resctrl_io_alloc_write() warn: error code type promoted to positive: 'io_alloc_closid' fs/resctrl/rdtgroup.c:2026 resctrl_io_alloc_cbm_show() warn: unsigned 'io_alloc_closid' is never less than zero. fs/resctrl/rdtgroup.c:2026 resctrl_io_alloc_cbm_show() warn: error code type promoted to positive: 'io_alloc_closid'

vim +/io_alloc_closid +2105 fs/resctrl/rdtgroup.c

2072
2073 static ssize_t resctrl_io_alloc_cbm_write(struct kernfs_open_file *of,
2074 char *buf, size_t nbytes, loff_t off)
2075 {
2076 struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
2077 struct rdt_resource *r = s->res;
2078 u32 io_alloc_closid;
2079 int ret = 0;
2080
2081 /* Valid input requires a trailing newline */
2082 if (nbytes == 0 || buf[nbytes - 1] != '\n')
2083 return -EINVAL;
2084
2085 buf[nbytes - 1] = '\0';
2086
2087 if (!r->cache.io_alloc_capable) {
2088 rdt_last_cmd_puts("io_alloc feature is not supported on the resource\n");
2089 return -EINVAL;
2090 }
2091
2092 cpus_read_lock();
2093 mutex_lock(&rdtgroup_mutex);
2094
2095 rdt_last_cmd_clear();
2096 rdt_staged_configs_clear();
2097
2098 if (!resctrl_arch_get_io_alloc_enabled(r)) {
2099 rdt_last_cmd_puts("io_alloc feature is not enabled\n");
2100 ret = -EINVAL;
2101 goto cbm_write_out;
2102 }
2103
2104 io_alloc_closid = resctrl_io_alloc_closid_get(r);

Quoted 2 lines
Quoted 1 line

2105 if (io_alloc_closid < 0) {

2106 rdt_last_cmd_puts("Max CLOSID to support io_alloc is not available\n");

Thanks. Will fix it in next revision.

Signature · 2 lines
Thanks
Babu Moger
maintainer
#28 lore raw

Re: [PATCH v6 8/8] fs/resctrl: Introduce interface to modify io_alloc Capacity Bit Masks

In reply to Babu Moger

Hi Babu,

Quoted 1 line · Babu Moger

"io_alloc" feature is a mechanism that enables direct insertion of data

""io_alloc" feature is a mechanism that enables" -> ""io_alloc" feature enables"

Quoted 1 line

from I/O devices into the L3 cache. By directly caching data from I/O

Drop L3

Quoted 5 lines

devices rather than first storing the I/O data in DRAM, it reduces the demands on DRAM bandwidth and reduces latency to the processor consuming the I/O data.

"io_alloc" feature uses the highest CLOSID to route the traffic from I/O

How is the CLOSID related here?

Quoted 5 lines

devices. Provide the interface to modify io_alloc CBMs (Capacity Bit Mask) when feature is enabled.

---

...

Quoted 17 lines
---
 Documentation/filesystems/resctrl.rst | 13 ++++
 fs/resctrl/ctrlmondata.c              |  4 +-
 fs/resctrl/internal.h                 |  2 +
 fs/resctrl/rdtgroup.c                 | 89 ++++++++++++++++++++++++++-
 4 files changed, 105 insertions(+), 3 deletions(-)
Documentation/filesystems/resctrl.rst +2 -0
index b31748ec8c61..ae1157dcb4a3 100644
@@ -181,6 +181,19 @@ related to allocation:
 			# cat /sys/fs/resctrl/info/L3/io_alloc_cbm
 			0=ffff;1=ffff
 
+		CBM can be configured by writing to the interface.
+

Documentation/filesystems/resctrl.rst related to allocation: · line 195

Quoted 10 lines
Documentation/filesystems/resctrl.rst +10 -0
+		Example::
+
+			# echo 1=FF > /sys/fs/resctrl/info/L3/io_alloc_cbm
+			# cat /sys/fs/resctrl/info/L3/io_alloc_cbm
+			0=ffff;1=00ff
+
+		When CDP is enabled, io_alloc directs traffic using the highest CLOSID
+		linked to an L3CODE resource. Although CBMs can be accessed through
+		either L3CODE or L3DATA resources, any updates to the schemata are
+		always routed through L3CODE.

Please do not commit resctrl to this implementation by documenting it as part of user interface. Could snippet about CDP I shared in patch 6 be placed here as a replacement? Not the usage of *may* to keep implementation options open.

Quoted 79 lines
Documentation/filesystems/resctrl.rst +1 -0
+
 
 Memory bandwidth(MB) subdirectory contains the following files
 with respect to allocation:
fs/resctrl/ctrlmondata.c +2 -2
index 6409637b4de6..f3e5e697945c 100644
@@ -148,8 +148,8 @@ static bool cbm_validate(char *buf, u32 *data, struct rdt_resource *r)
  * Read one cache bit mask (hex). Check that it is valid for the current
  * resource type.
  */
-static int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
-		     struct rdt_ctrl_domain *d)
+int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
+	      struct rdt_ctrl_domain *d)
 {
 	enum rdtgrp_mode mode = data->mode;
 	struct resctrl_staged_config *cfg;
fs/resctrl/internal.h +2 -0
index 10a3188ffa54..755f23934295 100644
@@ -382,6 +382,8 @@ bool closid_allocated(unsigned int closid);
 int resctrl_find_cleanest_closid(void);
 void show_doms(struct seq_file *s, struct resctrl_schema *schema,
 	       char *name, int closid);
+int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
+	      struct rdt_ctrl_domain *d);
 
 #ifdef CONFIG_RESCTRL_FS_PSEUDO_LOCK
 int rdtgroup_locksetup_enter(struct rdtgroup *rdtgrp);
fs/resctrl/rdtgroup.c +39 -0
index 0c2d2cf4baa1..f6c44fae4b72 100644
@@ -2037,6 +2037,92 @@ static int resctrl_io_alloc_cbm_show(struct kernfs_open_file *of,
 	return ret;
 }
 
+static int resctrl_io_alloc_parse_line(char *line,  struct rdt_resource *r,
+				       struct resctrl_schema *s, u32 closid)
+{
+	struct rdt_parse_data data;
+	struct rdt_ctrl_domain *d;
+	char *dom = NULL, *id;
+	unsigned long dom_id;
+
+next:
+	if (!line || line[0] == '\0')
+		return 0;
+
+	dom = strsep(&line, ";");
+	id = strsep(&dom, "=");
+	if (!dom || kstrtoul(id, 10, &dom_id)) {
+		rdt_last_cmd_puts("Missing '=' or non-numeric domain\n");
+		return -EINVAL;
+	}
+
+	dom = strim(dom);
+	list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
+		if (d->hdr.id == dom_id) {
+			data.buf = dom;
+			data.mode = RDT_MODE_SHAREABLE;
+			data.closid = closid;
+			if (parse_cbm(&data, s, d))
+				return -EINVAL;
+			goto next;
+		}
+	}
+	return -EINVAL;
+}
+
+static ssize_t resctrl_io_alloc_cbm_write(struct kernfs_open_file *of,
+					  char *buf, size_t nbytes, loff_t off)
+{
+	struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+	struct rdt_resource *r = s->res;
+	u32 io_alloc_closid;

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

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+	int ret = 0;
+
+	/* Valid input requires a trailing newline */
+	if (nbytes == 0 || buf[nbytes - 1] != '\n')
+		return -EINVAL;
+
+	buf[nbytes - 1] = '\0';
+
+	if (!r->cache.io_alloc_capable) {
+		rdt_last_cmd_puts("io_alloc feature is not supported on the resource\n");

rdt_last_cmd_puts() requires rdtgroup_mutex to be held.

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

Quoted 13 lines
fs/resctrl/rdtgroup.c +13 -0
+		return -EINVAL;
+	}
+
+	cpus_read_lock();
+	mutex_lock(&rdtgroup_mutex);
+
+	rdt_last_cmd_clear();
+	rdt_staged_configs_clear();
+
+	if (!resctrl_arch_get_io_alloc_enabled(r)) {
+		rdt_last_cmd_puts("io_alloc feature is not enabled\n");
+		ret = -EINVAL;
+		goto cbm_write_out;

can just be "out"

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

Quoted 4 lines
fs/resctrl/rdtgroup.c +4 -0
+	}
+
+	io_alloc_closid = resctrl_io_alloc_closid_get(r);
+	if (io_alloc_closid < 0) {

Similar to other places, since this is preceded by resctrl_arch_get_io_alloc_enabled(r) passing the io_alloc_closid has to be valid and can use proposed resctrl_io_alloc_closid() helper to simplify the code.

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

Quoted 7 lines
fs/resctrl/rdtgroup.c +7 -0
+		rdt_last_cmd_puts("Max CLOSID to support io_alloc is not available\n");
+		ret = -EINVAL;
+		goto cbm_write_out;
+	}
+
+	ret = resctrl_io_alloc_parse_line(buf, r, resctrl_schema_io_alloc(s),
+					  io_alloc_closid);

Here too I think both schemata needs to be updated.

Quoted 18 lines
fs/resctrl/rdtgroup.c +13 -0
+	if (ret)
+		goto cbm_write_out;
+
+	ret = resctrl_arch_update_domains(r, io_alloc_closid);
+
+cbm_write_out:
+	rdt_staged_configs_clear();
+	mutex_unlock(&rdtgroup_mutex);
+	cpus_read_unlock();
+
+	return ret ?: nbytes;
+}
+
 /* rdtgroup information files for one cache resource. */
 static struct rftype res_common_files[] = {
 	{
@@ -2198,9 +2284,10 @@ static struct rftype res_common_files[] = {
 	},

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

Quoted 10 lines
fs/resctrl/rdtgroup.c +2 -1
 	{
 		.name		= "io_alloc_cbm",
-		.mode		= 0444,
+		.mode		= 0644,
 		.kf_ops		= &rdtgroup_kf_single_ops,
 		.seq_show	= resctrl_io_alloc_cbm_show,
+		.write		= resctrl_io_alloc_cbm_write,
 	},
 	{
 		.name		= "mba_MBps_event",

Reinette

#29 lore raw

Re: [PATCH v6 8/8] fs/resctrl: Introduce interface to modify io_alloc Capacity Bit Masks

Hi Reinette,

Quoted 6 lines · Reinette Chatre

Hi Babu,

Quoted 1 line · Babu Moger

"io_alloc" feature is a mechanism that enables direct insertion of data

""io_alloc" feature is a mechanism that enables" -> ""io_alloc" feature enables"

Sure.

Quoted 5 lines
Quoted 2 lines

from I/O devices into the L3 cache. By directly caching data from I/O

Drop L3

Sure.

Quoted 7 lines
Quoted 5 lines

devices rather than first storing the I/O data in DRAM, it reduces the demands on DRAM bandwidth and reduces latency to the processor consuming the I/O data.

"io_alloc" feature uses the highest CLOSID to route the traffic from I/O

How is the CLOSID related here?

Will remove it.

Quoted 24 lines
Quoted 6 lines

devices. Provide the interface to modify io_alloc CBMs (Capacity Bit Mask) when feature is enabled.

---

...

Quoted 15 lines
---
  Documentation/filesystems/resctrl.rst | 13 ++++
  fs/resctrl/ctrlmondata.c              |  4 +-
  fs/resctrl/internal.h                 |  2 +
  fs/resctrl/rdtgroup.c                 | 89 ++++++++++++++++++++++++++-
  4 files changed, 105 insertions(+), 3 deletions(-)
Documentation/filesystems/resctrl.rst +0 -0
index b31748ec8c61..ae1157dcb4a3 100644
@@ -181,6 +181,19 @@ related to allocation:
  			# cat /sys/fs/resctrl/info/L3/io_alloc_cbm
  			0=ffff;1=ffff
 
Quoted 17 lines

Documentation/filesystems/resctrl.rst related to allocation: · line 195

Quoted 12 lines
Documentation/filesystems/resctrl.rst +12 -0
+		CBM can be configured by writing to the interface.
+
+		Example::
+
+			# echo 1=FF > /sys/fs/resctrl/info/L3/io_alloc_cbm
+			# cat /sys/fs/resctrl/info/L3/io_alloc_cbm
+			0=ffff;1=00ff
+
+		When CDP is enabled, io_alloc directs traffic using the highest CLOSID
+		linked to an L3CODE resource. Although CBMs can be accessed through
+		either L3CODE or L3DATA resources, any updates to the schemata are
+		always routed through L3CODE.

Please do not commit resctrl to this implementation by documenting it as part of user interface. Could snippet about CDP I shared in patch 6 be placed here as a replacement? Not the usage of *may* to keep implementation options open.

Sure. Yea. Already added in show().

Quoted 83 lines
Quoted 83 lines
Documentation/filesystems/resctrl.rst +1 -0
+
 
  Memory bandwidth(MB) subdirectory contains the following files
  with respect to allocation:
fs/resctrl/ctrlmondata.c +2 -2
index 6409637b4de6..f3e5e697945c 100644
@@ -148,8 +148,8 @@ static bool cbm_validate(char *buf, u32 *data, struct rdt_resource *r)
   * Read one cache bit mask (hex). Check that it is valid for the current
   * resource type.
   */
-static int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
-		     struct rdt_ctrl_domain *d)
+int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
+	      struct rdt_ctrl_domain *d)
  {
  	enum rdtgrp_mode mode = data->mode;
  	struct resctrl_staged_config *cfg;
fs/resctrl/internal.h +2 -0
index 10a3188ffa54..755f23934295 100644
@@ -382,6 +382,8 @@ bool closid_allocated(unsigned int closid);
  int resctrl_find_cleanest_closid(void);
  void show_doms(struct seq_file *s, struct resctrl_schema *schema,
  	       char *name, int closid);
+int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
+	      struct rdt_ctrl_domain *d);
 
  #ifdef CONFIG_RESCTRL_FS_PSEUDO_LOCK
  int rdtgroup_locksetup_enter(struct rdtgroup *rdtgrp);
fs/resctrl/rdtgroup.c +43 -0
index 0c2d2cf4baa1..f6c44fae4b72 100644
@@ -2037,6 +2037,92 @@ static int resctrl_io_alloc_cbm_show(struct kernfs_open_file *of,
  	return ret;
  }
 
+static int resctrl_io_alloc_parse_line(char *line,  struct rdt_resource *r,
+				       struct resctrl_schema *s, u32 closid)
+{
+	struct rdt_parse_data data;
+	struct rdt_ctrl_domain *d;
+	char *dom = NULL, *id;
+	unsigned long dom_id;
+
+next:
+	if (!line || line[0] == '\0')
+		return 0;
+
+	dom = strsep(&line, ";");
+	id = strsep(&dom, "=");
+	if (!dom || kstrtoul(id, 10, &dom_id)) {
+		rdt_last_cmd_puts("Missing '=' or non-numeric domain\n");
+		return -EINVAL;
+	}
+
+	dom = strim(dom);
+	list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
+		if (d->hdr.id == dom_id) {
+			data.buf = dom;
+			data.mode = RDT_MODE_SHAREABLE;
+			data.closid = closid;
+			if (parse_cbm(&data, s, d))
+				return -EINVAL;
+			goto next;
+		}
+	}
+	return -EINVAL;
+}
+
+static ssize_t resctrl_io_alloc_cbm_write(struct kernfs_open_file *of,
+					  char *buf, size_t nbytes, loff_t off)
+{
+	struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+	struct rdt_resource *r = s->res;
+	u32 io_alloc_closid;
+	int ret = 0;
+
+	/* Valid input requires a trailing newline */
+	if (nbytes == 0 || buf[nbytes - 1] != '\n')
Quoted 8 lines

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

Quoted 6 lines
fs/resctrl/rdtgroup.c +6 -0
+		return -EINVAL;
+
+	buf[nbytes - 1] = '\0';
+
+	if (!r->cache.io_alloc_capable) {
+		rdt_last_cmd_puts("io_alloc feature is not supported on the resource\n");

rdt_last_cmd_puts() requires rdtgroup_mutex to be held.

Sure.

Quoted 16 lines
Quoted 4 lines
fs/resctrl/rdtgroup.c +3 -0
+		return -EINVAL;
+	}
+

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

Quoted 10 lines
fs/resctrl/rdtgroup.c +10 -0
+	cpus_read_lock();
+	mutex_lock(&rdtgroup_mutex);
+
+	rdt_last_cmd_clear();
+	rdt_staged_configs_clear();
+
+	if (!resctrl_arch_get_io_alloc_enabled(r)) {
+		rdt_last_cmd_puts("io_alloc feature is not enabled\n");
+		ret = -EINVAL;
+		goto cbm_write_out;

can just be "out"

Sure.

Quoted 9 lines

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

Quoted 5 lines
fs/resctrl/rdtgroup.c +4 -0
+	}
+
+	io_alloc_closid = resctrl_io_alloc_closid_get(r);
+	if (io_alloc_closid < 0) {

Similar to other places, since this is preceded by resctrl_arch_get_io_alloc_enabled(r) passing the io_alloc_closid has to be valid and can use proposed resctrl_io_alloc_closid() helper to simplify the code.

Yes. Check not required.

Quoted 10 lines

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

Quoted 8 lines
fs/resctrl/rdtgroup.c +7 -0
+		rdt_last_cmd_puts("Max CLOSID to support io_alloc is not available\n");
+		ret = -EINVAL;
+		goto cbm_write_out;
+	}
+
+	ret = resctrl_io_alloc_parse_line(buf, r, resctrl_schema_io_alloc(s),
+					  io_alloc_closid);

Here too I think both schemata needs to be updated.

Yes. Added it.

Quoted 23 lines
Quoted 23 lines
fs/resctrl/rdtgroup.c +14 -1
+	if (ret)
+		goto cbm_write_out;
+
+	ret = resctrl_arch_update_domains(r, io_alloc_closid);
+
+cbm_write_out:
+	rdt_staged_configs_clear();
+	mutex_unlock(&rdtgroup_mutex);
+	cpus_read_unlock();
+
+	return ret ?: nbytes;
+}
+
  /* rdtgroup information files for one cache resource. */
  static struct rftype res_common_files[] = {
  	{
@@ -2198,9 +2284,10 @@ static struct rftype res_common_files[] = {
  	},
  	{
  		.name		= "io_alloc_cbm",
-		.mode		= 0444,
+		.mode		= 0644,
Quoted 9 lines

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

Quoted 6 lines
fs/resctrl/rdtgroup.c +1 -0
  		.kf_ops		= &rdtgroup_kf_single_ops,
  		.seq_show	= resctrl_io_alloc_cbm_show,
+		.write		= resctrl_io_alloc_cbm_write,
  	},
  	{
  		.name		= "mba_MBps_event",

Reinette

Thanks
Babu