From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.10]) (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 3971B47B422 for ; Thu, 4 Jun 2026 16:21:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.10 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780590111; cv=none; b=j5VquQ9Ii9aK/ygJfiSl1pt4NGFqU5XC+QT/Re+8s2RTa0yYjK9KAjabr2AZbccpwpo67Td9YKGDTgqhs2leT4/GvN/yrypzZBk0f7PNiFFWC6Egmwx4N+eDzw9LyY7L/gll6RFO+jjsVLHRsezA8cYQWINPNb0aLnUYWZ1SNoI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780590111; c=relaxed/simple; bh=PAj7gYAaY1D9mx160SaiHK4sNrCempQWCkULjhWvzB8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=b6hHBlEkn8iwoWy02pn3qryrVXYYJa3MMQ6+E/HoQIFaBWb/R9FzsGWq6npfI/0teTUEJBQOXfzWhXW1nGCRXhs7SHvuc3obwKP4dslK7W76yO8CsxMdwIowUneBOhImZ9bgbMyALjL/EB3swmWg2kn+ooPUlUztb8OiOd0c7kY= 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=gOKhMT1n; arc=none smtp.client-ip=198.175.65.10 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="gOKhMT1n" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1780590109; x=1812126109; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=PAj7gYAaY1D9mx160SaiHK4sNrCempQWCkULjhWvzB8=; b=gOKhMT1n1UJWTDxrppfwH0iF/oKc0eP00cYsFhN5uIfIkT40dAixDGG8 rWGVzeNpQ0ebBtrcHlMR2eRmIyP8wGC/JNV1vAg6MqKViWuLQ8TGTDjl+ spnGYDGBqH1IKLlNIrYxZA0uFpI+bmBVzdL0kB4PIuFEy4x7Q7N0BxgD+ f3MdtH+TdHKkRdTYmVtRwAVLcyZ6Yll/jgCr9DqtIKq5S3vCFwvwG3YA8 9xxhG4ywK4ST7ejW1VOxjHuYNu7rvNTCSE5Sm0EvMQMQOfa8lhHh9FsMs ihWhYZL5t/Ei4Pcuea6lX30GWNnu0FcLPO5RwQZgLtOJ+tgLuCffSVlW1 w==; X-CSE-ConnectionGUID: Qfg+DNJgSxOTE+l+zZFOaA== X-CSE-MsgGUID: 80bs7oJrQDCKeamDLlGwMA== X-IronPort-AV: E=McAfee;i="6800,10657,11807"; a="98839014" X-IronPort-AV: E=Sophos;i="6.24,187,1774335600"; d="scan'208";a="98839014" Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by orvoesa102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Jun 2026 09:21:48 -0700 X-CSE-ConnectionGUID: UTBsEAC8R4WTUFN1OGij6g== X-CSE-MsgGUID: cwbGKaQtTK6enUNACFwiFA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.24,187,1774335600"; d="scan'208";a="268508758" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by fmviesa001.fm.intel.com with ESMTP; 04 Jun 2026 09:21:46 -0700 From: Chen Yu To: tony.luck@intel.com, reinette.chatre@intel.com Cc: x86@kernel.org, linux-kernel@vger.kernel.org, bp@alien8.de, tglx@kernel.org, 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 v2 6/6] x86/resctrl: Add support for L3 occupancy monitoring via RMID MMIO read Date: Fri, 5 Jun 2026 00:11:57 +0800 Message-Id: <3832db18cd4ba58d9935a1f50ad963fc7fca5308.1780587063.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 88966aa5e050..2dda8011c2ce 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 d1eca4594f09..905d7fb53bd2 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