From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 120B07478 for ; Wed, 27 May 2026 09:37:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.8 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779874643; cv=none; b=AtARDBkole1chVn5vjifuIyQXWT/teCJ8iNRHMCkkJfQsAD4gZdTtZ65KtqIEFUNh0M5YsIjOMAG1J5zgS/6wzZioph8OaiYeeww2A89LgrkrpIytHJit59lJ4Jm2HWrwbjlP51iQq9D+uXYbmlJoKvbLD9XfmlBOC7YgW5+RLA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779874643; c=relaxed/simple; bh=HKvm7+7/JzVWabTelf2nuvc2ud/rrpcShZgykbl/eyU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=I7pQM5XzNnvvXlqCxG/WSCPCObUPb/k8TV95FilWhpZw6gu+OPmF4X5iUhVwyNei4dA/+TQi+Vk90QZSEuhpxPFhYFxrT2uFxJ57V6r9AfL7Yjnoi6fT1UCFZw/pp+KsTOlAXeBVTk0g/Y8uaNPGo0nl+K7EZL3V0pE0lGO3bX0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=bWU8ehg0; arc=none smtp.client-ip=192.198.163.8 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="bWU8ehg0" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779874642; x=1811410642; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=HKvm7+7/JzVWabTelf2nuvc2ud/rrpcShZgykbl/eyU=; b=bWU8ehg07tw6GRedJoYs1jFnhchkSsNtdBqfJIAEBJhpm3LikTstvggW kipt3DJl/u0NpS6zgMKY8Z2ZRcvZLfPM9xVmWhLS5YX9SN00nwmFLsRwn 2yYc6VZW2B46EswI8/4vcKX0ecio8aPnk+cU2A8sQMGIh4N8UoZiVU6WU EiyYwCh9SJCk0Jkk7uGm+Ut/uZ9HtgdFrqXUeSSzjsyRpyIrdVPvFIwB0 SOXXlumXTZ+ofTuyxyHVpYRoUcJAzWWCIBNvFG2UeFehIVIk7grLjz9O8 BJIvh++tCwKKVsPkkAPxnoG8gbI1+isruflCjpA67jLQoMzXj2DjvNnuT A==; X-CSE-ConnectionGUID: hH13DlvwRpKhS4uN2ntNxQ== X-CSE-MsgGUID: ouJTebpnT86mlBpbRC+mJg== X-IronPort-AV: E=McAfee;i="6800,10657,11798"; a="98275122" X-IronPort-AV: E=Sophos;i="6.24,171,1774335600"; d="scan'208";a="98275122" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 May 2026 02:37:19 -0700 X-CSE-ConnectionGUID: YxP1pq/NRVWpKLKd4m6iFQ== X-CSE-MsgGUID: inmSMWHNT+WwlXE+WM0eiw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.24,171,1774335600"; d="scan'208";a="239582187" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by fmviesa008.fm.intel.com with ESMTP; 27 May 2026 02:37:15 -0700 From: Chen Yu 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 , Chen Yu 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 Message-Id: <7c717b9100d0fd408ce1bfa754b7783b3dbadbb6.1779872016.git.yu.c.chen@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 Co-developed-by: Anil S Keshavamurthy Signed-off-by: Anil S Keshavamurthy Signed-off-by: Chen Yu --- 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