* [PATCH v11 00/23] Allow AET to use PMT as loadable module
@ 2026-08-31 17:43 Tony Luck
2026-08-31 17:43 ` [PATCH v11 01/23] x86/resctrl: Give better names to X86_FEATURE flags for monitoring Tony Luck
` (23 more replies)
0 siblings, 24 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:43 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
Requiring INTEL_PMT_TELEMETRY=y to enable AET is a functional workaround
to enable enumeration of Application Energy Telemetry (AET) events, but
unacceptable to many users. It results in increased configuration complexity,
increased kernel memory footprint and inability to patch problems by unloading
a module and loading an updated version.
Add a registration function to the AET code that can be used by
INTEL_PMT_TELEMETRY to provide the enumeration functions.
INTEL_PMT_TELEMETRY can be loaded/unloaded independently of
resctrl file system mount/unmount. Perform enumeration on
every mount and cleanup on every unmount.
Patch series based on v7.3-rc1
Signed-off-by: Tony Luck <tony.luck@intel.com>
Changes since v10:
Link: https://lore.kernel.org/all/20260729172752.11561-1-tony.luck@intel.com/
Several cleanups prepended to the series based on v10 discussion in
patches 1..8. See individual patches for changes to each part.
Tony Luck (23):
x86/resctrl: Give better names to X86_FEATURE flags for monitoring
x86/resctrl: Check if monitoring features are enabled
x86/resctrl: Enumerate monitor features in rdt_get_l3_mon_config()
x86/resctrl: Apply Intel MBM quirk from rdt_get_l3_mon_config()
x86/resctrl: Delete resctrl_cpu_detect()
arm,x86,fs/resctrl: Replace architecture
resctrl_arch_{alloc,mon}_capable()
x86/resctrl: Add special case for Intel Haswell enumeration
x86/resctrl: Delete rdt_alloc_capable and rdt_mon_capable
fs/resctrl: Remove redundant calls to resctrl_mon_capable()
x86/resctrl: Honor rdt=perf option to force enable AET perf events
fs/resctrl: Add interface to disable a monitor event
arm,x86,fs/resctrl: Handle change in number of RMIDs on each mount
x86/resctrl: Handle systems when AET is the only resource
x86/resctrl: Enforce system RMID limit on AET event groups
x86/resctrl: Add PMT registration API for AET enumeration callbacks
platform/x86/intel/pmt: Register enumeration functions with resctrl
arm,x86/resctrl: Resolve INTEL_PMT_TELEMETRY symbols at runtime
fs/resctrl: Call arch code for every mount
x86/resctrl: Export interface to report telemetry unbind/remove
platform/x86/intel/pmt: Inform resctrl when MMIO maps are being
removed
x86/resctrl: Require 64-bit x86 for resctrl support
x86/resctrl: Simplify Kconfig options for resctrl
x86/resctrl: Document telemetry mount timing caveat
Documentation/arch/x86/cpuinfo.rst | 2 +-
Documentation/filesystems/resctrl.rst | 60 +++++++-
include/linux/arm_mpam.h | 3 -
include/linux/intel_vsec.h | 14 ++
include/linux/resctrl.h | 74 +++++++++-
arch/x86/include/asm/cpufeatures.h | 4 +-
arch/x86/include/asm/processor.h | 4 -
arch/x86/include/asm/resctrl.h | 24 +--
arch/x86/kernel/cpu/resctrl/internal.h | 24 +--
tools/arch/x86/include/asm/cpufeatures.h | 4 +-
arch/x86/kernel/cpu/amd.c | 3 -
arch/x86/kernel/cpu/cpuid-deps.c | 8 +-
arch/x86/kernel/cpu/hygon.c | 3 -
arch/x86/kernel/cpu/intel.c | 7 -
arch/x86/kernel/cpu/resctrl/core.c | 162 +++++++++++----------
arch/x86/kernel/cpu/resctrl/intel_aet.c | 132 +++++++++++++++--
arch/x86/kernel/cpu/resctrl/monitor.c | 71 ++++++---
arch/x86/kernel/cpu/scattered.c | 2 +-
drivers/platform/x86/intel/pmt/telemetry.c | 46 +++++-
drivers/resctrl/mpam_resctrl.c | 44 +++---
fs/resctrl/monitor.c | 112 ++++++++++----
fs/resctrl/pseudo_lock.c | 6 +-
fs/resctrl/rdtgroup.c | 76 ++++++----
arch/x86/Kconfig | 15 +-
arch/x86/kernel/cpu/resctrl/Makefile | 2 +-
25 files changed, 620 insertions(+), 282 deletions(-)
base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
--
2.55.0
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v11 01/23] x86/resctrl: Give better names to X86_FEATURE flags for monitoring
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
@ 2026-08-31 17:43 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 02/23] x86/resctrl: Check if monitoring features are enabled Tony Luck
` (22 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:43 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
The feature flags for enumeration of Resource Director Technology (RDT)
capabilities were chosen when the only feature was LLC cache occupancy
monitoring and they were given names using the abbreviation CQM for
Cache Quality of Service Monitoring.
Additional monitoring features have been added to CPUs and the names
are now more likely to confuse than inform the purpose of these flags.
Rename X86_FEATURE_CQM to X86_FEATURE_RDT_M (to match the Intel Software
Developer's Manual, and for symmetry with X86_FEATURE_RDT_A).
Rename X86_FEATURE_CQM_LLC to X86_FEATURE_L3_MON since it enumerates
that some L3 monitoring features may be present.
Add missing dependency to cpuid_deps[].
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
New patch. Fix FEATURE options
Documentation/arch/x86/cpuinfo.rst | 2 +-
arch/x86/include/asm/cpufeatures.h | 4 ++--
tools/arch/x86/include/asm/cpufeatures.h | 4 ++--
arch/x86/kernel/cpu/cpuid-deps.c | 8 +++++---
arch/x86/kernel/cpu/resctrl/core.c | 2 +-
arch/x86/kernel/cpu/scattered.c | 2 +-
6 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/Documentation/arch/x86/cpuinfo.rst b/Documentation/arch/x86/cpuinfo.rst
index 17fce95367e6..5aa4e9d2ad23 100644
--- a/Documentation/arch/x86/cpuinfo.rst
+++ b/Documentation/arch/x86/cpuinfo.rst
@@ -96,7 +96,7 @@ Flags can be from scattered CPUID-based features
Hardware features enumerated in sparsely populated CPUID leaves get
software-defined values. Still, CPUID needs to be queried to determine
if a given feature is present. This is done in init_scattered_cpuid_features().
-For instance, X86_FEATURE_CQM_LLC is defined as 11*32 + 0 and its presence is
+For instance, X86_FEATURE_L3_MON is defined as 11*32 + 0 and its presence is
checked at runtime in the respective CPUID leaf [EAX=f, ECX=0] bit EDX[1].
The intent of scattering CPUID leaves is to not bloat struct
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index f70ee74b5f92..6a7f0adb123e 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -252,7 +252,7 @@
#define X86_FEATURE_ERMS ( 9*32+ 9) /* "erms" Enhanced REP MOVSB/STOSB instructions */
#define X86_FEATURE_INVPCID ( 9*32+10) /* "invpcid" Invalidate Processor Context ID */
#define X86_FEATURE_RTM ( 9*32+11) /* "rtm" Restricted Transactional Memory */
-#define X86_FEATURE_CQM ( 9*32+12) /* "cqm" Cache QoS Monitoring */
+#define X86_FEATURE_RDT_M ( 9*32+12) /* "cqm" Resource Director Technology Monitoring */
#define X86_FEATURE_ZERO_FCS_FDS ( 9*32+13) /* Zero out FPU CS and FPU DS */
#define X86_FEATURE_MPX ( 9*32+14) /* "mpx" Memory Protection Extension */
#define X86_FEATURE_RDT_A ( 9*32+15) /* "rdt_a" Resource Director Technology Allocation */
@@ -285,7 +285,7 @@
*
* Reuse free bits when adding new feature flags!
*/
-#define X86_FEATURE_CQM_LLC (11*32+ 0) /* "cqm_llc" LLC QoS if 1 */
+#define X86_FEATURE_L3_MON (11*32+ 0) /* "cqm_llc" LLC QoS if 1 */
#define X86_FEATURE_CQM_OCCUP_LLC (11*32+ 1) /* "cqm_occup_llc" LLC occupancy monitoring */
#define X86_FEATURE_CQM_MBM_TOTAL (11*32+ 2) /* "cqm_mbm_total" LLC Total MBM monitoring */
#define X86_FEATURE_CQM_MBM_LOCAL (11*32+ 3) /* "cqm_mbm_local" LLC Local MBM monitoring */
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
index 6547c0aee45b..9b71a7663e26 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -242,7 +242,7 @@
#define X86_FEATURE_ERMS ( 9*32+ 9) /* "erms" Enhanced REP MOVSB/STOSB instructions */
#define X86_FEATURE_INVPCID ( 9*32+10) /* "invpcid" Invalidate Processor Context ID */
#define X86_FEATURE_RTM ( 9*32+11) /* "rtm" Restricted Transactional Memory */
-#define X86_FEATURE_CQM ( 9*32+12) /* "cqm" Cache QoS Monitoring */
+#define X86_FEATURE_RDT_M ( 9*32+12) /* "cqm" Resource Director Technology Monitoring */
#define X86_FEATURE_ZERO_FCS_FDS ( 9*32+13) /* Zero out FPU CS and FPU DS */
#define X86_FEATURE_MPX ( 9*32+14) /* "mpx" Memory Protection Extension */
#define X86_FEATURE_RDT_A ( 9*32+15) /* "rdt_a" Resource Director Technology Allocation */
@@ -275,7 +275,7 @@
*
* Reuse free bits when adding new feature flags!
*/
-#define X86_FEATURE_CQM_LLC (11*32+ 0) /* "cqm_llc" LLC QoS if 1 */
+#define X86_FEATURE_L3_MON (11*32+ 0) /* "cqm_llc" LLC QoS if 1 */
#define X86_FEATURE_CQM_OCCUP_LLC (11*32+ 1) /* "cqm_occup_llc" LLC occupancy monitoring */
#define X86_FEATURE_CQM_MBM_TOTAL (11*32+ 2) /* "cqm_mbm_total" LLC Total MBM monitoring */
#define X86_FEATURE_CQM_MBM_LOCAL (11*32+ 3) /* "cqm_mbm_local" LLC Local MBM monitoring */
diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c
index 99801e844b30..58482c264b76 100644
--- a/arch/x86/kernel/cpu/cpuid-deps.c
+++ b/arch/x86/kernel/cpu/cpuid-deps.c
@@ -67,9 +67,11 @@ static const struct cpuid_dep cpuid_deps[] = {
{ X86_FEATURE_AVX512_4FMAPS, X86_FEATURE_AVX512F },
{ X86_FEATURE_AVX512_VPOPCNTDQ, X86_FEATURE_AVX512F },
{ X86_FEATURE_AVX512_VP2INTERSECT, X86_FEATURE_AVX512VL },
- { X86_FEATURE_CQM_OCCUP_LLC, X86_FEATURE_CQM_LLC },
- { X86_FEATURE_CQM_MBM_TOTAL, X86_FEATURE_CQM_LLC },
- { X86_FEATURE_CQM_MBM_LOCAL, X86_FEATURE_CQM_LLC },
+ { X86_FEATURE_L3_MON, X86_FEATURE_RDT_M },
+ { X86_FEATURE_CQM_OCCUP_LLC, X86_FEATURE_L3_MON },
+ { X86_FEATURE_CQM_MBM_TOTAL, X86_FEATURE_L3_MON },
+ { X86_FEATURE_CQM_MBM_LOCAL, X86_FEATURE_L3_MON },
+ { X86_FEATURE_ABMC, X86_FEATURE_L3_MON },
{ X86_FEATURE_BMEC, X86_FEATURE_CQM_MBM_TOTAL },
{ X86_FEATURE_BMEC, X86_FEATURE_CQM_MBM_LOCAL },
{ X86_FEATURE_SDCIAE, X86_FEATURE_CAT_L3 },
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index 55214d6fdc49..2435eddd24eb 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -1078,7 +1078,7 @@ static enum cpuhp_state rdt_online;
/* Runs once on the BSP during boot. */
void resctrl_cpu_detect(struct cpuinfo_x86 *c)
{
- if (!cpu_has(c, X86_FEATURE_CQM_LLC) && !cpu_has(c, X86_FEATURE_ABMC)) {
+ if (!cpu_has(c, X86_FEATURE_L3_MON) && !cpu_has(c, X86_FEATURE_ABMC)) {
c->x86_cache_max_rmid = -1;
c->x86_cache_occ_scale = -1;
c->x86_cache_mbm_width_offset = -1;
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index 8665a6474806..7e5490e1e537 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -32,7 +32,7 @@ static const struct cpuid_bit cpuid_bits[] = {
{ X86_FEATURE_APX, CPUID_EDX, 21, 0x00000007, 1 },
{ X86_FEATURE_RRSBA_CTRL, CPUID_EDX, 2, 0x00000007, 2 },
{ X86_FEATURE_BHI_CTRL, CPUID_EDX, 4, 0x00000007, 2 },
- { X86_FEATURE_CQM_LLC, CPUID_EDX, 1, 0x0000000f, 0 },
+ { X86_FEATURE_L3_MON, CPUID_EDX, 1, 0x0000000f, 0 },
{ X86_FEATURE_CQM_OCCUP_LLC, CPUID_EDX, 0, 0x0000000f, 1 },
{ X86_FEATURE_CQM_MBM_TOTAL, CPUID_EDX, 1, 0x0000000f, 1 },
{ X86_FEATURE_CQM_MBM_LOCAL, CPUID_EDX, 2, 0x0000000f, 1 },
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 02/23] x86/resctrl: Check if monitoring features are enabled
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
2026-08-31 17:43 ` [PATCH v11 01/23] x86/resctrl: Give better names to X86_FEATURE flags for monitoring Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 03/23] x86/resctrl: Enumerate monitor features in rdt_get_l3_mon_config() Tony Luck
` (21 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
Both Intel and AMD manuals say that software must first check
CPUID(0x7,0x0).EBX[12] to see if any monitoring features are enabled
before checking for specific features enabled in subleaves.
Each of the L3-based monitoring features is gated by X86_FEATURE_L3_MON
Add check feature bits.
Fixes: cbc82b172638 ("x86: Add support for Intel Cache QoS Monitoring (CQM) detection")
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
New patch
arch/x86/kernel/cpu/resctrl/core.c | 33 ++++++++++++++++++------------
1 file changed, 20 insertions(+), 13 deletions(-)
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index 2435eddd24eb..fcbecf677914 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -968,20 +968,27 @@ static __init bool get_rdt_mon_resources(void)
struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3].r_resctrl;
bool ret = false;
- if (rdt_cpu_has(X86_FEATURE_CQM_OCCUP_LLC)) {
- resctrl_enable_mon_event(QOS_L3_OCCUP_EVENT_ID, false, 0, NULL);
- ret = true;
- }
- if (rdt_cpu_has(X86_FEATURE_CQM_MBM_TOTAL)) {
- resctrl_enable_mon_event(QOS_L3_MBM_TOTAL_EVENT_ID, false, 0, NULL);
- ret = true;
- }
- if (rdt_cpu_has(X86_FEATURE_CQM_MBM_LOCAL)) {
- resctrl_enable_mon_event(QOS_L3_MBM_LOCAL_EVENT_ID, false, 0, NULL);
- ret = true;
+ /* Any monitoring at all? */
+ if (!cpu_feature_enabled(X86_FEATURE_RDT_M))
+ return false;
+
+ /* Any of the L3 monitoring features? */
+ if (cpu_feature_enabled(X86_FEATURE_L3_MON)) {
+ if (rdt_cpu_has(X86_FEATURE_CQM_OCCUP_LLC)) {
+ resctrl_enable_mon_event(QOS_L3_OCCUP_EVENT_ID, false, 0, NULL);
+ ret = true;
+ }
+ if (rdt_cpu_has(X86_FEATURE_CQM_MBM_TOTAL)) {
+ resctrl_enable_mon_event(QOS_L3_MBM_TOTAL_EVENT_ID, false, 0, NULL);
+ ret = true;
+ }
+ if (rdt_cpu_has(X86_FEATURE_CQM_MBM_LOCAL)) {
+ resctrl_enable_mon_event(QOS_L3_MBM_LOCAL_EVENT_ID, false, 0, NULL);
+ ret = true;
+ }
+ if (rdt_cpu_has(X86_FEATURE_ABMC))
+ ret = true;
}
- if (rdt_cpu_has(X86_FEATURE_ABMC))
- ret = true;
if (!ret)
return false;
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 03/23] x86/resctrl: Enumerate monitor features in rdt_get_l3_mon_config()
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
2026-08-31 17:43 ` [PATCH v11 01/23] x86/resctrl: Give better names to X86_FEATURE flags for monitoring Tony Luck
2026-08-31 17:44 ` [PATCH v11 02/23] x86/resctrl: Check if monitoring features are enabled Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 04/23] x86/resctrl: Apply Intel MBM quirk from rdt_get_l3_mon_config() Tony Luck
` (20 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
The original implementation of Intel Cache QoS Monitoring (CQM) planned
to integrate with the "perf" and "cgroup" subsystems. With that plan it
made sense for parameters from CPUID to be stored in fields of the
cpuinfo_x86 structure. But that plan was abandoned and the resctrl file
system user interface replaced it.
Enumerate the L3 monitoring features in rdt_get_l3_mon_config().
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
New patch
arch/x86/include/asm/resctrl.h | 9 ++++----
arch/x86/kernel/cpu/resctrl/monitor.c | 32 ++++++++++++++++++++++++---
2 files changed, 33 insertions(+), 8 deletions(-)
diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h
index 8f6edcdcfd87..9bfa9b14002b 100644
--- a/arch/x86/include/asm/resctrl.h
+++ b/arch/x86/include/asm/resctrl.h
@@ -44,6 +44,7 @@ DECLARE_PER_CPU(struct resctrl_pqr_state, pqr_state);
extern bool rdt_alloc_capable;
extern bool rdt_mon_capable;
+extern unsigned int __ro_after_init rdt_l3_mon_scale;
DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
DECLARE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
@@ -132,11 +133,9 @@ static inline void __resctrl_sched_in(struct task_struct *tsk)
static inline unsigned int resctrl_arch_round_mon_val(unsigned int val)
{
- unsigned int scale = boot_cpu_data.x86_cache_occ_scale;
-
- /* h/w works in units of "boot_cpu_data.x86_cache_occ_scale" */
- val /= scale;
- return val * scale;
+ /* Round down to nearest h/w monitoring unit */
+ val /= rdt_l3_mon_scale;
+ return val * rdt_l3_mon_scale;
}
static inline void resctrl_arch_set_cpu_default_closid_rmid(int cpu, u32 closid,
diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c
index 3838e0a13d36..0c2aa20148a1 100644
--- a/arch/x86/kernel/cpu/resctrl/monitor.c
+++ b/arch/x86/kernel/cpu/resctrl/monitor.c
@@ -32,6 +32,11 @@
*/
bool rdt_mon_capable;
+/*
+ * Scale factor to convert L3 monitor events to bytes.
+ */
+unsigned int __ro_after_init rdt_l3_mon_scale;
+
#define CF(cf) ((unsigned long)(1048576 * (cf) + 0.5))
static int snc_nodes_per_l3_cache = 1;
@@ -418,16 +423,37 @@ static __init int snc_get_config(void)
int __init rdt_get_l3_mon_config(struct rdt_resource *r)
{
- unsigned int mbm_offset = boot_cpu_data.x86_cache_mbm_width_offset;
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
+ unsigned int mbm_offset;
unsigned int threshold;
u32 eax, ebx, ecx, edx;
+ u32 num_rmid;
+
+ /* QoS sub-leaf, EAX=0Fh, ECX=1 */
+ cpuid_count(0xf, 1, &eax, &ebx, &ecx, &edx);
+ mbm_offset = eax & 0xff;
+ rdt_l3_mon_scale = ebx;
+ num_rmid = ecx + 1;
+
+ if (!mbm_offset) {
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_AMD:
+ mbm_offset = MBM_CNTR_WIDTH_OFFSET_AMD;
+ break;
+ case X86_VENDOR_HYGON:
+ mbm_offset = MBM_CNTR_WIDTH_OFFSET_HYGON;
+ break;
+ default:
+ /* Leave mbm_offset as 0 */
+ break;
+ }
+ }
snc_nodes_per_l3_cache = snc_get_config();
resctrl_rmid_realloc_limit = boot_cpu_data.x86_cache_size * 1024;
- hw_res->mon_scale = boot_cpu_data.x86_cache_occ_scale / snc_nodes_per_l3_cache;
- r->mon.num_rmid = (boot_cpu_data.x86_cache_max_rmid + 1) / snc_nodes_per_l3_cache;
+ hw_res->mon_scale = rdt_l3_mon_scale / snc_nodes_per_l3_cache;
+ r->mon.num_rmid = num_rmid / snc_nodes_per_l3_cache;
hw_res->mbm_width = MBM_CNTR_WIDTH_BASE;
if (mbm_offset > 0 && mbm_offset <= MBM_CNTR_WIDTH_OFFSET_MAX)
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 04/23] x86/resctrl: Apply Intel MBM quirk from rdt_get_l3_mon_config()
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (2 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 03/23] x86/resctrl: Enumerate monitor features in rdt_get_l3_mon_config() Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 05/23] x86/resctrl: Delete resctrl_cpu_detect() Tony Luck
` (19 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
The Intel quirk to adjust Memory Bandwidth Monitoring (MBM) values on
certain CPUs is applied early, before discovering if MBM is supported.
Move the call to rdt_get_l3_mon_config(), but keep the decision on
whether it is needed in __check_quirks_intel() with all the other
model specific tests.
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
New patch
arch/x86/kernel/cpu/resctrl/internal.h | 4 +--
arch/x86/kernel/cpu/resctrl/core.c | 2 +-
arch/x86/kernel/cpu/resctrl/monitor.c | 35 +++++++++++++++-----------
3 files changed, 23 insertions(+), 18 deletions(-)
diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h
index e3cfa0c10e92..e46eb9a4c725 100644
--- a/arch/x86/kernel/cpu/resctrl/internal.h
+++ b/arch/x86/kernel/cpu/resctrl/internal.h
@@ -151,6 +151,8 @@ static inline struct rdt_hw_resource *resctrl_to_arch_res(struct rdt_resource *r
extern struct rdt_hw_resource rdt_resources_all[];
+extern bool __initdata intel_rdt_mbm_need_quirk;
+
void arch_mon_domain_online(struct rdt_resource *r, struct rdt_l3_mon_domain *d);
/* CPUID.(EAX=10H, ECX=ResID=1).EAX */
@@ -228,8 +230,6 @@ int rdt_get_l3_mon_config(struct rdt_resource *r);
bool rdt_cpu_has(int flag);
-void __init intel_rdt_mbm_apply_quirk(void);
-
void rdt_domain_reconfigure_cdp(struct rdt_resource *r);
void resctrl_arch_mbm_cntr_assign_set_one(struct rdt_resource *r);
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index fcbecf677914..0799dbfc7a72 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -1010,7 +1010,7 @@ static __init void __check_quirks_intel(void)
set_rdt_options("!l3cat");
fallthrough;
case INTEL_BROADWELL_X:
- intel_rdt_mbm_apply_quirk();
+ intel_rdt_mbm_need_quirk = true;
break;
}
}
diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c
index 0c2aa20148a1..0bce199a5f7b 100644
--- a/arch/x86/kernel/cpu/resctrl/monitor.c
+++ b/arch/x86/kernel/cpu/resctrl/monitor.c
@@ -37,6 +37,8 @@ bool rdt_mon_capable;
*/
unsigned int __ro_after_init rdt_l3_mon_scale;
+bool __initdata intel_rdt_mbm_need_quirk;
+
#define CF(cf) ((unsigned long)(1048576 * (cf) + 0.5))
static int snc_nodes_per_l3_cache = 1;
@@ -51,7 +53,7 @@ static int snc_nodes_per_l3_cache = 1;
* 1. The threshold 0 is changed to rmid count - 1 so don't do correction
* for the case.
* 2. MBM total and local correction table indexed by core counter which is
- * equal to (x86_cache_max_rmid + 1) / 8 - 1 and is from 0 up to 27.
+ * equal to r->mon.num_rmid / 8 - 1 and is from 0 up to 27.
* 3. The correction factor is normalized to 2^20 (1048576) so it's faster
* to calculate corrected value by shifting:
* corrected_value = (original_value * correction_factor) >> 20
@@ -421,6 +423,20 @@ static __init int snc_get_config(void)
return ret;
}
+static void __init intel_rdt_mbm_apply_quirk(u32 num_rmid)
+{
+ int cf_index;
+
+ cf_index = num_rmid / 8 - 1;
+ if (cf_index >= ARRAY_SIZE(mbm_cf_table)) {
+ pr_info("No MBM correction factor available\n");
+ return;
+ }
+
+ mbm_cf_rmidthreshold = mbm_cf_table[cf_index].rmidthreshold;
+ mbm_cf = mbm_cf_table[cf_index].cf;
+}
+
int __init rdt_get_l3_mon_config(struct rdt_resource *r)
{
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
@@ -500,25 +516,14 @@ int __init rdt_get_l3_mon_config(struct rdt_resource *r)
hw_res->mbm_cntr_assign_enabled = true;
}
+ if (intel_rdt_mbm_need_quirk)
+ intel_rdt_mbm_apply_quirk(r->mon.num_rmid);
+
r->mon_capable = true;
return 0;
}
-void __init intel_rdt_mbm_apply_quirk(void)
-{
- int cf_index;
-
- cf_index = (boot_cpu_data.x86_cache_max_rmid + 1) / 8 - 1;
- if (cf_index >= ARRAY_SIZE(mbm_cf_table)) {
- pr_info("No MBM correction factor available\n");
- return;
- }
-
- mbm_cf_rmidthreshold = mbm_cf_table[cf_index].rmidthreshold;
- mbm_cf = mbm_cf_table[cf_index].cf;
-}
-
static void resctrl_abmc_set_one_amd(void *arg)
{
bool *enable = arg;
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 05/23] x86/resctrl: Delete resctrl_cpu_detect()
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (3 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 04/23] x86/resctrl: Apply Intel MBM quirk from rdt_get_l3_mon_config() Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 06/23] arm,x86,fs/resctrl: Replace architecture resctrl_arch_{alloc,mon}_capable() Tony Luck
` (18 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck,
Borislav Petkov (AMD)
cpuinfo_x86::x86_cache_{max_rmid,occ_scale,mbm_width_offset} are no
longer used.
Delete resctrl_cpu_detect() and the fields from struct cpuinfo_x86.
Signed-off-by: Tony Luck <tony.luck@intel.com>
Acked-by: Borislav Petkov (AMD) <bp@alien8.de>
---
v11:
New patch
arch/x86/include/asm/processor.h | 4 ---
arch/x86/include/asm/resctrl.h | 3 ---
arch/x86/kernel/cpu/amd.c | 3 ---
arch/x86/kernel/cpu/hygon.c | 3 ---
arch/x86/kernel/cpu/intel.c | 7 -----
arch/x86/kernel/cpu/resctrl/core.c | 42 ------------------------------
6 files changed, 62 deletions(-)
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index ec9db0dfa0df..4deb88c61c94 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -185,10 +185,6 @@ struct cpuinfo_x86 {
/* in KB - valid for CPUS which support this call: */
unsigned int x86_cache_size;
int x86_cache_alignment; /* In bytes */
- /* Cache QoS architectural values, valid only on the BSP: */
- int x86_cache_max_rmid; /* max index */
- int x86_cache_occ_scale; /* scale to bytes */
- int x86_cache_mbm_width_offset;
int x86_power;
unsigned long loops_per_jiffy;
/* protected processor identification number */
diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h
index 9bfa9b14002b..ab7f6ccd149e 100644
--- a/arch/x86/include/asm/resctrl.h
+++ b/arch/x86/include/asm/resctrl.h
@@ -193,12 +193,9 @@ static inline void resctrl_arch_mon_ctx_free(struct rdt_resource *r,
enum resctrl_event_id evtid,
void *ctx) { }
-void resctrl_cpu_detect(struct cpuinfo_x86 *c);
-
#else
static inline void resctrl_arch_sched_in(struct task_struct *tsk) {}
-static inline void resctrl_cpu_detect(struct cpuinfo_x86 *c) {}
#endif /* CONFIG_X86_CPU_RESCTRL */
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 54e14ed276b5..dd82a11084f4 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -23,7 +23,6 @@
#include <asm/pci-direct.h>
#include <asm/delay.h>
#include <asm/debugreg.h>
-#include <asm/resctrl.h>
#include <asm/msr.h>
#include <asm/sev.h>
@@ -475,8 +474,6 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
}
}
- resctrl_cpu_detect(c);
-
/* Figure out Zen generations: */
switch (c->x86) {
case 0x17:
diff --git a/arch/x86/kernel/cpu/hygon.c b/arch/x86/kernel/cpu/hygon.c
index ec51c2b9a257..0f226335dd9a 100644
--- a/arch/x86/kernel/cpu/hygon.c
+++ b/arch/x86/kernel/cpu/hygon.c
@@ -17,7 +17,6 @@
#include <asm/spec-ctrl.h>
#include <asm/delay.h>
#include <asm/msr.h>
-#include <asm/resctrl.h>
#include "cpu.h"
@@ -119,8 +118,6 @@ static void bsp_init_hygon(struct cpuinfo_x86 *c)
x86_amd_ls_cfg_ssbd_mask = 1ULL << 10;
}
}
-
- resctrl_cpu_detect(c);
}
static void early_init_hygon(struct cpuinfo_x86 *c)
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 4297ceb2cb24..2f09710e863c 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -22,7 +22,6 @@
#include <asm/microcode.h>
#include <asm/msr.h>
#include <asm/numa.h>
-#include <asm/resctrl.h>
#include <asm/thermal.h>
#include <asm/uaccess.h>
@@ -371,11 +370,6 @@ static void early_init_intel(struct cpuinfo_x86 *c)
detect_tme_early(c);
}
-static void bsp_init_intel(struct cpuinfo_x86 *c)
-{
- resctrl_cpu_detect(c);
-}
-
#ifdef CONFIG_X86_32
/*
* Early probe support logic for ppro memory erratum #50
@@ -804,7 +798,6 @@ static const struct cpu_dev intel_cpu_dev = {
#endif
.c_detect_tlb = intel_detect_tlb,
.c_early_init = early_init_intel,
- .c_bsp_init = bsp_init_intel,
.c_init = init_intel,
.c_x86_vendor = X86_VENDOR_INTEL,
};
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index 0799dbfc7a72..b657eab4eb0c 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -1082,48 +1082,6 @@ static __init void rdt_init_res_defs(void)
static enum cpuhp_state rdt_online;
-/* Runs once on the BSP during boot. */
-void resctrl_cpu_detect(struct cpuinfo_x86 *c)
-{
- if (!cpu_has(c, X86_FEATURE_L3_MON) && !cpu_has(c, X86_FEATURE_ABMC)) {
- c->x86_cache_max_rmid = -1;
- c->x86_cache_occ_scale = -1;
- c->x86_cache_mbm_width_offset = -1;
- return;
- }
-
- /* will be overridden if occupancy monitoring exists */
- c->x86_cache_max_rmid = cpuid_ebx(0xf);
-
- if (cpu_has(c, X86_FEATURE_CQM_OCCUP_LLC) ||
- cpu_has(c, X86_FEATURE_CQM_MBM_TOTAL) ||
- cpu_has(c, X86_FEATURE_CQM_MBM_LOCAL) ||
- cpu_has(c, X86_FEATURE_ABMC)) {
- u32 eax, ebx, ecx, edx;
-
- /* QoS sub-leaf, EAX=0Fh, ECX=1 */
- cpuid_count(0xf, 1, &eax, &ebx, &ecx, &edx);
-
- c->x86_cache_max_rmid = ecx;
- c->x86_cache_occ_scale = ebx;
- c->x86_cache_mbm_width_offset = eax & 0xff;
-
- if (!c->x86_cache_mbm_width_offset) {
- switch (c->x86_vendor) {
- case X86_VENDOR_AMD:
- c->x86_cache_mbm_width_offset = MBM_CNTR_WIDTH_OFFSET_AMD;
- break;
- case X86_VENDOR_HYGON:
- c->x86_cache_mbm_width_offset = MBM_CNTR_WIDTH_OFFSET_HYGON;
- break;
- default:
- /* Leave c->x86_cache_mbm_width_offset as 0 */
- break;
- }
- }
- }
-}
-
static int __init resctrl_arch_late_init(void)
{
struct rdt_resource *r;
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 06/23] arm,x86,fs/resctrl: Replace architecture resctrl_arch_{alloc,mon}_capable()
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (4 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 05/23] x86/resctrl: Delete resctrl_cpu_detect() Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 07/23] x86/resctrl: Add special case for Intel Haswell enumeration Tony Luck
` (17 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
All the information to determine whether a system is alloc, or mon,
capable is available to the file system. Architecture helpers are not
needed.
Define generic resctrl_alloc_capable() and resctrl_mon_capable() and
replace all architecture versions.
Suggested-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
New patch
include/linux/arm_mpam.h | 3 ---
include/linux/resctrl.h | 26 +++++++++++++++++++++++
arch/x86/include/asm/resctrl.h | 10 ---------
drivers/resctrl/mpam_resctrl.c | 26 ++---------------------
fs/resctrl/monitor.c | 10 ++++-----
fs/resctrl/pseudo_lock.c | 6 +++---
fs/resctrl/rdtgroup.c | 38 +++++++++++++++++-----------------
7 files changed, 55 insertions(+), 64 deletions(-)
diff --git a/include/linux/arm_mpam.h b/include/linux/arm_mpam.h
index f92a36187a52..ba4131048260 100644
--- a/include/linux/arm_mpam.h
+++ b/include/linux/arm_mpam.h
@@ -50,9 +50,6 @@ static inline int mpam_ris_create(struct mpam_msc *msc, u8 ris_idx,
}
#endif
-bool resctrl_arch_alloc_capable(void);
-bool resctrl_arch_mon_capable(void);
-
void resctrl_arch_set_cpu_default_closid(int cpu, u32 closid);
void resctrl_arch_set_closid_rmid(struct task_struct *tsk, u32 closid, u32 rmid);
void resctrl_arch_set_cpu_default_closid_rmid(int cpu, u32 closid, u32 rmid);
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index dd09c2ce9a0f..4a6b0c1833d6 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -346,6 +346,32 @@ struct rdt_resource {
*/
struct rdt_resource *resctrl_arch_get_resource(enum resctrl_res_level l);
+/*
+ * resctrl_alloc_capable - Are any allocation resources enabled.
+ */
+static inline bool resctrl_alloc_capable(void)
+{
+ struct rdt_resource *r;
+
+ for_each_rdt_resource(r)
+ if ((r)->alloc_capable)
+ return true;
+ return false;
+}
+
+/*
+ * resctrl_mon_capable - Are any monitor resources enabled.
+ */
+static inline bool resctrl_mon_capable(void)
+{
+ struct rdt_resource *r;
+
+ for_each_rdt_resource(r)
+ if ((r)->mon_capable)
+ return true;
+ return false;
+}
+
/**
* struct resctrl_schema - configuration abilities of a resource presented to
* user-space
diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h
index ab7f6ccd149e..fb6cfff82e2f 100644
--- a/arch/x86/include/asm/resctrl.h
+++ b/arch/x86/include/asm/resctrl.h
@@ -50,11 +50,6 @@ DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
DECLARE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
DECLARE_STATIC_KEY_FALSE(rdt_mon_enable_key);
-static inline bool resctrl_arch_alloc_capable(void)
-{
- return rdt_alloc_capable;
-}
-
static inline void resctrl_arch_enable_alloc(void)
{
static_branch_enable_cpuslocked(&rdt_alloc_enable_key);
@@ -67,11 +62,6 @@ static inline void resctrl_arch_disable_alloc(void)
static_branch_dec_cpuslocked(&rdt_enable_key);
}
-static inline bool resctrl_arch_mon_capable(void)
-{
- return rdt_mon_capable;
-}
-
static inline void resctrl_arch_enable_mon(void)
{
static_branch_enable_cpuslocked(&rdt_mon_enable_key);
diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
index 9d223057953a..0db62dd2a71c 100644
--- a/drivers/resctrl/mpam_resctrl.c
+++ b/drivers/resctrl/mpam_resctrl.c
@@ -75,28 +75,6 @@ static DECLARE_WAIT_QUEUE_HEAD(wait_cacheinfo_ready);
*/
static bool resctrl_enabled;
-bool resctrl_arch_alloc_capable(void)
-{
- struct mpam_resctrl_res *res;
- enum resctrl_res_level rid;
-
- for_each_mpam_resctrl_control(res, rid) {
- if (res->resctrl_res.alloc_capable)
- return true;
- }
-
- return false;
-}
-
-bool resctrl_arch_mon_capable(void)
-{
- struct mpam_resctrl_res *res = &mpam_resctrl_controls[RDT_RESOURCE_L3];
- struct rdt_resource *l3 = &res->resctrl_res;
-
- /* All monitors are presented as being on the L3 cache */
- return l3->mon_capable;
-}
-
bool resctrl_arch_is_evt_configurable(enum resctrl_event_id evt)
{
return false;
@@ -1897,9 +1875,9 @@ int mpam_resctrl_setup(void)
cpus_read_unlock();
- if (!resctrl_arch_alloc_capable() && !resctrl_arch_mon_capable()) {
+ if (!resctrl_alloc_capable() && !resctrl_mon_capable()) {
pr_debug("No alloc(%u) or monitor(%u) found - resctrl not supported\n",
- resctrl_arch_alloc_capable(), resctrl_arch_mon_capable());
+ resctrl_alloc_capable(), resctrl_mon_capable());
return -EOPNOTSUPP;
}
diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
index 73413cb128ea..362737e13cd3 100644
--- a/fs/resctrl/monitor.c
+++ b/fs/resctrl/monitor.c
@@ -338,7 +338,7 @@ void free_rmid(u32 closid, u32 rmid)
* allows architectures that ignore the closid parameter to avoid an
* unnecessary check.
*/
- if (!resctrl_arch_mon_capable() ||
+ if (!resctrl_mon_capable() ||
idx == resctrl_arch_rmid_idx_encode(RESCTRL_RESERVED_CLOSID,
RESCTRL_RESERVED_RMID))
return;
@@ -888,7 +888,7 @@ void mbm_handle_overflow(struct work_struct *work)
* If the filesystem has been unmounted this work no longer needs to
* run.
*/
- if (!resctrl_mounted || !resctrl_arch_mon_capable())
+ if (!resctrl_mounted || !resctrl_mon_capable())
goto out_unlock;
/*
@@ -950,7 +950,7 @@ void mbm_setup_overflow_handler(struct rdt_l3_mon_domain *dom, unsigned long del
* When a domain comes online there is no guarantee the filesystem is
* mounted. If not, there is no need to catch counter overflow.
*/
- if (!resctrl_mounted || !resctrl_arch_mon_capable())
+ if (!resctrl_mounted || !resctrl_mon_capable())
return;
cpu = cpumask_any_housekeeping(&dom->hdr.cpu_mask, exclude_cpu);
dom->mbm_work_cpu = cpu;
@@ -966,7 +966,7 @@ int setup_rmid_lru_list(void)
u32 idx;
int i;
- if (!resctrl_arch_mon_capable())
+ if (!resctrl_mon_capable())
return 0;
/*
@@ -1006,7 +1006,7 @@ int setup_rmid_lru_list(void)
void free_rmid_lru_list(void)
{
- if (!resctrl_arch_mon_capable())
+ if (!resctrl_mon_capable())
return;
mutex_lock(&rdtgroup_mutex);
diff --git a/fs/resctrl/pseudo_lock.c b/fs/resctrl/pseudo_lock.c
index dea2b4bf966f..04b69c0e37f2 100644
--- a/fs/resctrl/pseudo_lock.c
+++ b/fs/resctrl/pseudo_lock.c
@@ -383,7 +383,7 @@ static int rdtgroup_locksetup_user_restrict(struct rdtgroup *rdtgrp)
if (ret)
goto err_cpus;
- if (resctrl_arch_mon_capable()) {
+ if (resctrl_mon_capable()) {
ret = rdtgroup_kn_mode_restrict(rdtgrp, "mon_groups");
if (ret)
goto err_cpus_list;
@@ -430,7 +430,7 @@ static int rdtgroup_locksetup_user_restore(struct rdtgroup *rdtgrp)
if (ret)
goto err_cpus;
- if (resctrl_arch_mon_capable()) {
+ if (resctrl_mon_capable()) {
ret = rdtgroup_kn_mode_restore(rdtgrp, "mon_groups", 0777);
if (ret)
goto err_cpus_list;
@@ -577,7 +577,7 @@ int rdtgroup_locksetup_exit(struct rdtgroup *rdtgrp)
{
int ret;
- if (resctrl_arch_mon_capable()) {
+ if (resctrl_mon_capable()) {
ret = alloc_rmid(rdtgrp->closid);
if (ret < 0) {
rdt_last_cmd_puts("Out of RMIDs\n");
diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index 5dcbb0a964e8..79977200b1a0 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -685,13 +685,13 @@ static int __rdtgroup_move_task(struct task_struct *tsk,
static bool is_closid_match(struct task_struct *t, struct rdtgroup *r)
{
- return (resctrl_arch_alloc_capable() && (r->type == RDTCTRL_GROUP) &&
+ return (resctrl_alloc_capable() && (r->type == RDTCTRL_GROUP) &&
resctrl_arch_match_closid(t, r->closid));
}
static bool is_rmid_match(struct task_struct *t, struct rdtgroup *r)
{
- return (resctrl_arch_mon_capable() && (r->type == RDTMON_GROUP) &&
+ return (resctrl_mon_capable() && (r->type == RDTMON_GROUP) &&
resctrl_arch_match_rmid(t, r->mon.parent->closid,
r->mon.rmid));
}
@@ -3159,9 +3159,9 @@ static void resctrl_unmount(void)
resctrl_arch_reset_all_ctrls(r);
resctrl_fs_teardown();
- if (resctrl_arch_alloc_capable())
+ if (resctrl_alloc_capable())
resctrl_arch_disable_alloc();
- if (resctrl_arch_mon_capable())
+ if (resctrl_mon_capable())
resctrl_arch_disable_mon();
resctrl_mounted = false;
mutex_unlock(&rdtgroup_mutex);
@@ -3215,7 +3215,7 @@ static int rdt_get_tree(struct fs_context *fc)
if (ret)
goto out_schemata_free;
- if (resctrl_arch_mon_capable())
+ if (resctrl_mon_capable())
flags |= RFTYPE_MON;
ret = rdtgroup_add_files(rdtgroup_default.kn, flags);
@@ -3228,7 +3228,7 @@ static int rdt_get_tree(struct fs_context *fc)
if (ret < 0)
goto out_closid_exit;
- if (resctrl_arch_mon_capable()) {
+ if (resctrl_mon_capable()) {
ret = mongroup_create_dir(rdtgroup_default.kn,
&rdtgroup_default, "mon_groups",
&kn_mongrp);
@@ -3248,12 +3248,12 @@ static int rdt_get_tree(struct fs_context *fc)
if (ret)
goto out_mondata;
- if (resctrl_arch_alloc_capable())
+ if (resctrl_alloc_capable())
resctrl_arch_enable_alloc();
- if (resctrl_arch_mon_capable())
+ if (resctrl_mon_capable())
resctrl_arch_enable_mon();
- if (resctrl_arch_alloc_capable() || resctrl_arch_mon_capable())
+ if (resctrl_alloc_capable() || resctrl_mon_capable())
resctrl_mounted = true;
if (resctrl_is_mbm_enabled()) {
@@ -3296,10 +3296,10 @@ static int rdt_get_tree(struct fs_context *fc)
return ret;
out_mondata:
- if (resctrl_arch_mon_capable())
+ if (resctrl_mon_capable())
kernfs_remove(kn_mondata);
out_mongrp:
- if (resctrl_arch_mon_capable()) {
+ if (resctrl_mon_capable()) {
mon_put_kn_priv();
rdtgroup_unassign_cntrs(&rdtgroup_default);
kernfs_remove(kn_mongrp);
@@ -3888,7 +3888,7 @@ static int mkdir_rdt_prepare_rmid_alloc(struct rdtgroup *rdtgrp)
{
int ret;
- if (!resctrl_arch_mon_capable())
+ if (!resctrl_mon_capable())
return 0;
ret = alloc_rmid(rdtgrp->closid);
@@ -3913,7 +3913,7 @@ static int mkdir_rdt_prepare_rmid_alloc(struct rdtgroup *rdtgrp)
static void mkdir_rdt_prepare_rmid_free(struct rdtgroup *rgrp)
{
- if (resctrl_arch_mon_capable()) {
+ if (resctrl_mon_capable()) {
rdtgroup_unassign_cntrs(rgrp);
free_rmid(rgrp->closid, rgrp->mon.rmid);
}
@@ -4004,7 +4004,7 @@ static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
if (rtype == RDTCTRL_GROUP) {
files = RFTYPE_BASE | RFTYPE_CTRL;
- if (resctrl_arch_mon_capable())
+ if (resctrl_mon_capable())
files |= RFTYPE_MON;
} else {
files = RFTYPE_BASE | RFTYPE_MON;
@@ -4113,7 +4113,7 @@ static int rdtgroup_mkdir_ctrl_mon(struct kernfs_node *parent_kn,
list_add(&rdtgrp->rdtgroup_list, &rdt_all_groups);
- if (resctrl_arch_mon_capable()) {
+ if (resctrl_mon_capable()) {
/*
* Create an empty mon_groups directory to hold the subset
* of tasks and cpus to monitor.
@@ -4154,11 +4154,11 @@ static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
* allocation is supported, add a control and monitoring
* subdirectory
*/
- if (resctrl_arch_alloc_capable() && parent_kn == rdtgroup_default.kn)
+ if (resctrl_alloc_capable() && parent_kn == rdtgroup_default.kn)
return rdtgroup_mkdir_ctrl_mon(parent_kn, name, mode);
/* Else, attempt to add a monitoring subdirectory. */
- if (resctrl_arch_mon_capable())
+ if (resctrl_mon_capable())
return rdtgroup_mkdir_mon(parent_kn, name, mode);
return -EPERM;
@@ -4573,7 +4573,7 @@ void resctrl_offline_mon_domain(struct rdt_resource *r, struct rdt_domain_hdr *h
* If resctrl is mounted, remove all the
* per domain monitor data directories.
*/
- if (resctrl_mounted && resctrl_arch_mon_capable())
+ if (resctrl_mounted && resctrl_mon_capable())
rmdir_mondata_subdir_allrdtgrp(r, hdr);
if (r->rid != RDT_RESOURCE_L3)
@@ -4710,7 +4710,7 @@ int resctrl_online_mon_domain(struct rdt_resource *r, struct rdt_domain_hdr *hdr
* by rdt_get_tree() calling mkdir_mondata_all().
* If resctrl is mounted, add per domain monitor data directories.
*/
- if (resctrl_mounted && resctrl_arch_mon_capable())
+ if (resctrl_mounted && resctrl_mon_capable())
mkdir_mondata_subdir_allrdtgrp(r, hdr);
out_unlock:
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 07/23] x86/resctrl: Add special case for Intel Haswell enumeration
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (5 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 06/23] arm,x86,fs/resctrl: Replace architecture resctrl_arch_{alloc,mon}_capable() Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 08/23] x86/resctrl: Delete rdt_alloc_capable and rdt_mon_capable Tony Luck
` (16 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
Certain Intel Haswell CPUs have support for resctrl L3 cache allocation
but do not enumerate the feature. There is a quirk to check for support
and provide hard-coded parameters. This quirk sets rdt_alloc_capable
to indicate to get_rdt_alloc_resources() that normal enumeration is
not needed.
Replace the set and test of rdt_alloc_capable with a new variable
in preparation for the removal of rdt_alloc_capable.
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
New patch
arch/x86/kernel/cpu/resctrl/core.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index b657eab4eb0c..62b97e357ce5 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -138,6 +138,9 @@ struct rdt_resource *resctrl_arch_get_resource(enum resctrl_res_level l)
return &rdt_resources_all[l].r_resctrl;
}
+/* Skip regular allocation if cache_alloc_hsw_probe() succeeds. */
+static bool hsw_alloc_capable;
+
/*
* cache_alloc_hsw_probe() - Have to probe for Intel haswell server CPUs
* as they do not have CPUID enumeration support for Cache allocation.
@@ -178,7 +181,7 @@ static inline void cache_alloc_hsw_probe(void)
r->cache.arch_has_sparse_bitmasks = false;
r->alloc_capable = true;
- rdt_alloc_capable = true;
+ hsw_alloc_capable = true;
}
/*
@@ -930,7 +933,7 @@ static __init bool get_rdt_alloc_resources(void)
struct rdt_resource *r;
bool ret = false;
- if (rdt_alloc_capable)
+ if (hsw_alloc_capable)
return true;
if (!boot_cpu_has(X86_FEATURE_RDT_A))
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 08/23] x86/resctrl: Delete rdt_alloc_capable and rdt_mon_capable
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (6 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 07/23] x86/resctrl: Add special case for Intel Haswell enumeration Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 09/23] fs/resctrl: Remove redundant calls to resctrl_mon_capable() Tony Luck
` (15 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
These globals are no longer needed.
Signed-off-by: Tony Luck <tony.luck@intel.com>
v11:
New patch
---
arch/x86/include/asm/resctrl.h | 2 --
arch/x86/kernel/cpu/resctrl/core.c | 15 +++++----------
arch/x86/kernel/cpu/resctrl/monitor.c | 6 ------
3 files changed, 5 insertions(+), 18 deletions(-)
diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h
index fb6cfff82e2f..49b5357e2e5c 100644
--- a/arch/x86/include/asm/resctrl.h
+++ b/arch/x86/include/asm/resctrl.h
@@ -42,8 +42,6 @@ struct resctrl_pqr_state {
DECLARE_PER_CPU(struct resctrl_pqr_state, pqr_state);
-extern bool rdt_alloc_capable;
-extern bool rdt_mon_capable;
extern unsigned int __ro_after_init rdt_l3_mon_scale;
DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index 62b97e357ce5..e851da431dd9 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -45,12 +45,6 @@ static DEFINE_MUTEX(domain_list_lock);
*/
DEFINE_PER_CPU(struct resctrl_pqr_state, pqr_state);
-/*
- * Global boolean for rdt_alloc which is true if any
- * resource allocation is enabled.
- */
-bool rdt_alloc_capable;
-
static void mba_wrmsr_intel(struct msr_param *m);
static void cat_wrmsr(struct msr_param *m);
static void mba_wrmsr_amd(struct msr_param *m);
@@ -786,7 +780,6 @@ void resctrl_arch_pre_mount(void)
cpus_read_lock();
mutex_lock(&domain_list_lock);
r->mon_capable = true;
- rdt_mon_capable = true;
for_each_online_cpu(cpu)
domain_add_cpu_mon(cpu, r);
mutex_unlock(&domain_list_lock);
@@ -1026,10 +1019,12 @@ static __init void check_quirks(void)
static __init bool get_rdt_resources(void)
{
- rdt_alloc_capable = get_rdt_alloc_resources();
- rdt_mon_capable = get_rdt_mon_resources();
+ bool alloc_capable, mon_capable;
+
+ alloc_capable = get_rdt_alloc_resources();
+ mon_capable = get_rdt_mon_resources();
- return (rdt_mon_capable || rdt_alloc_capable);
+ return (mon_capable || alloc_capable);
}
static __init void rdt_init_res_defs_intel(void)
diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c
index 0bce199a5f7b..bc2df287ccfa 100644
--- a/arch/x86/kernel/cpu/resctrl/monitor.c
+++ b/arch/x86/kernel/cpu/resctrl/monitor.c
@@ -26,12 +26,6 @@
#include "internal.h"
-/*
- * Global boolean for rdt_monitor which is true if any
- * resource monitoring is enabled.
- */
-bool rdt_mon_capable;
-
/*
* Scale factor to convert L3 monitor events to bytes.
*/
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 09/23] fs/resctrl: Remove redundant calls to resctrl_mon_capable()
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (7 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 08/23] x86/resctrl: Delete rdt_alloc_capable and rdt_mon_capable Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 10/23] x86/resctrl: Honor rdt=perf option to force enable AET perf events Tony Luck
` (14 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
resctrl_mon_capable() indicates whether any monitoring resources
are enabled on the system. It does this by scanning all resources.
Redundant calls to resctrl_arch_mon_capable() in hot code paths should
be eliminated. There are two prime examples:
1) mbm_handle_overflow()
This function is called once per second from worker threads running on
each L3 domain. The call is clearly redundant because worker threads are
only created if the MBM monitoring feature is enabled.
2) is_rmid_match()
This is called for every task on the system so making it less expensive is
appealing. The call is redundant because the function also checks "r->type
== RDTMON_GROUP" and this type of group can only be created on systems that
support monitoring.
Remove the call to resctrl_mon_capable() from both of these
functions.
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
Update commit message with performace impact justifying the is_rmid_match() case.
fs/resctrl/monitor.c | 2 +-
fs/resctrl/rdtgroup.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
index 362737e13cd3..02e81fc82b14 100644
--- a/fs/resctrl/monitor.c
+++ b/fs/resctrl/monitor.c
@@ -888,7 +888,7 @@ void mbm_handle_overflow(struct work_struct *work)
* If the filesystem has been unmounted this work no longer needs to
* run.
*/
- if (!resctrl_mounted || !resctrl_mon_capable())
+ if (!resctrl_mounted)
goto out_unlock;
/*
diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index 79977200b1a0..4f8a510be8ec 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -691,7 +691,7 @@ static bool is_closid_match(struct task_struct *t, struct rdtgroup *r)
static bool is_rmid_match(struct task_struct *t, struct rdtgroup *r)
{
- return (resctrl_mon_capable() && (r->type == RDTMON_GROUP) &&
+ return ((r->type == RDTMON_GROUP) &&
resctrl_arch_match_rmid(t, r->mon.parent->closid,
r->mon.rmid));
}
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 10/23] x86/resctrl: Honor rdt=perf option to force enable AET perf events
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (8 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 09/23] fs/resctrl: Remove redundant calls to resctrl_mon_capable() Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 11/23] fs/resctrl: Add interface to disable a monitor event Tony Luck
` (13 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
resctrl can disable ("force_off") a feature supported by the platform if,
for example, there is an erratum related to the feature or, in the case of AET
(Application Energy Telemetry), when the event group has insufficient RMIDs. The
"rdt=" kernel command line option lets the user override ("force_on") when
a feature is disabled in such case. Users may also disable ("force_off")
individual supported resctrl features they do not need.
Linux enumerates AET once on first mount and skips this enumeration if
the associated event group is supported but disabled. Since AET is only
enumerated once, this check is guaranteed to only consider disabling via
the rdt= kernel parameter.
However, when transitioning to enumerate AET on every mount, it is no longer
correct to skip enumeration simply because an event group is marked as
disabled. It is then possible for resctrl to have force-disabled the event
group during an earlier enumeration due to insufficient RMIDs, which would
improperly cause the kernel to ignore a user's explicit rdt= override on
subsequent mounts.
Ensure the user's command line choices take precedence over system-level limits.
Signed-off-by: Tony Luck <tony.luck@intel.com>
Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
---
v11:
Add Reinette RB tag.
arch/x86/kernel/cpu/resctrl/intel_aet.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/kernel/cpu/resctrl/intel_aet.c b/arch/x86/kernel/cpu/resctrl/intel_aet.c
index c22c3cf5167d..4ad6ad78e93e 100644
--- a/arch/x86/kernel/cpu/resctrl/intel_aet.c
+++ b/arch/x86/kernel/cpu/resctrl/intel_aet.c
@@ -228,7 +228,7 @@ static bool enable_events(struct event_group *e, struct pmt_feature_group *p)
struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_PERF_PKG].r_resctrl;
int skipped_events = 0;
- if (e->force_off)
+ if (e->force_off && !e->force_on)
return false;
if (!group_has_usable_regions(e, p))
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 11/23] fs/resctrl: Add interface to disable a monitor event
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (9 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 10/23] x86/resctrl: Honor rdt=perf option to force enable AET perf events Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 12/23] arm,x86,fs/resctrl: Handle change in number of RMIDs on each mount Tony Luck
` (12 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
resctrl currently assumes all monitor events are enabled before any domain
is created, because per-domain state is allocated by the architecture's CPU
hotplug callbacks. There is no way to disable an event once registered.
AET events are enumerated by the INTEL_PMT_TELEMETRY driver. To allow that
driver to be a loadable module, resctrl must tolerate AET events appearing
and disappearing, which requires the ability to disable an event when the
driver is unloaded.
Add resctrl_disable_mon_event(). The architecture owns domain lifetime
and knows mount state, so it is responsible for calling this only while
resctrl is unmounted and for cleaning up any per-domain state. Document
those requirements in the kerneldoc since they are not enforced in code.
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
Add Reinette RB tag.
include/linux/resctrl.h | 34 ++++++++++++++++++++++++++++++++++
fs/resctrl/monitor.c | 15 +++++++++++++++
2 files changed, 49 insertions(+)
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index 4a6b0c1833d6..e9094d886ba7 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -445,9 +445,43 @@ u32 resctrl_arch_get_num_closid(struct rdt_resource *r);
u32 resctrl_arch_system_num_rmid_idx(void);
int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid);
+/**
+ * resctrl_enable_mon_event() - Enable monitoring event
+ * @eventid: ID of the event
+ * @any_cpu: True if event data can be read from any CPU.
+ * @binary_bits: Number of binary places of the fixed-point value expected to
+ * back a floating point event. Can only be set for floating point
+ * events.
+ * @arch_priv: Architecture private data associated with event. Passed back to
+ * architecture when reading the event via resctrl_arch_rmid_read().
+ *
+ * The file system must not be mounted when enabling an event.
+ *
+ * Events that require per-domain (architectural and/or filesystem) state must
+ * be enabled before the domain structures are allocated. For example before
+ * CPU hotplug callbacks that allocate domain structures are registered. If the
+ * architecture discovers a resource after initialization it should enable
+ * events needing per-domain state before any domain structure allocation which
+ * should be coordinated with the CPU hotplug callbacks.
+ *
+ * Return:
+ * true if event was successfully enabled, false otherwise.
+ */
bool resctrl_enable_mon_event(enum resctrl_event_id eventid, bool any_cpu,
unsigned int binary_bits, void *arch_priv);
+/**
+ * resctrl_disable_mon_event() - Disable monitoring event
+ * @eventid: ID of the event
+ *
+ * The file system must not be mounted when disabling an event.
+ *
+ * Events that require per-domain (architectural and/or filesystem) state
+ * will require additional cleanup which should be coordinated with the CPU
+ * hotplug callbacks.
+ */
+void resctrl_disable_mon_event(enum resctrl_event_id eventid);
+
bool resctrl_is_mon_event_enabled(enum resctrl_event_id eventid);
bool resctrl_arch_is_evt_configurable(enum resctrl_event_id evt);
diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
index 02e81fc82b14..2a28fe04284b 100644
--- a/fs/resctrl/monitor.c
+++ b/fs/resctrl/monitor.c
@@ -1066,6 +1066,21 @@ bool resctrl_enable_mon_event(enum resctrl_event_id eventid, bool any_cpu,
return true;
}
+void resctrl_disable_mon_event(enum resctrl_event_id eventid)
+{
+ if (WARN_ON_ONCE(eventid < QOS_FIRST_EVENT || eventid >= QOS_NUM_EVENTS))
+ return;
+ if (!mon_event_all[eventid].enabled) {
+ pr_warn("Event %d already disabled\n", eventid);
+ return;
+ }
+
+ mon_event_all[eventid].any_cpu = false;
+ mon_event_all[eventid].binary_bits = 0;
+ mon_event_all[eventid].arch_priv = NULL;
+ mon_event_all[eventid].enabled = false;
+}
+
bool resctrl_is_mon_event_enabled(enum resctrl_event_id eventid)
{
return eventid >= QOS_FIRST_EVENT && eventid < QOS_NUM_EVENTS &&
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 12/23] arm,x86,fs/resctrl: Handle change in number of RMIDs on each mount
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (10 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 11/23] fs/resctrl: Add interface to disable a monitor event Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 13/23] x86/resctrl: Handle systems when AET is the only resource Tony Luck
` (11 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
Application Energy Telemetry (AET) event enumeration takes place
asynchronously. Linux builds the pmt_telemetry module into the kernel to
kick off enumeration early enough that it completes before first mount of
the resctrl file system.
Allowing pmt_telemetry to be a loadable module means that it is possible
for different numbers of RMIDs to be supported on each mount, depending
on whether pmt_telemetry module is loaded.
For simplicity, calculate the maximum possible number of RMIDs and use
that value to allocate the rmid_ptrs[] array just once. Use this same
calculated value for all references to rmid_ptrs[] instead of calling
resctrl_arch_system_max_rmid_idx() in multiple places.
Add resctrl_arch_get_num_rmid_idx(r) to report the maximum RMID index
for a resource. Use it to allocate the rdt_l3_mon_domain::rmid_busy_llc
bitmap and rdt_l3_mon_domain::mbm_states and when operating on these
structures.
The limbo code must deal with changes in the number of RMIDs from one
mount to the next because some RMIDs may still be "busy" when the file
system is unmounted, but be above resctrl_arch_system_num_rmid_idx()
for the remount. In this case RMIDs that can be released are not put
onto the rmid_free_lru list.
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
Add resctrl_arch_get_num_rmid_idx(r) and use it for allocating
an operating on L3 per-domain dynamically allocated structures.
Update kernel doc comment for max_idx_limit.
Update comment to explain why all RMIDs need to be checked
for LLC cache occupancy.
include/linux/resctrl.h | 8 ++-
arch/x86/kernel/cpu/resctrl/core.c | 30 +++++++++++
drivers/resctrl/mpam_resctrl.c | 14 +++++
fs/resctrl/monitor.c | 87 +++++++++++++++++++++---------
fs/resctrl/rdtgroup.c | 6 +--
5 files changed, 114 insertions(+), 31 deletions(-)
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index e9094d886ba7..4fb06d434c85 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -183,10 +183,12 @@ struct mbm_cntr_cfg {
* struct rdt_l3_mon_domain - group of CPUs sharing RDT_RESOURCE_L3 monitoring
* @hdr: common header for different domain types
* @ci_id: cache info id for this domain
- * @rmid_busy_llc: bitmap of which limbo RMIDs are above threshold
+ * @rmid_busy_llc: bitmap of which limbo RMIDs are above threshold. Sized for
+ * maximum supported RMIDs in L3 resource.
* @mbm_states: Per-event pointer to the MBM event's saved state.
* An MBM event's state is an array of struct mbm_state
* indexed by RMID on x86 or combined CLOSID, RMID on Arm.
+ * Sized same as @rmid_busy_llc.
* @mbm_over: worker to periodically read MBM h/w counters
* @cqm_limbo: worker to periodically read CQM h/w counters
* @mbm_work_cpu: worker CPU for MBM h/w counters
@@ -440,9 +442,11 @@ static inline u32 resctrl_get_default_ctrl(struct rdt_resource *r)
return WARN_ON_ONCE(1);
}
-/* The number of closid supported by this resource regardless of CDP */
+/* The number of closid/rmid supported by this resource regardless of CDP */
u32 resctrl_arch_get_num_closid(struct rdt_resource *r);
+u32 resctrl_arch_get_num_rmid_idx(struct rdt_resource *r);
u32 resctrl_arch_system_num_rmid_idx(void);
+u32 resctrl_arch_system_max_rmid_idx(void);
int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid);
/**
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index e851da431dd9..ef37fbb586d3 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -124,6 +124,31 @@ u32 resctrl_arch_system_num_rmid_idx(void)
return num_rmids == U32_MAX ? 0 : num_rmids;
}
+/**
+ * resctrl_arch_system_max_rmid_idx - Largest possible number of RMIDs
+ *
+ * Return: Maximum possible number of RMIDs used for boot time allocations.
+ */
+u32 resctrl_arch_system_max_rmid_idx(void)
+{
+ struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3].r_resctrl;
+ u32 ret;
+
+ /* CPUID enumerates maximum value that can be written to IA32_PQR_ASSOC.RMID */
+ ret = cpuid_ebx(0xf) + 1;
+
+ /*
+ * If the system is capable of L3 monitoring the maximum RMID value may
+ * be lower than the system maximum. Either because the L3 monitoring
+ * feature supports fewer RMIDs, or because SNC (Sub-NUMA Cluster)
+ * is enabled and divides RMIDs per cluster.
+ */
+ if (r->mon_capable)
+ ret = r->mon.num_rmid;
+
+ return ret;
+}
+
struct rdt_resource *resctrl_arch_get_resource(enum resctrl_res_level l)
{
if (l >= RDT_NUM_RESOURCES)
@@ -360,6 +385,11 @@ u32 resctrl_arch_get_num_closid(struct rdt_resource *r)
return resctrl_to_arch_res(r)->num_closid;
}
+u32 resctrl_arch_get_num_rmid_idx(struct rdt_resource *r)
+{
+ return r->mon.num_rmid;
+}
+
void rdt_ctrl_update(void *arg)
{
struct rdt_hw_resource *hw_res;
diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
index 0db62dd2a71c..a117aa98ae90 100644
--- a/drivers/resctrl/mpam_resctrl.c
+++ b/drivers/resctrl/mpam_resctrl.c
@@ -247,11 +247,25 @@ u32 resctrl_arch_get_num_closid(struct rdt_resource *ignored)
return mpam_partid_max + 1;
}
+/*
+ * File system calls this for one-time allocation of structures
+ * during initialization. Return the largest possible value.
+ */
+u32 resctrl_arch_get_num_rmid_idx(struct rdt_resource *ignored)
+{
+ return resctrl_arch_system_num_rmid_idx();
+}
+
u32 resctrl_arch_system_num_rmid_idx(void)
{
return (mpam_pmg_max + 1) * (mpam_partid_max + 1);
}
+u32 resctrl_arch_system_max_rmid_idx(void)
+{
+ return resctrl_arch_system_num_rmid_idx();
+}
+
u32 resctrl_arch_rmid_idx_encode(u32 closid, u32 rmid)
{
return closid * (mpam_pmg_max + 1) + rmid;
diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
index 2a28fe04284b..5340c764bf7f 100644
--- a/fs/resctrl/monitor.c
+++ b/fs/resctrl/monitor.c
@@ -75,6 +75,11 @@ static unsigned int rmid_limbo_count;
*/
static struct rmid_entry *rmid_ptrs;
+/*
+ * @max_idx_limit - The number of elements in rmid_ptrs[].
+ */
+static u32 max_idx_limit;
+
/*
* This is the threshold cache occupancy in bytes at which we will consider an
* RMID available for re-allocation.
@@ -115,10 +120,18 @@ static inline struct rmid_entry *__rmid_entry(u32 idx)
static void limbo_release_entry(struct rmid_entry *entry)
{
+ u32 cur_idx_limit = resctrl_arch_system_num_rmid_idx();
+
lockdep_assert_held(&rdtgroup_mutex);
rmid_limbo_count--;
- list_add_tail(&entry->list, &rmid_free_lru);
+
+ /*
+ * Limbo may be freeing an RMID from a previous mount where there
+ * were more RMIDs available.
+ */
+ if (resctrl_arch_rmid_idx_encode(entry->closid, entry->rmid) < cur_idx_limit)
+ list_add_tail(&entry->list, &rmid_free_lru);
if (IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID))
closid_num_dirty_rmid[entry->closid]--;
@@ -133,7 +146,7 @@ static void limbo_release_entry(struct rmid_entry *entry)
void __check_limbo(struct rdt_l3_mon_domain *d, bool force_free)
{
struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
- u32 idx_limit = resctrl_arch_system_num_rmid_idx();
+ u32 max_l3_idx_limit = resctrl_arch_get_num_rmid_idx(r);
struct rmid_entry *entry;
bool rmid_dirty = true;
u32 idx, cur_idx = 1;
@@ -156,8 +169,14 @@ void __check_limbo(struct rdt_l3_mon_domain *d, bool force_free)
* RMID and move it to the free list when the counter reaches 0.
*/
for (;;) {
- idx = find_next_bit(d->rmid_busy_llc, idx_limit, cur_idx);
- if (idx >= idx_limit)
+ /*
+ * RMIDs will keep counts of allocated LLC entries after the
+ * resctrl file system is unmounted. So check all possible
+ * RMIDs since a previous mount cycle may have used more
+ * than are available in this mount cycle.
+ */
+ idx = find_next_bit(d->rmid_busy_llc, max_l3_idx_limit, cur_idx);
+ if (idx >= max_l3_idx_limit)
break;
entry = __rmid_entry(idx);
@@ -197,9 +216,10 @@ void __check_limbo(struct rdt_l3_mon_domain *d, bool force_free)
bool has_busy_rmid(struct rdt_l3_mon_domain *d)
{
- u32 idx_limit = resctrl_arch_system_num_rmid_idx();
+ struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
+ u32 max_l3_idx_limit = resctrl_arch_get_num_rmid_idx(r);
- return find_first_bit(d->rmid_busy_llc, idx_limit) != idx_limit;
+ return find_first_bit(d->rmid_busy_llc, max_l3_idx_limit) != max_l3_idx_limit;
}
static struct rmid_entry *resctrl_find_free_rmid(u32 closid)
@@ -962,7 +982,7 @@ void mbm_setup_overflow_handler(struct rdt_l3_mon_domain *dom, unsigned long del
int setup_rmid_lru_list(void)
{
struct rmid_entry *entry = NULL;
- u32 idx_limit;
+ u32 cur_idx_limit;
u32 idx;
int i;
@@ -970,27 +990,36 @@ int setup_rmid_lru_list(void)
return 0;
/*
- * Called on every mount, but the number of RMIDs cannot change
- * after the first mount, so keep using the same set of rmid_ptrs[]
- * until resctrl_exit(). Note that the limbo handler continues to
- * access rmid_ptrs[] after resctrl is unmounted.
+ * Allocate the largest number of RMIDs that this system will ever
+ * need. These cannot be freed until resctrl_exit() because the limbo
+ * handler continues to access rmid_ptrs[] after resctrl is unmounted.
*/
- if (rmid_ptrs)
- return 0;
+ if (!rmid_ptrs) {
+ max_idx_limit = resctrl_arch_system_max_rmid_idx();
+ rmid_ptrs = kzalloc_objs(struct rmid_entry, max_idx_limit);
+ if (!rmid_ptrs) {
+ max_idx_limit = 0;
+ return -ENOMEM;
+ }
- idx_limit = resctrl_arch_system_num_rmid_idx();
- rmid_ptrs = kzalloc_objs(struct rmid_entry, idx_limit);
- if (!rmid_ptrs)
- return -ENOMEM;
+ for (i = 0; i < max_idx_limit; i++) {
+ entry = &rmid_ptrs[i];
+ INIT_LIST_HEAD(&entry->list);
- for (i = 0; i < idx_limit; i++) {
- entry = &rmid_ptrs[i];
- INIT_LIST_HEAD(&entry->list);
+ resctrl_arch_rmid_idx_decode(i, &entry->closid, &entry->rmid);
+ }
+ }
- resctrl_arch_rmid_idx_decode(i, &entry->closid, &entry->rmid);
- list_add_tail(&entry->list, &rmid_free_lru);
+ /* Find how many RMIDs are needed for this mount */
+ cur_idx_limit = resctrl_arch_system_num_rmid_idx();
+ if (cur_idx_limit > max_idx_limit) {
+ pr_warn_once("RMID count %u exceeds allocated %u; capping\n",
+ cur_idx_limit, max_idx_limit);
+ cur_idx_limit = max_idx_limit;
}
+ INIT_LIST_HEAD(&rmid_free_lru);
+
/*
* RESCTRL_RESERVED_CLOSID and RESCTRL_RESERVED_RMID are special and
* are always allocated. These are used for the rdtgroup_default
@@ -998,8 +1027,14 @@ int setup_rmid_lru_list(void)
*/
idx = resctrl_arch_rmid_idx_encode(RESCTRL_RESERVED_CLOSID,
RESCTRL_RESERVED_RMID);
- entry = __rmid_entry(idx);
- list_del(&entry->list);
+
+ for (i = 0; i < cur_idx_limit; i++) {
+ entry = &rmid_ptrs[i];
+ /* Don't add reserved or busy entries to free list */
+ if (i == idx || entry->busy)
+ continue;
+ list_add_tail(&entry->list, &rmid_free_lru);
+ }
return 0;
}
@@ -1218,7 +1253,7 @@ static void mbm_cntr_free_all(struct rdt_resource *r, struct rdt_l3_mon_domain *
*/
static void resctrl_reset_rmid_all(struct rdt_resource *r, struct rdt_l3_mon_domain *d)
{
- u32 idx_limit = resctrl_arch_system_num_rmid_idx();
+ u32 max_l3_idx_limit = resctrl_arch_get_num_rmid_idx(r);
enum resctrl_event_id evt;
int idx;
@@ -1226,7 +1261,7 @@ static void resctrl_reset_rmid_all(struct rdt_resource *r, struct rdt_l3_mon_dom
if (!resctrl_is_mon_event_enabled(evt))
continue;
idx = MBM_STATE_IDX(evt);
- memset(d->mbm_states[idx], 0, sizeof(*d->mbm_states[0]) * idx_limit);
+ memset(d->mbm_states[idx], 0, sizeof(*d->mbm_states[0]) * max_l3_idx_limit);
}
}
diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index 4f8a510be8ec..de07ccdffdb2 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -4621,13 +4621,13 @@ void resctrl_offline_mon_domain(struct rdt_resource *r, struct rdt_domain_hdr *h
*/
static int domain_setup_l3_mon_state(struct rdt_resource *r, struct rdt_l3_mon_domain *d)
{
- u32 idx_limit = resctrl_arch_system_num_rmid_idx();
+ u32 max_idx_limit = resctrl_arch_get_num_rmid_idx(r);
size_t tsize = sizeof(*d->mbm_states[0]);
enum resctrl_event_id eventid;
int idx;
if (resctrl_is_mon_event_enabled(QOS_L3_OCCUP_EVENT_ID)) {
- d->rmid_busy_llc = bitmap_zalloc(idx_limit, GFP_KERNEL);
+ d->rmid_busy_llc = bitmap_zalloc(max_idx_limit, GFP_KERNEL);
if (!d->rmid_busy_llc)
return -ENOMEM;
}
@@ -4636,7 +4636,7 @@ static int domain_setup_l3_mon_state(struct rdt_resource *r, struct rdt_l3_mon_d
if (!resctrl_is_mon_event_enabled(eventid))
continue;
idx = MBM_STATE_IDX(eventid);
- d->mbm_states[idx] = kcalloc(idx_limit, tsize, GFP_KERNEL);
+ d->mbm_states[idx] = kcalloc(max_idx_limit, tsize, GFP_KERNEL);
if (!d->mbm_states[idx])
goto cleanup;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 13/23] x86/resctrl: Handle systems when AET is the only resource
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (11 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 12/23] arm,x86,fs/resctrl: Handle change in number of RMIDs on each mount Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 14/23] x86/resctrl: Enforce system RMID limit on AET event groups Tony Luck
` (10 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
On a system with no L3 monitor resources it should still be possible to
run with just AET.
Update get_rdt_mon_resources() to return true based on whether the
system supports monitoring rather than on the presence of any of the
L3 monitor features.
Make rdt_get_tree() handle the case where AET is the only feature, but
is not enabled for a specific mount.
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
Split the AET RMID cap change into separate commit.
s/Fix get_rdt_mon_resources/Update get_rdt_mon_resources/
New subject for this patch
arch/x86/kernel/cpu/resctrl/internal.h | 2 +-
arch/x86/kernel/cpu/resctrl/core.c | 7 ++++---
arch/x86/kernel/cpu/resctrl/monitor.c | 4 +---
fs/resctrl/rdtgroup.c | 8 ++++++--
4 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h
index e46eb9a4c725..d70c8cb1cb81 100644
--- a/arch/x86/kernel/cpu/resctrl/internal.h
+++ b/arch/x86/kernel/cpu/resctrl/internal.h
@@ -226,7 +226,7 @@ union l3_qos_abmc_cfg {
void rdt_ctrl_update(void *arg);
-int rdt_get_l3_mon_config(struct rdt_resource *r);
+void rdt_get_l3_mon_config(struct rdt_resource *r);
bool rdt_cpu_has(int flag);
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index ef37fbb586d3..0ddec2b67e3d 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -1016,10 +1016,11 @@ static __init bool get_rdt_mon_resources(void)
ret = true;
}
- if (!ret)
- return false;
+ if (ret)
+ rdt_get_l3_mon_config(r);
- return !rdt_get_l3_mon_config(r);
+ /* Even if there are no L3 monitor events, AET might be supported */
+ return resctrl_arch_system_max_rmid_idx() > 0;
}
static __init void __check_quirks_intel(void)
diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c
index bc2df287ccfa..e3485dc55923 100644
--- a/arch/x86/kernel/cpu/resctrl/monitor.c
+++ b/arch/x86/kernel/cpu/resctrl/monitor.c
@@ -431,7 +431,7 @@ static void __init intel_rdt_mbm_apply_quirk(u32 num_rmid)
mbm_cf = mbm_cf_table[cf_index].cf;
}
-int __init rdt_get_l3_mon_config(struct rdt_resource *r)
+void __init rdt_get_l3_mon_config(struct rdt_resource *r)
{
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
unsigned int mbm_offset;
@@ -514,8 +514,6 @@ int __init rdt_get_l3_mon_config(struct rdt_resource *r)
intel_rdt_mbm_apply_quirk(r->mon.num_rmid);
r->mon_capable = true;
-
- return 0;
}
static void resctrl_abmc_set_one_amd(void *arg)
diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index de07ccdffdb2..3ac518ed2368 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -3195,6 +3195,11 @@ static int rdt_get_tree(struct fs_context *fc)
goto out;
}
+ if (!resctrl_alloc_capable() && !resctrl_mon_capable()) {
+ ret = -EINVAL;
+ goto out;
+ }
+
ret = setup_rmid_lru_list();
if (ret)
goto out;
@@ -3253,8 +3258,7 @@ static int rdt_get_tree(struct fs_context *fc)
if (resctrl_mon_capable())
resctrl_arch_enable_mon();
- if (resctrl_alloc_capable() || resctrl_mon_capable())
- resctrl_mounted = true;
+ resctrl_mounted = true;
if (resctrl_is_mbm_enabled()) {
r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 14/23] x86/resctrl: Enforce system RMID limit on AET event groups
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (12 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 13/23] x86/resctrl: Handle systems when AET is the only resource Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 15/23] x86/resctrl: Add PMT registration API for AET enumeration callbacks Tony Luck
` (9 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
AET (Application Energy Telemetry) event groups each support a specific
number of RMIDs. But that number may be lower than the number supported
by the system. This is especially true on systems with SNC (Sub-NUMA Cluster)
enabled as that reduces the number of supported RMIDs.
Reduce all event_group::num_rmid to system maximum.
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
Split out as separate patch
arch/x86/kernel/cpu/resctrl/internal.h | 2 ++
arch/x86/kernel/cpu/resctrl/core.c | 2 ++
arch/x86/kernel/cpu/resctrl/intel_aet.c | 19 +++++++++++++++----
3 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h
index d70c8cb1cb81..27dc27480f6e 100644
--- a/arch/x86/kernel/cpu/resctrl/internal.h
+++ b/arch/x86/kernel/cpu/resctrl/internal.h
@@ -235,6 +235,7 @@ void resctrl_arch_mbm_cntr_assign_set_one(struct rdt_resource *r);
#ifdef CONFIG_X86_CPU_RESCTRL_INTEL_AET
bool intel_aet_get_events(void);
+void __init intel_aet_init(void);
void __exit intel_aet_exit(void);
int intel_aet_read_event(int domid, u32 rmid, void *arch_priv, u64 *val);
void intel_aet_mon_domain_setup(int cpu, int id, struct rdt_resource *r,
@@ -242,6 +243,7 @@ void intel_aet_mon_domain_setup(int cpu, int id, struct rdt_resource *r,
bool intel_handle_aet_option(bool force_off, char *tok);
#else
static inline bool intel_aet_get_events(void) { return false; }
+static inline void intel_aet_init(void) { }
static inline void __exit intel_aet_exit(void) { }
static inline int intel_aet_read_event(int domid, u32 rmid, void *arch_priv, u64 *val)
{
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index 0ddec2b67e3d..8b763cf638ef 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -1131,6 +1131,8 @@ static int __init resctrl_arch_late_init(void)
if (!get_rdt_resources())
return -ENODEV;
+ intel_aet_init();
+
state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
"x86/resctrl/cat:online:",
resctrl_arch_online_cpu,
diff --git a/arch/x86/kernel/cpu/resctrl/intel_aet.c b/arch/x86/kernel/cpu/resctrl/intel_aet.c
index 4ad6ad78e93e..fef1081f926d 100644
--- a/arch/x86/kernel/cpu/resctrl/intel_aet.c
+++ b/arch/x86/kernel/cpu/resctrl/intel_aet.c
@@ -65,10 +65,10 @@ struct pmt_event {
* @force_on: True when "rdt" command line overrides disable of this
* event group.
* @guid: Unique number per XML description file.
- * @num_rmid: Number of RMIDs supported by this group. May be
- * adjusted downwards if enumeration from
- * intel_pmt_get_regions_by_feature() indicates fewer
- * RMIDs can be tracked simultaneously.
+ * @num_rmid: Number of RMIDs supported by this group. May be adjusted
+ * downwards if the system supports fewer RMIDs or
+ * enumeration from intel_pmt_get_regions_by_feature()
+ * indicates fewer RMIDs can be tracked simultaneously.
* @mmio_size: Number of bytes of MMIO registers for this group.
* @num_events: Number of events in this group.
* @evts: Array of event descriptors.
@@ -325,6 +325,17 @@ bool intel_aet_get_events(void)
return ret;
}
+void __init intel_aet_init(void)
+{
+ u32 max_rmid = resctrl_arch_system_max_rmid_idx();
+ struct event_group **peg, *e;
+
+ for_each_event_group(peg) {
+ e = *peg;
+ e->num_rmid = min(max_rmid, e->num_rmid);
+ }
+}
+
void __exit intel_aet_exit(void)
{
struct event_group **peg;
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 15/23] x86/resctrl: Add PMT registration API for AET enumeration callbacks
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (13 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 14/23] x86/resctrl: Enforce system RMID limit on AET event groups Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 16/23] platform/x86/intel/pmt: Register enumeration functions with resctrl Tony Luck
` (8 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
resctrl is always built-in; INTEL_PMT_TELEMETRY may be a module. Add, and
export, register/unregister functions so the PMT module can supply/clear
enumeration callback functions when loaded/unloaded.
Suggested-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
No change.
include/linux/intel_vsec.h | 12 ++++++++++++
arch/x86/kernel/cpu/resctrl/intel_aet.c | 24 ++++++++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/include/linux/intel_vsec.h b/include/linux/intel_vsec.h
index 843cda8f8644..c04b1d0f3143 100644
--- a/include/linux/intel_vsec.h
+++ b/include/linux/intel_vsec.h
@@ -257,4 +257,16 @@ static inline void
intel_pmt_put_feature_group(struct pmt_feature_group *feature_group) {}
#endif
+#ifdef CONFIG_X86_CPU_RESCTRL_INTEL_AET
+void intel_aet_register_enumeration(struct module *module,
+ struct pmt_feature_group *(*get)(enum pmt_feature_id id),
+ void (*put)(struct pmt_feature_group *p));
+void intel_aet_unregister_enumeration(void);
+#else
+static inline void intel_aet_register_enumeration(struct module *module,
+ struct pmt_feature_group *(*get)(enum pmt_feature_id id),
+ void (*put)(struct pmt_feature_group *p)) { }
+static inline void intel_aet_unregister_enumeration(void) { }
+#endif /* CONFIG_X86_CPU_RESCTRL_INTEL_AET */
+
#endif
diff --git a/arch/x86/kernel/cpu/resctrl/intel_aet.c b/arch/x86/kernel/cpu/resctrl/intel_aet.c
index fef1081f926d..f5007bea8346 100644
--- a/arch/x86/kernel/cpu/resctrl/intel_aet.c
+++ b/arch/x86/kernel/cpu/resctrl/intel_aet.c
@@ -17,12 +17,14 @@
#include <linux/cpumask.h>
#include <linux/err.h>
#include <linux/errno.h>
+#include <linux/export.h>
#include <linux/gfp_types.h>
#include <linux/init.h>
#include <linux/intel_pmt_features.h>
#include <linux/intel_vsec.h>
#include <linux/io.h>
#include <linux/minmax.h>
+#include <linux/module.h>
#include <linux/printk.h>
#include <linux/rculist.h>
#include <linux/rcupdate.h>
@@ -291,6 +293,10 @@ static enum pmt_feature_id lookup_pfid(const char *pfname)
return FEATURE_INVALID;
}
+static struct module *pmt_module;
+static struct pmt_feature_group *(*get_feature)(enum pmt_feature_id id);
+static void (*put_feature)(struct pmt_feature_group *p);
+
/*
* Request a copy of struct pmt_feature_group for each event group. If there is
* one, the returned structure has an array of telemetry_region structures,
@@ -336,6 +342,24 @@ void __init intel_aet_init(void)
}
}
+void intel_aet_register_enumeration(struct module *module,
+ struct pmt_feature_group *(*get)(enum pmt_feature_id id),
+ void (*put)(struct pmt_feature_group *p))
+{
+ get_feature = get;
+ put_feature = put;
+ pmt_module = module;
+}
+EXPORT_SYMBOL_NS_GPL(intel_aet_register_enumeration, "INTEL_PMT");
+
+void intel_aet_unregister_enumeration(void)
+{
+ pmt_module = NULL;
+ get_feature = NULL;
+ put_feature = NULL;
+}
+EXPORT_SYMBOL_NS_GPL(intel_aet_unregister_enumeration, "INTEL_PMT");
+
void __exit intel_aet_exit(void)
{
struct event_group **peg;
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 16/23] platform/x86/intel/pmt: Register enumeration functions with resctrl
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (14 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 15/23] x86/resctrl: Add PMT registration API for AET enumeration callbacks Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-09-01 11:11 ` Ilpo Järvinen
2026-08-31 17:44 ` [PATCH v11 17/23] arm,x86/resctrl: Resolve INTEL_PMT_TELEMETRY symbols at runtime Tony Luck
` (7 subsequent siblings)
23 siblings, 1 reply; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
INTEL_PMT_TELEMETRY is a loadable module, but resctrl is built-in and cannot
call PMT functions directly.
Use ".probe_type = PROBE_FORCE_SYNCHRONOUS" to ensure sequential, synchronous
calls to per-device .probe() functions. Register the telemetry enumeration
function pointers at the end of pmt_telem_init() when all .probe() functions
have run and enumeration is complete.
Unregister at the start of pmt_telem_exit() before teardown of the
auxiliary drivers.
Suggested-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
Add TAB to line up '=' in .driver initialization
drivers/platform/x86/intel/pmt/telemetry.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c
index 953f35b6daec..2d2282c636b2 100644
--- a/drivers/platform/x86/intel/pmt/telemetry.c
+++ b/drivers/platform/x86/intel/pmt/telemetry.c
@@ -427,16 +427,28 @@ static struct auxiliary_driver pmt_telem_aux_driver = {
.id_table = pmt_telem_id_table,
.remove = pmt_telem_remove,
.probe = pmt_telem_probe,
+ .driver = {
+ .probe_type = PROBE_FORCE_SYNCHRONOUS,
+ },
};
static int __init pmt_telem_init(void)
{
- return auxiliary_driver_register(&pmt_telem_aux_driver);
+ int ret;
+
+ ret = auxiliary_driver_register(&pmt_telem_aux_driver);
+
+ if (!ret)
+ intel_aet_register_enumeration(THIS_MODULE, intel_pmt_get_regions_by_feature,
+ intel_pmt_put_feature_group);
+
+ return ret;
}
module_init(pmt_telem_init);
static void __exit pmt_telem_exit(void)
{
+ intel_aet_unregister_enumeration();
auxiliary_driver_unregister(&pmt_telem_aux_driver);
xa_destroy(&telem_array);
}
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 17/23] arm,x86/resctrl: Resolve INTEL_PMT_TELEMETRY symbols at runtime
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (15 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 16/23] platform/x86/intel/pmt: Register enumeration functions with resctrl Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 18/23] fs/resctrl: Call arch code for every mount Tony Luck
` (6 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
resctrl is always built-in, but INTEL_PMT_TELEMETRY and INTEL_TPMI are
logically independent and should be loadable modules. Switch AET to use the
function-pointer registration API instead of direct link-time references to
PMT symbols.
Prepare for the file system to call resctrl_arch_pre_mount() on every mount
by moving AET enumeration into resctrl_arch_pre_mount() and cleanup into
resctrl_arch_unmount(). This allows the PMT module to be unloaded whenever
the filesystem is not mounted.
intel_aet_exit() was never called because resctrl is built into the kernel. All
cleanup is now handled in the unmount path. Remove intel_aet_exit().
Note that the Linux file system code does not serialize calls to
fs_context_operations::get_tree(), so there may be arbitrarily many parallel
calls if users invoke mount(2) multiple times.
Zero rdt_resource::resctrl_mon::num_rmid for RDT_RESOURCE_PERF_PKG so
that it will be re-computed next mount.
event_group::num_rmid may be reset (reduced) during enumeration. This is
not worth resetting on unmount because the same reduction would occur on
each subsequent mount.
Place a hold on the pmt_telemetry while enumerating AET events during
pre-mount processing. Release the hold if no events were enabled.
Otherwise keep the hold until the resctrl file system is unmounted.
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
Drop unneeded include of <linux/cleanup.h> from core.c
Comment on data protected by aet_register_lock
Add commit comment on module{get,put} activity
include/linux/resctrl.h | 6 +++
arch/x86/kernel/cpu/resctrl/internal.h | 8 ++--
arch/x86/kernel/cpu/resctrl/core.c | 24 ++++++++--
arch/x86/kernel/cpu/resctrl/intel_aet.c | 62 ++++++++++++++++++++++---
drivers/resctrl/mpam_resctrl.c | 4 ++
5 files changed, 90 insertions(+), 14 deletions(-)
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index 4fb06d434c85..0d7fd294b760 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -591,6 +591,12 @@ void resctrl_offline_cpu(unsigned int cpu);
*/
void resctrl_arch_pre_mount(void);
+/*
+ * Architecture hook called when mount fails, or on unmount.
+ * No locks are held.
+ */
+void resctrl_arch_unmount(void);
+
/**
* resctrl_arch_rmid_read() - Read the eventid counter corresponding to rmid
* for this resource and domain.
diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h
index 27dc27480f6e..4409ee20474d 100644
--- a/arch/x86/kernel/cpu/resctrl/internal.h
+++ b/arch/x86/kernel/cpu/resctrl/internal.h
@@ -234,17 +234,17 @@ void rdt_domain_reconfigure_cdp(struct rdt_resource *r);
void resctrl_arch_mbm_cntr_assign_set_one(struct rdt_resource *r);
#ifdef CONFIG_X86_CPU_RESCTRL_INTEL_AET
-bool intel_aet_get_events(void);
void __init intel_aet_init(void);
-void __exit intel_aet_exit(void);
+bool intel_aet_pre_mount(void);
+void intel_aet_unmount(void);
int intel_aet_read_event(int domid, u32 rmid, void *arch_priv, u64 *val);
void intel_aet_mon_domain_setup(int cpu, int id, struct rdt_resource *r,
struct list_head *add_pos);
bool intel_handle_aet_option(bool force_off, char *tok);
#else
-static inline bool intel_aet_get_events(void) { return false; }
static inline void intel_aet_init(void) { }
-static inline void __exit intel_aet_exit(void) { }
+static inline bool intel_aet_pre_mount(void) { return false; }
+static inline void intel_aet_unmount(void) { }
static inline int intel_aet_read_event(int domid, u32 rmid, void *arch_priv, u64 *val)
{
return -EINVAL;
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index 8b763cf638ef..cdcc5611345f 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -20,6 +20,7 @@
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/cpuhotplug.h>
+#include <linux/mutex.h>
#include <asm/cpu_device_id.h>
#include <asm/cpuid/api.h>
@@ -800,7 +801,7 @@ void resctrl_arch_pre_mount(void)
struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_PERF_PKG].r_resctrl;
int cpu;
- if (!intel_aet_get_events())
+ if (!intel_aet_pre_mount())
return;
/*
@@ -816,6 +817,25 @@ void resctrl_arch_pre_mount(void)
cpus_read_unlock();
}
+void resctrl_arch_unmount(void)
+{
+ struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_PERF_PKG].r_resctrl;
+ int cpu;
+
+ if (!r->mon_capable)
+ return;
+
+ intel_aet_unmount();
+
+ cpus_read_lock();
+ mutex_lock(&domain_list_lock);
+ for_each_online_cpu(cpu)
+ domain_remove_cpu_mon(cpu, r);
+ r->mon_capable = false;
+ mutex_unlock(&domain_list_lock);
+ cpus_read_unlock();
+}
+
enum {
RDT_FLAG_CMT,
RDT_FLAG_MBM_TOTAL,
@@ -1160,8 +1180,6 @@ late_initcall(resctrl_arch_late_init);
static void __exit resctrl_arch_exit(void)
{
- intel_aet_exit();
-
cpuhp_remove_state(rdt_online);
resctrl_exit();
diff --git a/arch/x86/kernel/cpu/resctrl/intel_aet.c b/arch/x86/kernel/cpu/resctrl/intel_aet.c
index f5007bea8346..c3bd3536c514 100644
--- a/arch/x86/kernel/cpu/resctrl/intel_aet.c
+++ b/arch/x86/kernel/cpu/resctrl/intel_aet.c
@@ -12,6 +12,7 @@
#define pr_fmt(fmt) "resctrl: " fmt
#include <linux/bits.h>
+#include <linux/cleanup.h>
#include <linux/compiler_types.h>
#include <linux/container_of.h>
#include <linux/cpumask.h>
@@ -25,6 +26,7 @@
#include <linux/io.h>
#include <linux/minmax.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/printk.h>
#include <linux/rculist.h>
#include <linux/rcupdate.h>
@@ -293,10 +295,22 @@ static enum pmt_feature_id lookup_pfid(const char *pfname)
return FEATURE_INVALID;
}
+/*
+ * Protects pmt_module, get_feature, put_feature against races between module
+ * load/unload of the pmt_telemetry module and mount/unmount of the resctrl
+ * file system. Also protects pmt_in_use.
+ */
+static DEFINE_MUTEX(aet_register_lock);
+
static struct module *pmt_module;
static struct pmt_feature_group *(*get_feature)(enum pmt_feature_id id);
static void (*put_feature)(struct pmt_feature_group *p);
+/*
+ * Track whether pmt_telemetry enumeration succeeded during mount for use during unmount.
+ */
+static bool pmt_in_use;
+
/*
* Request a copy of struct pmt_feature_group for each event group. If there is
* one, the returned structure has an array of telemetry_region structures,
@@ -308,7 +322,7 @@ static void (*put_feature)(struct pmt_feature_group *p);
* struct pmt_feature_group to indicate that its events are successfully
* enabled.
*/
-bool intel_aet_get_events(void)
+static bool aet_get_events(void)
{
struct pmt_feature_group *p;
enum pmt_feature_id pfid;
@@ -317,14 +331,14 @@ bool intel_aet_get_events(void)
for_each_event_group(peg) {
pfid = lookup_pfid((*peg)->pfname);
- p = intel_pmt_get_regions_by_feature(pfid);
+ p = get_feature(pfid);
if (IS_ERR_OR_NULL(p))
continue;
if (enable_events(*peg, p)) {
(*peg)->pfg = p;
ret = true;
} else {
- intel_pmt_put_feature_group(p);
+ put_feature(p);
}
}
@@ -346,6 +360,7 @@ void intel_aet_register_enumeration(struct module *module,
struct pmt_feature_group *(*get)(enum pmt_feature_id id),
void (*put)(struct pmt_feature_group *p))
{
+ guard(mutex)(&aet_register_lock);
get_feature = get;
put_feature = put;
pmt_module = module;
@@ -354,22 +369,55 @@ EXPORT_SYMBOL_NS_GPL(intel_aet_register_enumeration, "INTEL_PMT");
void intel_aet_unregister_enumeration(void)
{
+ guard(mutex)(&aet_register_lock);
pmt_module = NULL;
get_feature = NULL;
put_feature = NULL;
}
EXPORT_SYMBOL_NS_GPL(intel_aet_unregister_enumeration, "INTEL_PMT");
-void __exit intel_aet_exit(void)
+bool intel_aet_pre_mount(void)
{
+ guard(mutex)(&aet_register_lock);
+
+ if (!get_feature || !put_feature)
+ return false;
+
+ if (!try_module_get(pmt_module))
+ return false;
+
+ if (!aet_get_events()) {
+ module_put(pmt_module);
+ return false;
+ }
+
+ pmt_in_use = true;
+
+ return true;
+}
+
+void intel_aet_unmount(void)
+{
+ struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_PERF_PKG].r_resctrl;
struct event_group **peg;
+ guard(mutex)(&aet_register_lock);
+ if (!pmt_in_use)
+ return;
+
for_each_event_group(peg) {
- if ((*peg)->pfg) {
- intel_pmt_put_feature_group((*peg)->pfg);
- (*peg)->pfg = NULL;
+ struct event_group *e = *peg;
+
+ if (e->pfg) {
+ for (int i = 0; i < e->num_events; i++)
+ resctrl_disable_mon_event(e->evts[i].id);
+ put_feature(e->pfg);
+ e->pfg = NULL;
}
}
+ module_put(pmt_module);
+ pmt_in_use = false;
+ r->mon.num_rmid = 0;
}
#define DATA_VALID BIT_ULL(63)
diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
index a117aa98ae90..51f83d275a62 100644
--- a/drivers/resctrl/mpam_resctrl.c
+++ b/drivers/resctrl/mpam_resctrl.c
@@ -121,6 +121,10 @@ void resctrl_arch_pre_mount(void)
{
}
+void resctrl_arch_unmount(void)
+{
+}
+
bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level rid)
{
return mpam_resctrl_controls[rid].cdp_enabled;
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 18/23] fs/resctrl: Call arch code for every mount
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (16 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 17/23] arm,x86/resctrl: Resolve INTEL_PMT_TELEMETRY symbols at runtime Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 19/23] x86/resctrl: Export interface to report telemetry unbind/remove Tony Luck
` (5 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
Linux file system code provides no serialization of mount(2) system
calls. Without such serialization calling resctrl_arch_pre_mount() on
every mount before acquiring rdtgroup_mutex would open up many complex
races between mount and unmount operations.
Add resctrl_mount_lock to provide serialization and protect resctrl_mounted.
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
New patch. Locking at file system level replaces v10 attempt
at locking inside architecture resctrl_arch_pre_mount() and
resctrl_arch_unmount()
fs/resctrl/rdtgroup.c | 28 ++++++++++++++++++++++------
1 file changed, 22 insertions(+), 6 deletions(-)
diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index 3ac518ed2368..7f09d76dbf8c 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -30,6 +30,9 @@
#include "internal.h"
+/* Mutex protecting resctrl_mounted and mount/unmount operations */
+static DEFINE_MUTEX(resctrl_mount_lock);
+
/* Mutex to protect rdtgroup access. */
DEFINE_MUTEX(rdtgroup_mutex);
@@ -3149,6 +3152,7 @@ static void resctrl_unmount(void)
{
struct rdt_resource *r;
+ mutex_lock(&resctrl_mount_lock);
cpus_read_lock();
mutex_lock(&rdtgroup_mutex);
@@ -3166,6 +3170,8 @@ static void resctrl_unmount(void)
resctrl_mounted = false;
mutex_unlock(&rdtgroup_mutex);
cpus_read_unlock();
+ resctrl_arch_unmount();
+ mutex_unlock(&resctrl_mount_lock);
}
static int rdt_get_tree(struct fs_context *fc)
@@ -3177,24 +3183,27 @@ static int rdt_get_tree(struct fs_context *fc)
struct rdt_resource *r;
int ret;
- DO_ONCE_SLEEPABLE(resctrl_arch_pre_mount);
+ mutex_lock(&resctrl_mount_lock);
- cpus_read_lock();
- mutex_lock(&rdtgroup_mutex);
/*
* resctrl file system can only be mounted once.
*/
if (resctrl_mounted) {
ret = -EBUSY;
- goto out;
+ goto out_mount_unlock;
}
/* Avoid races from pending operations from a previous mount */
if (atomic_read(&rdtgroup_default.waitcount) != 0) {
ret = -EBUSY;
- goto out;
+ goto out_mount_unlock;
}
+ resctrl_arch_pre_mount();
+
+ cpus_read_lock();
+ mutex_lock(&rdtgroup_mutex);
+
if (!resctrl_alloc_capable() && !resctrl_mon_capable()) {
ret = -EINVAL;
goto out;
@@ -3289,6 +3298,8 @@ static int rdt_get_tree(struct fs_context *fc)
mutex_unlock(&rdtgroup_mutex);
cpus_read_unlock();
+ mutex_unlock(&resctrl_mount_lock);
+
ret = kernfs_get_tree(fc);
/*
* resctrl can only be mounted once, new superblock only expected
@@ -3297,7 +3308,8 @@ static int rdt_get_tree(struct fs_context *fc)
if (!ctx->kfc.new_sb_created)
resctrl_unmount();
kernfs_put(rdt_root_kn);
- return ret;
+
+ return 0;
out_mondata:
if (resctrl_mon_capable())
@@ -3318,8 +3330,12 @@ static int rdt_get_tree(struct fs_context *fc)
out_root:
rdtgroup_destroy_root();
out:
+ resctrl_arch_unmount();
mutex_unlock(&rdtgroup_mutex);
cpus_read_unlock();
+out_mount_unlock:
+ mutex_unlock(&resctrl_mount_lock);
+
return ret;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 19/23] x86/resctrl: Export interface to report telemetry unbind/remove
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (17 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 18/23] fs/resctrl: Call arch code for every mount Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 20/23] platform/x86/intel/pmt: Inform resctrl when MMIO maps are being removed Tony Luck
` (4 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
Linux allows devices to be unbound from drivers, even if the modules
cannot be unloaded because of reference counts.
For telemetry this results in teardown of the virtual address mappings
of the MMIO regions which hold the event counters. Subsequent access
to these counters will page fault.
Export intel_aet_invalidate() for the pmt_telemetry module to inform
resctrl when invalidation is about to happen.
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
Replace bitpmap argument to intel_aet_invalidate() with
package_id. David Box confirmed that unbind/remove operations
do not cross package boundaries.
Mark invalidated event counters by clearing "addr".
include/linux/intel_vsec.h | 2 ++
arch/x86/kernel/cpu/resctrl/intel_aet.c | 25 +++++++++++++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/include/linux/intel_vsec.h b/include/linux/intel_vsec.h
index c04b1d0f3143..bcbf4937c71c 100644
--- a/include/linux/intel_vsec.h
+++ b/include/linux/intel_vsec.h
@@ -262,11 +262,13 @@ void intel_aet_register_enumeration(struct module *module,
struct pmt_feature_group *(*get)(enum pmt_feature_id id),
void (*put)(struct pmt_feature_group *p));
void intel_aet_unregister_enumeration(void);
+void intel_aet_invalidate(u8 package_id);
#else
static inline void intel_aet_register_enumeration(struct module *module,
struct pmt_feature_group *(*get)(enum pmt_feature_id id),
void (*put)(struct pmt_feature_group *p)) { }
static inline void intel_aet_unregister_enumeration(void) { }
+static inline void intel_aet_invalidate(u8 package_id) { }
#endif /* CONFIG_X86_CPU_RESCTRL_INTEL_AET */
#endif
diff --git a/arch/x86/kernel/cpu/resctrl/intel_aet.c b/arch/x86/kernel/cpu/resctrl/intel_aet.c
index c3bd3536c514..5cd2711d00e7 100644
--- a/arch/x86/kernel/cpu/resctrl/intel_aet.c
+++ b/arch/x86/kernel/cpu/resctrl/intel_aet.c
@@ -376,6 +376,29 @@ void intel_aet_unregister_enumeration(void)
}
EXPORT_SYMBOL_NS_GPL(intel_aet_unregister_enumeration, "INTEL_PMT");
+/*
+ * pmt_telemetry driver calls this for unbind/remove operations that
+ * will invalidate the virtual addresses of MMIO registers provided
+ * by intel_pmt_get_regions_by_feature().
+ */
+void intel_aet_invalidate(u8 package_id)
+{
+ struct event_group **peg;
+
+ guard(mutex)(&aet_register_lock);
+ for_each_event_group(peg) {
+ struct event_group *e = *peg;
+
+ if (!e->pfg)
+ continue;
+ for (int i = 0; i < e->pfg->count; i++) {
+ if (e->pfg->regions[i].plat_info.package_id == package_id)
+ e->pfg->regions[i].addr = NULL;
+ }
+ }
+}
+EXPORT_SYMBOL_NS_GPL(intel_aet_invalidate, "INTEL_PMT");
+
bool intel_aet_pre_mount(void)
{
guard(mutex)(&aet_register_lock);
@@ -439,6 +462,8 @@ int intel_aet_read_event(int domid, u32 rmid, void *arch_priv, u64 *val)
void *pevt0;
u32 idx;
+ guard(mutex)(&aet_register_lock);
+
pevt0 = pevt - pevt->idx;
e = container_of(pevt0, struct event_group, evts);
idx = rmid * e->num_events;
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 20/23] platform/x86/intel/pmt: Inform resctrl when MMIO maps are being removed
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (18 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 19/23] x86/resctrl: Export interface to report telemetry unbind/remove Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-09-01 11:09 ` Ilpo Järvinen
2026-08-31 17:44 ` [PATCH v11 21/23] x86/resctrl: Require 64-bit x86 for resctrl support Tony Luck
` (3 subsequent siblings)
23 siblings, 1 reply; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
Before destroying devices, tell resctrl that the virtual addresses
supplied by an earlier call to intel_pmt_get_regions_by_feature()
are about to be invalidated and should not be used again.
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
Unbind/remove operations can't cross package boundaries.
Psss package_id instead of bitmap of package IDs.
Use dev_warn() to report failure to find package_id.
drivers/platform/x86/intel/pmt/telemetry.c | 32 ++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c
index 2d2282c636b2..92871ce51c57 100644
--- a/drivers/platform/x86/intel/pmt/telemetry.c
+++ b/drivers/platform/x86/intel/pmt/telemetry.c
@@ -366,11 +366,43 @@ pmt_telem_find_and_register_endpoint(struct device *dev, u32 guid, u16 pos)
}
EXPORT_SYMBOL_NS_GPL(pmt_telem_find_and_register_endpoint, "INTEL_PMT_TELEMETRY");
+static int pmt_telem_get_package_id(struct pmt_telem_priv *priv)
+{
+ u32 ret = -1;
+ int i;
+
+ mutex_lock(&ep_lock);
+ for (i = 0; i < priv->num_entries; i++) {
+ struct intel_pmt_entry *entry = &priv->entry[i];
+ struct pci_dev *pdev = to_pci_dev(entry->ep->dev);
+ struct oobmsm_plat_info *plat_info;
+
+ plat_info = intel_vsec_get_mapping(pdev);
+ if (!IS_ERR(plat_info)) {
+ ret = plat_info->package_id;
+ break;
+ }
+ }
+ mutex_unlock(&ep_lock);
+
+ return ret;
+}
+
static void pmt_telem_remove(struct auxiliary_device *auxdev)
{
struct pmt_telem_priv *priv = auxiliary_get_drvdata(auxdev);
+ int package_id = pmt_telem_get_package_id(priv);
int i;
+ /*
+ * Tell resctrl/AET that virtual mappings for MMIO space in a CPU
+ * packages are about to be torn down.
+ */
+ if (package_id != -1)
+ intel_aet_invalidate(package_id);
+ else
+ dev_warn(&auxdev->dev, "Unable to determine package ID for removed device\n");
+
mutex_lock(&ep_lock);
for (i = 0; i < priv->num_entries; i++) {
struct intel_pmt_entry *entry = &priv->entry[i];
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 21/23] x86/resctrl: Require 64-bit x86 for resctrl support
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (19 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 20/23] platform/x86/intel/pmt: Inform resctrl when MMIO maps are being removed Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 22/23] x86/resctrl: Simplify Kconfig options for resctrl Tony Luck
` (2 subsequent siblings)
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
Intel Application Energy Telemetry (AET) provides event counts in 64-bit
registers in MMIO space. For accurate results these should be read with a
single 64-bit load operation from the CPU.
In preparation for the removal of the separate CONFIG_X86_CPU_RESCTRL_INTEL_AET
configuration option, move the X86_64 dependency to X86_CPU_RESCTRL.
This in inline with Dave Hansen's proposal[1] for an addition to Linux
documentation that details the state of 32-bit x86 support.
Signed-off-by: Tony Luck <tony.luck@intel.com>
Link: https://lore.kernel.org/all/c6ab0c24-8931-4f0d-9be6-23498ab4c38b@intel.com/ [1]
---
v11:
Provide more accurate justification on why 32-bit support is not useful
for resctrl.
arch/x86/Kconfig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 15fd9ec5ecac..06b5d0c4633e 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -518,7 +518,7 @@ config X86_MPPARSE
config X86_CPU_RESCTRL
bool "x86 CPU resource control support"
- depends on X86 && (CPU_SUP_INTEL || CPU_SUP_AMD)
+ depends on X86_64 && (CPU_SUP_INTEL || CPU_SUP_AMD)
depends on MISC_FILESYSTEMS
select ARCH_HAS_CPU_RESCTRL
select RESCTRL_FS
@@ -541,7 +541,7 @@ config X86_CPU_RESCTRL
config X86_CPU_RESCTRL_INTEL_AET
bool "Intel Application Energy Telemetry"
- depends on X86_64 && X86_CPU_RESCTRL && CPU_SUP_INTEL && INTEL_PMT_TELEMETRY=y && INTEL_TPMI=y
+ depends on X86_CPU_RESCTRL && CPU_SUP_INTEL && INTEL_PMT_TELEMETRY=y && INTEL_TPMI=y
help
Enable per-RMID telemetry events in resctrl.
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 22/23] x86/resctrl: Simplify Kconfig options for resctrl
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (20 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 21/23] x86/resctrl: Require 64-bit x86 for resctrl support Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-08-31 17:44 ` [PATCH v11 23/23] x86/resctrl: Document telemetry mount timing caveat Tony Luck
2026-09-01 19:53 ` [PATCH v11 00/23] Allow AET to use PMT as loadable module Luck, Tony
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
Linus Torvalds complained[1] about Kconfig complexity making it too
hard for "random people to build their own kernels".
CONFIG_X86_CPU_RESCTRL_INTEL_AET has been causing problems since it was
first added as it required other config options to be set to "built-in".
AET now resolves PMT symbols at runtime via the registration API,
so INTEL_PMT_TELEMETRY no longer needs to be built-in. This means
that AET can be included unconditionally as part of X86_CPU_RESCTRL.
Signed-off-by: Tony Luck <tony.luck@intel.com>
Link: https://lore.kernel.org/all/CAHk-=whigg3hvOy7c1j1MXFy6o6CHp0g4Tc3Y-MAk+XDssHU0A@mail.gmail.com # 1
---
v11:
Drop the intel_aet*() stubs from internal.h
include/linux/intel_vsec.h | 4 ++--
arch/x86/kernel/cpu/resctrl/internal.h | 14 --------------
arch/x86/Kconfig | 13 -------------
arch/x86/kernel/cpu/resctrl/Makefile | 2 +-
4 files changed, 3 insertions(+), 30 deletions(-)
diff --git a/include/linux/intel_vsec.h b/include/linux/intel_vsec.h
index bcbf4937c71c..885f8e3ab057 100644
--- a/include/linux/intel_vsec.h
+++ b/include/linux/intel_vsec.h
@@ -257,7 +257,7 @@ static inline void
intel_pmt_put_feature_group(struct pmt_feature_group *feature_group) {}
#endif
-#ifdef CONFIG_X86_CPU_RESCTRL_INTEL_AET
+#ifdef CONFIG_X86_CPU_RESCTRL
void intel_aet_register_enumeration(struct module *module,
struct pmt_feature_group *(*get)(enum pmt_feature_id id),
void (*put)(struct pmt_feature_group *p));
@@ -269,6 +269,6 @@ static inline void intel_aet_register_enumeration(struct module *module,
void (*put)(struct pmt_feature_group *p)) { }
static inline void intel_aet_unregister_enumeration(void) { }
static inline void intel_aet_invalidate(u8 package_id) { }
-#endif /* CONFIG_X86_CPU_RESCTRL_INTEL_AET */
+#endif /* CONFIG_X86_CPU_RESCTRL */
#endif
diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h
index 4409ee20474d..d88f9f82c9cb 100644
--- a/arch/x86/kernel/cpu/resctrl/internal.h
+++ b/arch/x86/kernel/cpu/resctrl/internal.h
@@ -233,7 +233,6 @@ bool rdt_cpu_has(int flag);
void rdt_domain_reconfigure_cdp(struct rdt_resource *r);
void resctrl_arch_mbm_cntr_assign_set_one(struct rdt_resource *r);
-#ifdef CONFIG_X86_CPU_RESCTRL_INTEL_AET
void __init intel_aet_init(void);
bool intel_aet_pre_mount(void);
void intel_aet_unmount(void);
@@ -241,18 +240,5 @@ int intel_aet_read_event(int domid, u32 rmid, void *arch_priv, u64 *val);
void intel_aet_mon_domain_setup(int cpu, int id, struct rdt_resource *r,
struct list_head *add_pos);
bool intel_handle_aet_option(bool force_off, char *tok);
-#else
-static inline void intel_aet_init(void) { }
-static inline bool intel_aet_pre_mount(void) { return false; }
-static inline void intel_aet_unmount(void) { }
-static inline int intel_aet_read_event(int domid, u32 rmid, void *arch_priv, u64 *val)
-{
- return -EINVAL;
-}
-
-static inline void intel_aet_mon_domain_setup(int cpu, int id, struct rdt_resource *r,
- struct list_head *add_pos) { }
-static inline bool intel_handle_aet_option(bool force_off, char *tok) { return false; }
-#endif
#endif /* _ASM_X86_RESCTRL_INTERNAL_H */
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 06b5d0c4633e..47f92613434e 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -539,19 +539,6 @@ config X86_CPU_RESCTRL
Say N if unsure.
-config X86_CPU_RESCTRL_INTEL_AET
- bool "Intel Application Energy Telemetry"
- depends on X86_CPU_RESCTRL && CPU_SUP_INTEL && INTEL_PMT_TELEMETRY=y && INTEL_TPMI=y
- help
- Enable per-RMID telemetry events in resctrl.
-
- Intel feature that collects per-RMID execution data
- about energy consumption, measure of frequency independent
- activity and other performance metrics. Data is aggregated
- per package.
-
- Say N if unsure.
-
config X86_FRED
bool "Flexible Return and Event Delivery"
depends on X86_64
diff --git a/arch/x86/kernel/cpu/resctrl/Makefile b/arch/x86/kernel/cpu/resctrl/Makefile
index 273ddfa30836..97ceb4e44dfa 100644
--- a/arch/x86/kernel/cpu/resctrl/Makefile
+++ b/arch/x86/kernel/cpu/resctrl/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_X86_CPU_RESCTRL) += core.o rdtgroup.o monitor.o
obj-$(CONFIG_X86_CPU_RESCTRL) += ctrlmondata.o
-obj-$(CONFIG_X86_CPU_RESCTRL_INTEL_AET) += intel_aet.o
+obj-$(CONFIG_X86_CPU_RESCTRL) += intel_aet.o
obj-$(CONFIG_RESCTRL_FS_PSEUDO_LOCK) += pseudo_lock.o
# To allow define_trace.h's recursive include:
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v11 23/23] x86/resctrl: Document telemetry mount timing caveat
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (21 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 22/23] x86/resctrl: Simplify Kconfig options for resctrl Tony Luck
@ 2026-08-31 17:44 ` Tony Luck
2026-09-01 19:53 ` [PATCH v11 00/23] Allow AET to use PMT as loadable module Luck, Tony
23 siblings, 0 replies; 27+ messages in thread
From: Tony Luck @ 2026-08-31 17:44 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches, Tony Luck
The PMT driver enumerates telemetry features asynchronously, so an
automatic mount of resctrl from /etc/fstab early in boot may occur before
those features are available, resulting in them not being enabled in the
mounted instance.
Add a footnote to the 'If telemetry monitoring is enabled' sentence
pointing readers to a new "Mounting resctrl with telemetry" section. That
section explains the race and provides example systemd service and udev
rule snippets that defer the mount until after the pmt_telemetry module
has loaded.
Assisted-by: Claude:Opus_4.7
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
v11:
No change
Documentation/filesystems/resctrl.rst | 60 ++++++++++++++++++++++++++-
1 file changed, 59 insertions(+), 1 deletion(-)
diff --git a/Documentation/filesystems/resctrl.rst b/Documentation/filesystems/resctrl.rst
index e4b66af55ffb..e34910ac589c 100644
--- a/Documentation/filesystems/resctrl.rst
+++ b/Documentation/filesystems/resctrl.rst
@@ -630,7 +630,7 @@ When monitoring is enabled all MON groups will also contain:
each instance of an L3 cache. Each directory contains files for the enabled
L3 events (e.g. "llc_occupancy", "mbm_total_bytes", and "mbm_local_bytes").
- If telemetry monitoring is enabled, there will be a "mon_PERF_PKG_YY"
+ If telemetry monitoring is enabled [#]_, there will be a "mon_PERF_PKG_YY"
directory for each physical processor package. Each directory contains
files for the enabled telemetry events (e.g. "core_energy". "activity",
"uops_retired", etc.)
@@ -669,6 +669,10 @@ When monitoring is enabled all MON groups will also contain:
returned if the MBM event does not have an assigned counter in the
CTRL_MON group nor in any of its associated MON groups.
+.. [#] Telemetry features are enumerated asynchronously by the PMT driver, so
+ an automatic mount of resctrl from ``/etc/fstab`` at boot may not enable
+ them. See `Mounting resctrl with telemetry`_ below.
+
"mon_hw_id":
Available only with debug option. The identifier used by hardware
for the monitor group. On x86 this is the RMID.
@@ -1898,6 +1902,60 @@ m. Unmount the resctrl filesystem.
# umount /sys/fs/resctrl/
+Mounting resctrl with telemetry
+===============================
+
+Telemetry features (e.g. the ``mon_PERF_PKG_YY`` events) are enumerated
+asynchronously by the PMT driver. If resctrl is mounted before that
+enumeration completes - for example, when mounted automatically from
+``/etc/fstab`` early in boot - the telemetry features will not be available
+at mount time and will therefore not be enabled in the mounted instance.
+
+To avoid this race, defer the mount until after the ``pmt_telemetry`` module
+has loaded. One way to do this is with a udev rule that triggers a systemd
+service when the module appears. A tmpfs mount onto ``/sys/fs/resctrl`` is
+needed to prevent daemon tasks from obtaining references to the resctrl
+file system in the other namespaces that systemd uses during startup.
+
+Example systemd tmpfs mount service (``/etc/systemd/system/sys-fs-resctrl.mount``)::
+
+ [Unit]
+ Description=Early Resctrl Namespace Firewall
+ DefaultDependencies=no
+ Before=basic.target local-fs.target
+
+ [Mount]
+ What=tmpfs
+ Where=/sys/fs/resctrl
+ Type=tmpfs
+ Options=private,nosuid,nodev,noexec,mode=755
+
+ [Install]
+ WantedBy=sysinit.target
+
+Example systemd service (``/etc/systemd/system/mount-resctrl.service``)::
+
+ [Unit]
+ Description=Mount real resctrl pseudo-filesystem natively
+ DefaultDependencies=no
+ Requires=sys-fs-resctrl.mount
+ After=sys-fs-resctrl.mount
+
+ [Service]
+ Type=oneshot
+ # Pause to let systemd start daemons (delay may need per-system tuning)
+ ExecStart=/usr/bin/sleep 10
+ # Mount the real resctrl file system
+ ExecStart=/usr/bin/mount -t resctrl resctrl /sys/fs/resctrl
+ RemainAfterExit=no
+
+ [Install]
+ WantedBy=multi-user.target
+
+Example udev rule (``/etc/udev/rules.d/99-rmid-telemetry.rules``)::
+
+ SUBSYSTEM=="module", KERNEL=="pmt_telemetry", ACTION=="add", RUN+="/usr/bin/systemctl start mount-resctrl.service"
+
Intel RDT Errata
================
--
2.55.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH v11 20/23] platform/x86/intel/pmt: Inform resctrl when MMIO maps are being removed
2026-08-31 17:44 ` [PATCH v11 20/23] platform/x86/intel/pmt: Inform resctrl when MMIO maps are being removed Tony Luck
@ 2026-09-01 11:09 ` Ilpo Järvinen
0 siblings, 0 replies; 27+ messages in thread
From: Ilpo Järvinen @ 2026-09-01 11:09 UTC (permalink / raw)
To: Tony Luck
Cc: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86, Christoph Hellwig, LKML, patches
On Mon, 31 Aug 2026, Tony Luck wrote:
> Before destroying devices, tell resctrl that the virtual addresses
> supplied by an earlier call to intel_pmt_get_regions_by_feature()
> are about to be invalidated and should not be used again.
>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> ---
> v11:
> Unbind/remove operations can't cross package boundaries.
> Psss package_id instead of bitmap of package IDs.
> Use dev_warn() to report failure to find package_id.
>
> drivers/platform/x86/intel/pmt/telemetry.c | 32 ++++++++++++++++++++++
> 1 file changed, 32 insertions(+)
>
> diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c
> index 2d2282c636b2..92871ce51c57 100644
> --- a/drivers/platform/x86/intel/pmt/telemetry.c
> +++ b/drivers/platform/x86/intel/pmt/telemetry.c
> @@ -366,11 +366,43 @@ pmt_telem_find_and_register_endpoint(struct device *dev, u32 guid, u16 pos)
> }
> EXPORT_SYMBOL_NS_GPL(pmt_telem_find_and_register_endpoint, "INTEL_PMT_TELEMETRY");
>
> +static int pmt_telem_get_package_id(struct pmt_telem_priv *priv)
> +{
> + u32 ret = -1;
> + int i;
> +
> + mutex_lock(&ep_lock);
> + for (i = 0; i < priv->num_entries; i++) {
> + struct intel_pmt_entry *entry = &priv->entry[i];
> + struct pci_dev *pdev = to_pci_dev(entry->ep->dev);
> + struct oobmsm_plat_info *plat_info;
> +
> + plat_info = intel_vsec_get_mapping(pdev);
> + if (!IS_ERR(plat_info)) {
> + ret = plat_info->package_id;
Use guard() and a direct return, no need to complicate code flow anymore
just for handling unlocking.
> + break;
> + }
> + }
> + mutex_unlock(&ep_lock);
> +
> + return ret;
> +}
> +
> static void pmt_telem_remove(struct auxiliary_device *auxdev)
> {
> struct pmt_telem_priv *priv = auxiliary_get_drvdata(auxdev);
> + int package_id = pmt_telem_get_package_id(priv);
> int i;
>
> + /*
> + * Tell resctrl/AET that virtual mappings for MMIO space in a CPU
> + * packages are about to be torn down.
> + */
> + if (package_id != -1)
> + intel_aet_invalidate(package_id);
> + else
> + dev_warn(&auxdev->dev, "Unable to determine package ID for removed device\n");
Why to print this? To me it looks like dev_dbg() material at most, if even
that.
> +
> mutex_lock(&ep_lock);
> for (i = 0; i < priv->num_entries; i++) {
> struct intel_pmt_entry *entry = &priv->entry[i];
>
--
i.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v11 16/23] platform/x86/intel/pmt: Register enumeration functions with resctrl
2026-08-31 17:44 ` [PATCH v11 16/23] platform/x86/intel/pmt: Register enumeration functions with resctrl Tony Luck
@ 2026-09-01 11:11 ` Ilpo Järvinen
0 siblings, 0 replies; 27+ messages in thread
From: Ilpo Järvinen @ 2026-09-01 11:11 UTC (permalink / raw)
To: Tony Luck
Cc: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86, Christoph Hellwig, LKML, patches
On Mon, 31 Aug 2026, Tony Luck wrote:
> INTEL_PMT_TELEMETRY is a loadable module, but resctrl is built-in and cannot
> call PMT functions directly.
>
> Use ".probe_type = PROBE_FORCE_SYNCHRONOUS" to ensure sequential, synchronous
> calls to per-device .probe() functions. Register the telemetry enumeration
> function pointers at the end of pmt_telem_init() when all .probe() functions
> have run and enumeration is complete.
>
> Unregister at the start of pmt_telem_exit() before teardown of the
> auxiliary drivers.
>
> Suggested-by: Christoph Hellwig <hch@infradead.org>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> ---
> v11:
> Add TAB to line up '=' in .driver initialization
>
> drivers/platform/x86/intel/pmt/telemetry.c | 14 +++++++++++++-
> 1 file changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c
> index 953f35b6daec..2d2282c636b2 100644
> --- a/drivers/platform/x86/intel/pmt/telemetry.c
> +++ b/drivers/platform/x86/intel/pmt/telemetry.c
> @@ -427,16 +427,28 @@ static struct auxiliary_driver pmt_telem_aux_driver = {
> .id_table = pmt_telem_id_table,
> .remove = pmt_telem_remove,
> .probe = pmt_telem_probe,
> + .driver = {
> + .probe_type = PROBE_FORCE_SYNCHRONOUS,
> + },
> };
>
> static int __init pmt_telem_init(void)
> {
> - return auxiliary_driver_register(&pmt_telem_aux_driver);
> + int ret;
> +
> + ret = auxiliary_driver_register(&pmt_telem_aux_driver);
> +
> + if (!ret)
> + intel_aet_register_enumeration(THIS_MODULE, intel_pmt_get_regions_by_feature,
> + intel_pmt_put_feature_group);
Preferably reverse the logic and handle the error first.
> +
> + return ret;
> }
> module_init(pmt_telem_init);
>
> static void __exit pmt_telem_exit(void)
> {
> + intel_aet_unregister_enumeration();
> auxiliary_driver_unregister(&pmt_telem_aux_driver);
> xa_destroy(&telem_array);
> }
>
--
i.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v11 00/23] Allow AET to use PMT as loadable module
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
` (22 preceding siblings ...)
2026-08-31 17:44 ` [PATCH v11 23/23] x86/resctrl: Document telemetry mount timing caveat Tony Luck
@ 2026-09-01 19:53 ` Luck, Tony
23 siblings, 0 replies; 27+ messages in thread
From: Luck, Tony @ 2026-09-01 19:53 UTC (permalink / raw)
To: Fenghua Yu, Reinette Chatre, Maciej Wieczor-Retman, Peter Newman,
James Morse, Babu Moger, Drew Fustini, Dave Martin, Chen Yu,
David E Box, x86
Cc: Christoph Hellwig, linux-kernel, patches
On Mon, Aug 31, 2026 at 10:43:58AM -0700, Tony Luck wrote:
> Requiring INTEL_PMT_TELEMETRY=y to enable AET is a functional workaround
> to enable enumeration of Application Energy Telemetry (AET) events, but
> unacceptable to many users. It results in increased configuration complexity,
> increased kernel memory footprint and inability to patch problems by unloading
> a module and loading an updated version.
>
> Add a registration function to the AET code that can be used by
> INTEL_PMT_TELEMETRY to provide the enumeration functions.
>
> INTEL_PMT_TELEMETRY can be loaded/unloaded independently of
> resctrl file system mount/unmount. Perform enumeration on
> every mount and cleanup on every unmount.
Summary of Sashiko findings:
https://sashiko.dev/#/patchset/20260831174421.13921-1-tony.luck%40intel.com
[PATCH v11 09/23] fs/resctrl: Remove redundant calls to resctrl_mon_capable()
Pre-existing issue that systems supporting only monitoring will not
report any tasks in the default group. Issue is real. Sashiko suggests
removing the check for resctrl_alloc_capable(). I should have done this
anyway for the same optimization reasons that I removed resctrl_mon_capable()
from is_rmid_match().
[PATCH v11 16/23] platform/x86/intel/pmt: Register enumeration functions with resctrl
Pre-existing potential race. Sashiko suggests calling intel_pmt_get_features()
under ep_lock.
[PATCH v11 18/23] fs/resctrl: Call arch code for every mount
Two broken bits, both with easy (I hope) fixes:
1) rdt_get_tree() should "return ret;" not "return 0;"
2) resctrl_arch_unmount() called in error path before cpus_read_unlock()
could deadlock. Move the resctrl_arch_unmount() after the unlock.
[PATCH v11 20/23] platform/x86/intel/pmt: Inform resctrl when MMIO maps are being removed
Sashiko is concerned about non-PCI telemetry end points. Not a real
issue. Endpoints are enumerated using PCIe DVSEC - so they have to be
PCIe devices.
Pollution of kernel log with dev_warn(). Ilpo also flagged this. It's a
"can't happen" test. I will downgrade severity to dev_dbg()
Pre-existing issue in telemetry driver that other places need to handle
unbind/remove of devices and unmap of MMIO.
[PATCH v11 23/23] x86/resctrl: Document telemetry mount timing caveat
I'm still struggling to come up with a systemd/udev way to delay
mounting the resctrl file system until after telemetry enumeration
is complete. Sashiko says there are gaps in the example I provide.
The whole namespace issue is a mystery to me :-(
-Tony
^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2026-09-01 19:53 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-31 17:43 [PATCH v11 00/23] Allow AET to use PMT as loadable module Tony Luck
2026-08-31 17:43 ` [PATCH v11 01/23] x86/resctrl: Give better names to X86_FEATURE flags for monitoring Tony Luck
2026-08-31 17:44 ` [PATCH v11 02/23] x86/resctrl: Check if monitoring features are enabled Tony Luck
2026-08-31 17:44 ` [PATCH v11 03/23] x86/resctrl: Enumerate monitor features in rdt_get_l3_mon_config() Tony Luck
2026-08-31 17:44 ` [PATCH v11 04/23] x86/resctrl: Apply Intel MBM quirk from rdt_get_l3_mon_config() Tony Luck
2026-08-31 17:44 ` [PATCH v11 05/23] x86/resctrl: Delete resctrl_cpu_detect() Tony Luck
2026-08-31 17:44 ` [PATCH v11 06/23] arm,x86,fs/resctrl: Replace architecture resctrl_arch_{alloc,mon}_capable() Tony Luck
2026-08-31 17:44 ` [PATCH v11 07/23] x86/resctrl: Add special case for Intel Haswell enumeration Tony Luck
2026-08-31 17:44 ` [PATCH v11 08/23] x86/resctrl: Delete rdt_alloc_capable and rdt_mon_capable Tony Luck
2026-08-31 17:44 ` [PATCH v11 09/23] fs/resctrl: Remove redundant calls to resctrl_mon_capable() Tony Luck
2026-08-31 17:44 ` [PATCH v11 10/23] x86/resctrl: Honor rdt=perf option to force enable AET perf events Tony Luck
2026-08-31 17:44 ` [PATCH v11 11/23] fs/resctrl: Add interface to disable a monitor event Tony Luck
2026-08-31 17:44 ` [PATCH v11 12/23] arm,x86,fs/resctrl: Handle change in number of RMIDs on each mount Tony Luck
2026-08-31 17:44 ` [PATCH v11 13/23] x86/resctrl: Handle systems when AET is the only resource Tony Luck
2026-08-31 17:44 ` [PATCH v11 14/23] x86/resctrl: Enforce system RMID limit on AET event groups Tony Luck
2026-08-31 17:44 ` [PATCH v11 15/23] x86/resctrl: Add PMT registration API for AET enumeration callbacks Tony Luck
2026-08-31 17:44 ` [PATCH v11 16/23] platform/x86/intel/pmt: Register enumeration functions with resctrl Tony Luck
2026-09-01 11:11 ` Ilpo Järvinen
2026-08-31 17:44 ` [PATCH v11 17/23] arm,x86/resctrl: Resolve INTEL_PMT_TELEMETRY symbols at runtime Tony Luck
2026-08-31 17:44 ` [PATCH v11 18/23] fs/resctrl: Call arch code for every mount Tony Luck
2026-08-31 17:44 ` [PATCH v11 19/23] x86/resctrl: Export interface to report telemetry unbind/remove Tony Luck
2026-08-31 17:44 ` [PATCH v11 20/23] platform/x86/intel/pmt: Inform resctrl when MMIO maps are being removed Tony Luck
2026-09-01 11:09 ` Ilpo Järvinen
2026-08-31 17:44 ` [PATCH v11 21/23] x86/resctrl: Require 64-bit x86 for resctrl support Tony Luck
2026-08-31 17:44 ` [PATCH v11 22/23] x86/resctrl: Simplify Kconfig options for resctrl Tony Luck
2026-08-31 17:44 ` [PATCH v11 23/23] x86/resctrl: Document telemetry mount timing caveat Tony Luck
2026-09-01 19:53 ` [PATCH v11 00/23] Allow AET to use PMT as loadable module Luck, Tony
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).