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 96E0E343899 for ; Sat, 13 Jun 2026 08:07:36 +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=1781338058; cv=none; b=rNCG9TAwdei7Oj0+JjrZ+xPAn7mgPLX6UELTZe5G0SakN7MXicXClyZAqXm9MNGO8YGzi47xj2JDIpbRtE+bXmngOOUcFnJZ+A/xqDDYhJLgrAgg6AurYOFFAfNONqnVGpXPAZmBsLy70sumlK4l/jzlHBzQJdXZRjRfOMiJcOM= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781338058; c=relaxed/simple; bh=EWAnM403XdOzxG2YfWHYjYA85qfwTj7cQ8eNUuDKE+A=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Th9r/uRkVAqkl12OojUHFL6+JIntN22DfltXfMK/kVnyFkzPA6nvfFZePhlo3+YJgkOZMP5Q+nSEdOCCcTGZMZSNGWcWnh0E5EjrtkWKmObjSnJEVl03cVGm5MuL2zcKrkzipLq7D4B71deAghGHKyrdz2kJ74n+C8uFYR0pd7Q= 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=fxmQgAD8; 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="fxmQgAD8" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1781338056; x=1812874056; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=EWAnM403XdOzxG2YfWHYjYA85qfwTj7cQ8eNUuDKE+A=; b=fxmQgAD8etSIg2na6s9TNWVlpZZ8f3sOxB9r1oF3zkTXar7/jpERTSW2 131sb58WVdVmD5tdxaiJL/vBY5+HWgAV6SxxCkEp0ETt6I71QGIETq840 4sa54RllxqMQsm2ZHSd4AIFECnOPdiaV4C5fsOGNEuTebNqeAX6xBbefs r1LW4l/LYrPMmBVmPMfANUS8p99aPcTWhColEqNxO2oyv0OSN2kPNlO/L rfTWKbUI82YCqSwrCEtvxZjFt2sYbkXFGDFpJ9rtrqh8UCcRhKUgjKWhH eAJAr6/uII8hDMh7n0qybscdbg572NPeJr6dEq2xPZ2vvMMo9c08N6FBx Q==; X-CSE-ConnectionGUID: JhLRo/AgTQqheM+Ie/IGZg== X-CSE-MsgGUID: VCAl6A03REC06+TabICnIQ== X-IronPort-AV: E=McAfee;i="6800,10657,11815"; a="99739091" X-IronPort-AV: E=Sophos;i="6.24,202,1774335600"; d="scan'208";a="99739091" Received: from fmviesa003.fm.intel.com ([10.60.135.143]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Jun 2026 01:07:36 -0700 X-CSE-ConnectionGUID: yJKk0bZ+Q3SwjwkZT7e1qw== X-CSE-MsgGUID: 43fJPNZGSfGajqvDA78ZeQ== X-ExtLoop1: 1 Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by fmviesa003.fm.intel.com with ESMTP; 13 Jun 2026 01:07:32 -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, bp@alien8.de, mingo@redhat.com, dave.hansen@linux.intel.com, hpa@zytor.com, dave.martin@arm.com, james.morse@arm.com, fenghuay@nvidia.com, babu.moger@amd.com, anil.keshavamurthy@broadcom.com Subject: [PATCH v4 6/6] x86/resctrl: Add support for L3 occupancy monitoring via RMID MMIO read Date: Sat, 13 Jun 2026 15:57:44 +0800 Message-Id: <21beef1acbba4bc7bbc6e54dc11868116638d5b5.1781332698.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 Reviewed-by: Thomas Gleixner Tested-by: Hongyu Ning Signed-off-by: Chen Yu --- v3->v4: Add Thomas and Hongyu's tags. --- arch/x86/include/asm/resctrl.h | 2 + arch/x86/kernel/cpu/resctrl/core.c | 2 +- arch/x86/kernel/cpu/resctrl/erdt.c | 89 +++++++++++++++++++++++++++ arch/x86/kernel/cpu/resctrl/monitor.c | 7 +++ 4 files changed, 99 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 90730f0851fa..fe812f7190fc 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 a1d5de82d5c9..2a1f638285b2 100644 --- a/arch/x86/kernel/cpu/resctrl/erdt.c +++ b/arch/x86/kernel/cpu/resctrl/erdt.c @@ -35,6 +35,7 @@ static DEFINE_XARRAY(erdt_domain_xa); #define ERDT_VALID_VERSION 1 #define CMRC_VALID_INDEX_FUNC_VERSION 1 +#define UNAVAILABLE_COUNTER BIT_ULL(63) #define RMDD_FLAG_CPU_DOMAIN BIT(0) static u32 valid_subtbl_mask; @@ -44,6 +45,94 @@ bool erdt_enabled(void) return erdt_enabled_flag; } +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 + * @val: Output pointer to store the scaled occupancy count + * + * 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 success, 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 9209927f88a2..1491f96b57c3 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