From: Chen Yu <yu.c.chen@intel.com>
To: tony.luck@intel.com, reinette.chatre@intel.com
Cc: x86@kernel.org, linux-kernel@vger.kernel.org, tglx@kernel.org,
mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com,
hpa@zytor.com, Dave.Martin@arm.com, james.morse@arm.com,
babu.moger@amd.com, fenghuay@nvidia.com,
Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>,
Chen Yu <yu.c.chen@intel.com>
Subject: [RFC PATCH 6/6] x86/resctrl: Add support for L3 occupancy monitoring via RMID MMIO read
Date: Wed, 27 May 2026 17:28:12 +0800 [thread overview]
Message-ID: <7c717b9100d0fd408ce1bfa754b7783b3dbadbb6.1779872016.git.yu.c.chen@intel.com> (raw)
In-Reply-To: <cover.1779872016.git.yu.c.chen@intel.com>
The CMRC (Cache Monitoring Registers for CPU Agents Description)
ACPI sub-table provides the MMIO address used to read the LLC
occupancy counter for each RMID. When ERDT is enabled on the
platform, use this MMIO interface instead of the legacy MSR read
to obtain the L3 occupancy value.
Introduce erdt_mon_read(), a helper that retrieves monitoring
data for a given RMID and event ID from an ERDT domain. Initial
support is added for the L3 occupancy monitoring event
(QOS_L3_OCCUP_EVENT_ID).
If the platform supports ERDT, CMRC-based MMIO access is used by
default. If ERDT is unavailable, the implementation is to use
MSR-based operations.
Suggested-by: Tony Luck <tony.luck@intel.com>
Co-developed-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: Chen Yu <yu.c.chen@intel.com>
---
arch/x86/include/asm/resctrl.h | 2 +
arch/x86/kernel/cpu/resctrl/core.c | 2 +-
arch/x86/kernel/cpu/resctrl/erdt.c | 90 +++++++++++++++++++++++++++
arch/x86/kernel/cpu/resctrl/monitor.c | 7 +++
4 files changed, 100 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h
index 97c2f6bc7a5f..9b3b03279dd8 100644
--- a/arch/x86/include/asm/resctrl.h
+++ b/arch/x86/include/asm/resctrl.h
@@ -41,6 +41,8 @@ struct resctrl_pqr_state {
};
bool erdt_enabled(void);
+struct rdt_domain_hdr;
+int erdt_mon_read(struct rdt_domain_hdr *hdr, int ev_id, int rmid, u64 *val);
DECLARE_PER_CPU(struct resctrl_pqr_state, pqr_state);
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index 893d2efe76f0..6e0feae2595c 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -965,7 +965,7 @@ static __init bool get_rdt_mon_resources(void)
bool ret = false;
if (rdt_cpu_has(X86_FEATURE_CQM_OCCUP_LLC)) {
- resctrl_enable_mon_event(QOS_L3_OCCUP_EVENT_ID, false, 0, NULL);
+ resctrl_enable_mon_event(QOS_L3_OCCUP_EVENT_ID, erdt_enabled(), 0, NULL);
ret = true;
}
if (rdt_cpu_has(X86_FEATURE_CQM_MBM_TOTAL)) {
diff --git a/arch/x86/kernel/cpu/resctrl/erdt.c b/arch/x86/kernel/cpu/resctrl/erdt.c
index 30b7dfd99086..6180f14ab377 100644
--- a/arch/x86/kernel/cpu/resctrl/erdt.c
+++ b/arch/x86/kernel/cpu/resctrl/erdt.c
@@ -39,6 +39,7 @@ static DEFINE_XARRAY(erdt_domain_xa); /* Indexed by L3 cache ID */
#define ERDT_VALID_VERSION 1
#define CMRC_VALID_INDEX_FUNC_VERSION 1
+#define UNAVAILABLE_COUNTER BIT_ULL(63)
static u32 valid_subtbl_mask;
@@ -65,6 +66,95 @@ static __init int lookup_logical_cpu_by_x2apicid(u32 x2apicid)
return -1;
}
+static void __iomem *cmrc_index_function_1(struct erdt_domain_info *d,
+ struct acpi_erdt_cmrc *cmrc, int rmid)
+{
+ u16 clump_size, stride_size;
+ void __iomem *vaddr;
+
+ clump_size = cmrc->clump_size;
+ stride_size = cmrc->clump_stride;
+
+ /*
+ * MMIO_ADDRESS_for_RMID# = CMRC Base +
+ * (RMID / ClumpSize) * Stride +
+ * (RMID % ClumpSize) * 8
+ */
+ vaddr = d->base[ERDT_MMIO_CMRC_BASE] +
+ (rmid / clump_size) * stride_size +
+ (rmid % clump_size) * 8;
+
+ return vaddr;
+}
+
+/*
+ * erdt_read_l3_occupancy - Read L3 occupancy count for a given RMID
+ * @d: Pointer to the ERDT domain info
+ * @rmid: Resource Monitoring ID to read occupancy for
+ *
+ * Calculates the MMIO address using clump and stride information
+ * from the CMRC ACPI structure and reads the L3 cache occupancy
+ * count for the given RMID. The raw value is scaled using the
+ * up_scale factor provided by firmware.
+ *
+ * Return: 0 for success, error code for other cases.
+ */
+static int erdt_read_l3_occupancy(struct erdt_domain_info *d, int rmid,
+ u64 *val)
+{
+ struct acpi_erdt_cmrc *cmrc;
+ void __iomem *vaddr;
+ u64 l3_cmt_count;
+ u32 offset;
+
+ cmrc = d->cmrc;
+ if (!cmrc)
+ return -EIO;
+
+ offset = (rmid / cmrc->clump_size) * cmrc->clump_stride +
+ (rmid % cmrc->clump_size) * 8;
+ if (offset + sizeof(u64) > (u32)cmrc->cmt_reg_size << 12)
+ return -EINVAL;
+
+ vaddr = cmrc_index_function_1(d, cmrc, rmid);
+
+ l3_cmt_count = readq(vaddr);
+ if (l3_cmt_count & UNAVAILABLE_COUNTER)
+ return -EINVAL;
+
+ *val = l3_cmt_count * cmrc->up_scale;
+
+ return 0;
+}
+
+/*
+ * erdt_mon_read - Read monitoring data for a given domain and RMID
+ * @hdr: Domain header
+ * @ev_id: Monitoring event ID (e.g. QOS_L3_OCCUP_EVENT_ID)
+ * @rmid: Resource Monitoring ID for which to read the data
+ * @val: Store the read data
+ *
+ * Looks up the domain by domid and dispatches the read request
+ * to the appropriate helper based on the event type.
+ * Currently supports only L3 occupancy monitoring.
+ *
+ * Return 0 on succeed, error code otherwise.
+ */
+int erdt_mon_read(struct rdt_domain_hdr *hdr, int ev_id, int rmid,
+ u64 *val)
+{
+ struct erdt_domain_info *d;
+
+ d = xa_load(&erdt_domain_xa, hdr->id);
+ if (!d)
+ return -EIO;
+
+ if (ev_id == QOS_L3_OCCUP_EVENT_ID)
+ return erdt_read_l3_occupancy(d, rmid, val);
+
+ return -EINVAL;
+}
+
/*
* get_l3_cache_id_from_cacd - Resolve L3 cache ID from CACD subtable
* @cacd: Pointer to the ACPI ERDT CACD structure
diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c
index 1e81b3c33843..12b4014e47f3 100644
--- a/arch/x86/kernel/cpu/resctrl/monitor.c
+++ b/arch/x86/kernel/cpu/resctrl/monitor.c
@@ -278,6 +278,13 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain_hdr *hdr,
switch (r->rid) {
case RDT_RESOURCE_L3:
+ /*
+ * No SNC for mmio based L3 occupancy, so there is no need
+ * to convert logical RMID to a physical RMID via
+ * logical_rmid_to_physical_rmid().
+ */
+ if (erdt_enabled() && eventid == QOS_L3_OCCUP_EVENT_ID)
+ return erdt_mon_read(hdr, eventid, rmid, val);
return arch_l3_read_event(hdr, rmid, eventid, val, r);
case RDT_RESOURCE_PERF_PKG:
return intel_aet_read_event(hdr->id, rmid, arch_priv, val);
--
2.25.1
prev parent reply other threads:[~2026-05-27 9:37 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-27 9:25 [RFC PATCH 0/6] x86/resctrl: Introduce MMIO-based CMT access for Enhanced RDT Chen Yu
2026-05-27 9:26 ` [RFC PATCH 1/6] x86/resctrl: Parse ACPI ERDT table and map RMDD domains by L3 cache ID Chen Yu
2026-05-28 20:21 ` Luck, Tony
2026-05-29 2:16 ` Chen, Yu C
2026-05-27 9:27 ` [RFC PATCH 2/6] x86/resctrl: Parse ACPI CMRC table Chen Yu
2026-05-27 9:27 ` [RFC PATCH 3/6] x86/resctrl: Rename prev_msr to prev_mon_val Chen Yu
2026-05-27 9:27 ` [RFC PATCH 4/6] x86/resctrl: Refactor the monitor read function Chen Yu
2026-05-27 9:28 ` [RFC PATCH 5/6] fs/resctrl: Do not invoke smp_processor_id() in preemptible context Chen Yu
2026-05-27 9:28 ` Chen Yu [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7c717b9100d0fd408ce1bfa754b7783b3dbadbb6.1779872016.git.yu.c.chen@intel.com \
--to=yu.c.chen@intel.com \
--cc=Dave.Martin@arm.com \
--cc=anil.s.keshavamurthy@intel.com \
--cc=babu.moger@amd.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=fenghuay@nvidia.com \
--cc=hpa@zytor.com \
--cc=james.morse@arm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=reinette.chatre@intel.com \
--cc=tglx@kernel.org \
--cc=tony.luck@intel.com \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®