From nobody Fri Sep 25 01:18:32 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (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 6423C238C1A for ; Fri, 18 Sep 2026 04:58:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789707540; cv=none; b=jszXmXWt7p+NZHy1v0AWAwgNa0Zx6VqwSGi6FLWX8L1jKap7vrPytK+gACLFyuy8k3UmzOZh8v7qmkM+w9JVod9lyLHxiHeGXU1juLvbMDiYm0AzmGYDF/OkVSAv3trFf3LP76jXlPdolS4c6lKp9/OATZLs26Imiss5LWyw5XY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789707540; c=relaxed/simple; bh=6aldtN4ey7HhVuJqveGfwVpcOqrd+UOagCBtbDnPWO8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=T7XfwqbTmqpc+4icjAo637CVV9TFXZqrkfApCHMtW3BEKJbEi3w9guMV5FnxbD6j0IgudGZCVcH7H41mphS0JKGagRFqOvoc53g0Zh1KhlrQsD7E6EdxcR8t19ZipgvlmRMo0oo5SXGajbzIIz4nqiLQbjB1Rv0XCC3Yg9+/4Gw= 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=i4xnBcgD; arc=none smtp.client-ip=192.198.163.13 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="i4xnBcgD" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789707539; x=1821243539; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=6aldtN4ey7HhVuJqveGfwVpcOqrd+UOagCBtbDnPWO8=; b=i4xnBcgDqz1MLcBrHa7PGeFAUSQSoiqW3eB6Hsm4NARDJp/MM3lp7tRR YhjRQMZlbU7CJSlTb266JL9p20kA0AH5Nt/Cav3PTqmBNI624BaYXeJY8 CKvuyxFdpr76F1RhFHL02zFqcL9048/xRCKPTYrhbAflvkndNvgmHP8k+ LbHXGBXr8mk4j5aMMcNNiPgI38pTrJKW9bfhdZmtCJOQnZOdn25qvSdQh mzklRX7ppr9HMQs6em2424Nqtuj1B+QZ13subZ/sd58OzcEMFF+wzQN8W UxixvmY8iHqhcppoKfAfbgNxs6HFi8PKVJuJN0/aUcaIcXr48I3mCSn77 w==; X-CSE-ConnectionGUID: X+ON9zSwSp6Ly1eOPxpH2Q== X-CSE-MsgGUID: wj2TlKq2QYiJQyUZ+NV3Sg== X-IronPort-AV: E=McAfee;i="6800,10657,11905"; a="92699395" X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="92699395" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2026 21:58:58 -0700 X-CSE-ConnectionGUID: lMZxbsfpTKuVvG7aDTPPkA== X-CSE-MsgGUID: gtB1PkZ3QsKyzPVnzx4GXg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="279438447" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by fmviesa005.fm.intel.com with ESMTP; 17 Sep 2026 21:58:52 -0700 From: Chen Yu To: tony.luck@intel.com, reinette.chatre@intel.com Cc: tglx@kernel.org, bp@alien8.de, mingo@redhat.com, dave.hansen@linux.intel.com, hpa@zytor.com, fenghuay@nvidia.com, babu.moger@amd.com, hongyu.ning@intel.com, chen.yu@linux.dev, x86@kernel.org, linux-kernel@vger.kernel.org, Chen Yu , Hongyu Ning Subject: [PATCH v8 1/9] x86/topology: Export topo_lookup_cpuid() for resctrl use Date: Fri, 18 Sep 2026 12:48:21 +0800 Message-Id: <78066ab48e7c917417b0ac6c94eed5015f445180.1789705667.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: quoted-printable Content-Type: text/plain; charset="utf-8" Enhanced RDT (ERDT) enumerates its monitoring and control resources through ACPI tables that identify each CPU by its x2APIC ID. To associate this firmware-provided data with the kernel's per-CPU structures, ERDT must translate those x2APIC IDs into logical CPU numbers. topo_lookup_cpuid() already performs this translation, but it is static to topology.c and therefore not reachable from resctrl. Export topo_lookup_cpuid() and add its declaration to asm/apic.h that alrea= dy exposes the inverse mapping via cpuid_to_apicid[], so that ERDT can resolve x2APIC IDs from ACPI tables to logical CPU numbers. No functional change intended. Signed-off-by: Chen Yu Tested-by: Hongyu Ning Reviewed-by: Reinette Chatre --- arch/x86/include/asm/apic.h | 1 + arch/x86/kernel/cpu/topology.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 9cd493d467d4..bb84651b14bd 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -54,6 +54,7 @@ static inline void x86_32_probe_apic(void) { } #endif =20 extern u32 cpuid_to_apicid[]; +int topo_lookup_cpuid(u32 apic_id); =20 #define CPU_ACPIID_INVALID U32_MAX =20 diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c index 4913b64ec592..bcee70fb9277 100644 --- a/arch/x86/kernel/cpu/topology.c +++ b/arch/x86/kernel/cpu/topology.c @@ -92,7 +92,7 @@ static inline u32 topo_apicid(u32 apicid, enum x86_topolo= gy_domains dom) return apicid & (UINT_MAX << x86_topo_system.dom_shifts[dom - 1]); } =20 -static int topo_lookup_cpuid(u32 apic_id) +int topo_lookup_cpuid(u32 apic_id) { int i; =20 --=20 2.25.1 From nobody Fri Sep 25 01:18:32 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.6]) (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 673673F105D for ; Fri, 18 Sep 2026 04:59:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.6 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789707588; cv=none; b=UDe8gdEzC4UtfNnVNTIsL4w9SDnbFdSUSjPAvrKOtauTPmQHy/Iwtgl88tZGqJVC0YwFdjBdowMS4spEVBfqTfBCMiTz6R9Vu/F6uhb7hj7JW1NIMYcGzcpnCnZQOH6mhspQ9zluIIpoOcjNTyuHibP18/SVlzO5rP2w28IrPnw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789707588; c=relaxed/simple; bh=BcTR5EDFiVeGoYMwZ5vWzexnMIV8T2dcLFpKkfv+Nic=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Xjeho1wF1IzvWu2imrRxuwPe83NiAJweWFC4cuMqdo7isKYaJymdvE/4QI/hDgPRZ9sJhJXjEuFZYKrql0MNwFco8q1HmHSd5PGplVxBE4i7nn9oGCLz7jSpnfirgsksRecxkqdWXNgYLJqYAit2fSCC1EoOVGLtKjKB7EJxoOo= 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=JbIUrMuB; arc=none smtp.client-ip=192.198.163.6 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="JbIUrMuB" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789707588; x=1821243588; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=BcTR5EDFiVeGoYMwZ5vWzexnMIV8T2dcLFpKkfv+Nic=; b=JbIUrMuBfQqiVtUTkTq1o82ZzDr387wYWZDhcslqLXFbLE4TPnMIYrb7 hkVUshlNnpM/eRRcEYVsao9lVhK856B8lwtkPzYIygQIRbcaOECZXEMYD aHMHmGcgqpVeFhWgHifeR2/JLMQg48KuUiErQ+m8Hfs7mECGR3Bxk8iFk B6M24CD5y/ke0UL+Ss5PREioWdqDJHx8zj9A8sojqWIDZLmzM0NIkms0c 6Iu1HQmmnEks9FpERhee/jl+jr/a5sFAZDxqag7cEy9j/ff0TOEdQsXFY /laEtA3r9wRofmbxjLy1Td1SEX0NJbq9Ugjf6j6BYZiVtpC0ZL+4BLUqL w==; X-CSE-ConnectionGUID: I8qdJh3NSAuk+a7v5PTWog== X-CSE-MsgGUID: pes0bjntTjWPyH9ZR2c8Fg== X-IronPort-AV: E=McAfee;i="6800,10657,11905"; a="704598" X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="704598" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by fmvoesa116.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2026 21:59:47 -0700 X-CSE-ConnectionGUID: yI6mFI4lQJSk2X3UOwrigw== X-CSE-MsgGUID: ZodesKnUTJmNQ032tHVVbA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="271541891" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by fmviesa008.fm.intel.com with ESMTP; 17 Sep 2026 21:59:44 -0700 From: Chen Yu To: tony.luck@intel.com, reinette.chatre@intel.com Cc: tglx@kernel.org, bp@alien8.de, mingo@redhat.com, dave.hansen@linux.intel.com, hpa@zytor.com, fenghuay@nvidia.com, babu.moger@amd.com, hongyu.ning@intel.com, chen.yu@linux.dev, x86@kernel.org, linux-kernel@vger.kernel.org, Chen Yu Subject: [PATCH v8 2/9] x86/resctrl: Require 64-bit x86 for resctrl support Date: Fri, 18 Sep 2026 12:48:38 +0800 Message-Id: <711a7976e0a33cd6fa2872ff10898b66d34fcd70.1789705667.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: quoted-printable Content-Type: text/plain; charset="utf-8" From: 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 line 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 Signed-off-by: Chen Yu Link: https://lore.kernel.org/all/c6ab0c24-8931-4f0d-9be6-23498ab4c38b@inte= l.com/ # [1] --- 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 =20 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 =20 config X86_CPU_RESCTRL_INTEL_AET bool "Intel Application Energy Telemetry" - depends on X86_64 && X86_CPU_RESCTRL && CPU_SUP_INTEL && INTEL_PMT_TELEME= TRY=3Dy && INTEL_TPMI=3Dy + depends on X86_CPU_RESCTRL && CPU_SUP_INTEL && INTEL_PMT_TELEMETRY=3Dy &&= INTEL_TPMI=3Dy help Enable per-RMID telemetry events in resctrl. =20 --=20 2.25.1 From nobody Fri Sep 25 01:18:32 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.14]) (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 E30E0364EB2 for ; Fri, 18 Sep 2026 05:00:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789707625; cv=none; b=cX0TgkbWvr6J6OCRTuYRicUfAw9DiakGP9tY9lUWK+o9XsEiOtXiJ3QN11vl5+e20757sK3fH9lyY/ni/8Vp4QWv4pqCJfswCh3GiWijOTdW6MwXwb9d2drrRAjWTd716wXtf76gOlPC2Vt6cDkWt0cweeBnFb8AfOk+b/c5nwc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789707625; c=relaxed/simple; bh=wCQQ9sK8MfeSQANhBg4GB6Z1MDBl+lE8ukLAzYLr7xw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Cut67sEExizarfWJRe0yEcilU7Md1Lr5fSYTUU1Lcfp3nZ0ZIpKSrJFBHomfJSLjcfFF9EheH+cM4ruW+LoTN10gdfTB16F1cA79Dk5vqFgsJ+n/KaJ/Wx/C9f110koBCV+UpcecY+fwAT5GjH0uZFIPQ1K9M9iNXdbUkHD7mUA= 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=XxNBF9r7; arc=none smtp.client-ip=192.198.163.14 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="XxNBF9r7" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789707624; x=1821243624; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=wCQQ9sK8MfeSQANhBg4GB6Z1MDBl+lE8ukLAzYLr7xw=; b=XxNBF9r757axa+onLPiVXVbEPPXVkk/klps8WBdqeT8l0nJbZV/OtwdM L86WTOqtTFMDlsOhCDY2cztvOR0TJW0aY84xNFM6PAP9C0inJjXIsKXR0 asK08zEbhkFMCpFSOmmbbwRaULNpc7VOYa6069B7D0VNUEW4fbuSDn3IA KfnhcN6LiL6p1GmU+SdVJl+vMfhUKbWhMkqP2Jve+GMBR+Wqb7myjfrOB j2pqgzBq3L4rDLAynrMpOd6UOsUOYYEA9kqVw8wu3JRPvGcbjic6P3PTS 6ZwSuACGI3hfRTa/0HPfOO8Iq6mNou+Ng0QfPveNkSzIZ6K9sVOoi02ZZ Q==; X-CSE-ConnectionGUID: 3uTEmzdCRka5JCcBJjlCoA== X-CSE-MsgGUID: /MOLE0q8ShS8ZgvhZDjFQQ== X-IronPort-AV: E=McAfee;i="6800,10657,11905"; a="90206749" X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="90206749" Received: from fmviesa012.fm.intel.com ([10.60.135.152]) by fmvoesa108.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2026 22:00:23 -0700 X-CSE-ConnectionGUID: XiiQNUv5RFuFFsrIzBWuTQ== X-CSE-MsgGUID: ivTogSmpRAOh6aDxrQOtJA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="2395279" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by fmviesa012.fm.intel.com with ESMTP; 17 Sep 2026 22:00:17 -0700 From: Chen Yu To: tony.luck@intel.com, reinette.chatre@intel.com Cc: tglx@kernel.org, bp@alien8.de, mingo@redhat.com, dave.hansen@linux.intel.com, hpa@zytor.com, fenghuay@nvidia.com, babu.moger@amd.com, hongyu.ning@intel.com, chen.yu@linux.dev, x86@kernel.org, linux-kernel@vger.kernel.org, Chen Yu , Hongyu Ning Subject: [PATCH v8 3/9] x86/resctrl: Parse ACPI ERDT table and save CACD cpumask for RMDD domains Date: Fri, 18 Sep 2026 12:49:50 +0800 Message-Id: <16e1ac77eb48c5433f16c3a7cefcd4217a19007b.1789705667.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: quoted-printable Content-Type: text/plain; charset="utf-8" There is one Enhanced RDT (ERDT) ACPI table per platform. Each Resource Management Domain Description (RMDD) sub-table within it describes one reso= urce management domain (RMD), also known as an L3 domain, and carries MMIO base information for monitoring support. The CPU agents within the scope of an R= MDD are enumerated by their x2APIC IDs in a nested CPU Agent Collection Descrip= tion (CACD) sub-table. Parse the RMDD sub-tables within the ERDT ACPI table and their nested CACD entries to construct per-domain CPU masks. For each RMDD, parse the associated CACD, map its x2APIC IDs to logical CPU= s, and save the resulting CPU mask. Associate every ERDT domain with the CPUs = that belong to it to prepare for attaching ERDT data to resctrl monitoring domai= ns. Based on original work from Anil S Keshavamurthy. Suggested-by: Tony Luck Suggested-by: Reinette Chatre Signed-off-by: Chen Yu Tested-by: Hongyu Ning --- arch/x86/kernel/cpu/resctrl/Makefile | 1 + arch/x86/kernel/cpu/resctrl/core.c | 16 +- arch/x86/kernel/cpu/resctrl/erdt.c | 265 +++++++++++++++++++++++++ arch/x86/kernel/cpu/resctrl/internal.h | 29 +++ 4 files changed, 309 insertions(+), 2 deletions(-) create mode 100644 arch/x86/kernel/cpu/resctrl/erdt.c diff --git a/arch/x86/kernel/cpu/resctrl/Makefile b/arch/x86/kernel/cpu/res= ctrl/Makefile index 273ddfa30836..2216ee084832 100644 --- a/arch/x86/kernel/cpu/resctrl/Makefile +++ b/arch/x86/kernel/cpu/resctrl/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_X86_CPU_RESCTRL) +=3D core.o rdtgroup.o monitor.o obj-$(CONFIG_X86_CPU_RESCTRL) +=3D ctrlmondata.o obj-$(CONFIG_X86_CPU_RESCTRL_INTEL_AET) +=3D intel_aet.o +obj-$(CONFIG_X86_CPU_RESCTRL) +=3D erdt.o obj-$(CONFIG_RESCTRL_FS_PSEUDO_LOCK) +=3D pseudo_lock.o =20 # To allow define_trace.h's recursive include: diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resct= rl/core.c index 55214d6fdc49..54cfdf12dfbb 100644 --- a/arch/x86/kernel/cpu/resctrl/core.c +++ b/arch/x86/kernel/cpu/resctrl/core.c @@ -1016,10 +1016,17 @@ static __init void check_quirks(void) =20 static __init bool get_rdt_resources(void) { + bool succeed; + + erdt_init(); rdt_alloc_capable =3D get_rdt_alloc_resources(); rdt_mon_capable =3D get_rdt_mon_resources(); =20 - return (rdt_mon_capable || rdt_alloc_capable); + succeed =3D (rdt_mon_capable || rdt_alloc_capable); + if (!succeed) + erdt_exit(); + + return succeed; } =20 static __init void rdt_init_res_defs_intel(void) @@ -1141,12 +1148,15 @@ static int __init resctrl_arch_late_init(void) "x86/resctrl/cat:online:", resctrl_arch_online_cpu, resctrl_arch_offline_cpu); - if (state < 0) + if (state < 0) { + erdt_exit(); return state; + } =20 ret =3D resctrl_init(); if (ret) { cpuhp_remove_state(state); + erdt_exit(); return ret; } rdt_online =3D state; @@ -1169,6 +1179,8 @@ static void __exit resctrl_arch_exit(void) cpuhp_remove_state(rdt_online); =20 resctrl_exit(); + + erdt_exit(); } =20 __exitcall(resctrl_arch_exit); diff --git a/arch/x86/kernel/cpu/resctrl/erdt.c b/arch/x86/kernel/cpu/resct= rl/erdt.c new file mode 100644 index 000000000000..0dfe5eda166c --- /dev/null +++ b/arch/x86/kernel/cpu/resctrl/erdt.c @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Enhanced Resource Director Technology (ERDT) + * + * Copyright (C) 2026 Intel Corporation + * + */ + +#define pr_fmt(fmt) "resctrl: " fmt + +#include +#include +#include +#include + +#include + +#include "internal.h" + +static LIST_HEAD(domain_info_list); + +/* True when the ERDT ACPI table describes at least one domain with at lea= st one CPU. */ +static bool erdt_enabled; + +#define ERDT_VALID_VERSION 1 +#define RMDD_FLAG_CPU_L3_DOMAIN BIT(0) + +/* Bitmask of valid sub-tables found in the first RMDD, used to ensure all= RMDDs match. */ +static u32 valid_subtbl_mask; + +/* Domain ID of the first RMDD that established @valid_subtbl_mask, for di= agnostics. */ +static u16 first_rmdd_domain_id; + +/* + * The minimal max-rmid of different domains. Using minimal is to avoid th= e domain with + * small rmid accessing an invalid rmid. + */ +static unsigned int erdt_max_rmid; + +unsigned int erdt_get_max_rmid(void) +{ + return erdt_max_rmid; +} + +static void __iomem *erdt_ioremap(resource_size_t base, u32 num_pages, con= st char *desc) +{ + void __iomem *addr; + unsigned long size; + + if (check_mul_overflow(num_pages, SZ_4K, &size)) + return NULL; + + addr =3D ioremap(base, size); + if (!addr) + pr_warn(FW_BUG "ERDT: Failed to map %s at phys addr %pa (size: %u pages)= \n", + desc, &base, num_pages); + + return addr; +} + +static void erdt_iounmap_domain(struct erdt_domain_info *domain) +{ + for (int i =3D 0; i < ERDT_MMIO_NUM_TYPES; i++) { + if (domain->base[i]) { + iounmap(domain->base[i]); + domain->base[i] =3D NULL; + } + } +} + +static void cleanup_one_domain(struct erdt_domain_info *d) +{ + erdt_iounmap_domain(d); + kfree(d); +} + +/* + * Save CACD information for this RMDD: + * convert the X2APIC to CPU and save them in a mask. + */ +static __init int cacd_init(struct acpi_subtbl_hdr_16 *subtbl, + struct erdt_domain_info *domain_info) +{ + struct acpi_erdt_cacd *cacd =3D (struct acpi_erdt_cacd *)subtbl; + unsigned int num_ids; + int cpu; + + if (cacd->header.length < struct_size(cacd, X2APICIDS, 1)) { + pr_warn(FW_BUG "Invalid x2apicid CACD table\n"); + return -EIO; + } + + num_ids =3D (cacd->header.length - sizeof(*cacd)) / sizeof(cacd->X2APICID= S[0]); + + for (unsigned int i =3D 0; i < num_ids; i++) { + cpu =3D topo_lookup_cpuid(cacd->X2APICIDS[i]); + if (cpu < 0) { + pr_warn(FW_BUG "Unknown x2apicid 0x%x\n", cacd->X2APICIDS[i]); + return -EIO; + } + + cpumask_set_cpu(cpu, &domain_info->cpu_mask); + } + + return 0; +} + +static inline struct acpi_subtbl_hdr_16 *rmdd_subtbl(struct acpi_erdt_rmdd= *rmdd) +{ + return (void *)rmdd + sizeof(*rmdd); +} + +static inline struct acpi_subtbl_hdr_16 *next_subtbl(struct acpi_subtbl_hd= r_16 *subtbl) +{ + return (void *)subtbl + subtbl->length; +} + +static inline bool subtbl_valid(void *end, struct acpi_subtbl_hdr_16 *subt= bl) +{ + /* Ensure the header is within bounds before dereferencing it. */ + if ((void *)subtbl + sizeof(*subtbl) > end) + return false; + + /* A sub-table must be at least as large as its header. */ + if (subtbl->length < sizeof(*subtbl)) + return false; + + /* The entire sub-table (including body) must fit within the parent. */ + if ((void *)subtbl + subtbl->length > end) + return false; + + return true; +} + +static __init bool parse_rmdd_table(struct acpi_subtbl_hdr_16 *rmdd_hdr) +{ + struct acpi_erdt_rmdd *rmdd =3D (struct acpi_erdt_rmdd *)rmdd_hdr; + struct erdt_domain_info *domain_info; + struct acpi_subtbl_hdr_16 *subtbl; + u32 subtbl_mask =3D 0; + + if (rmdd->header.length < sizeof(*rmdd)) { + pr_warn(FW_BUG "Invalid RMDD length %u bytes\n", rmdd->header.length); + return false; + } + + /* Quietly ignore non-CPU-based L3 domains */ + if (!(rmdd->flags & RMDD_FLAG_CPU_L3_DOMAIN)) + return true; + + domain_info =3D kzalloc_obj(*domain_info, GFP_KERNEL); + if (!domain_info) + return false; + + domain_info->dom_id =3D -1; + + domain_info->base[ERDT_MMIO_RMDD_CREG] =3D + erdt_ioremap(rmdd->creg_base, rmdd->creg_size, "RMDD ctrl base"); + if (!domain_info->base[ERDT_MMIO_RMDD_CREG]) + goto cleanup; + + for (subtbl =3D rmdd_subtbl(rmdd); + subtbl_valid((void *)rmdd + rmdd->header.length, subtbl); + subtbl =3D next_subtbl(subtbl)) { + switch (subtbl->type) { + /* An RMDD table has one or more CACD sub-table(s) */ + case ACPI_ERDT_TYPE_CACD: + if (cacd_init(subtbl, domain_info)) + goto cleanup; + + subtbl_mask |=3D BIT(ACPI_ERDT_TYPE_CACD); + break; + default: + break; + } + } + + if (!subtbl_mask) + goto cleanup; + + /* + * Require all RMDDs to support same set of sub-tables + */ + if (!valid_subtbl_mask) { + valid_subtbl_mask =3D subtbl_mask; + first_rmdd_domain_id =3D rmdd->domain_id; + } else if (subtbl_mask !=3D valid_subtbl_mask) { + pr_warn(FW_BUG "RMDD %u sub-table set does not match the first RMDD %u\n= ", + rmdd->domain_id, first_rmdd_domain_id); + goto cleanup; + } + + if (!rmdd->max_rmid) { + pr_warn(FW_BUG "Unreasonable RMDD max_rmid %u\n", rmdd->max_rmid); + goto cleanup; + } + + if (!erdt_max_rmid) + erdt_max_rmid =3D rmdd->max_rmid; + else + erdt_max_rmid =3D min(erdt_max_rmid, rmdd->max_rmid); + + list_add(&domain_info->entry, &domain_info_list); + + return true; + +cleanup: + cleanup_one_domain(domain_info); + return false; +} + +void erdt_exit(void) +{ + struct erdt_domain_info *d, *tmp; + + list_for_each_entry_safe(d, tmp, &domain_info_list, entry) { + list_del(&d->entry); + cleanup_one_domain(d); + } + erdt_enabled =3D false; + valid_subtbl_mask =3D 0; + first_rmdd_domain_id =3D 0; + erdt_max_rmid =3D 0; +} + +static __init int enumerate_erdt_table(struct acpi_table_header *table_hdr) +{ + struct acpi_table_erdt *erdt =3D (struct acpi_table_erdt *)table_hdr; + struct acpi_subtbl_hdr_16 *subtbl; + + if (erdt->header.revision !=3D ERDT_VALID_VERSION) { + pr_info("Unsupported ERDT table revision %u (expected %u)\n", + erdt->header.revision, ERDT_VALID_VERSION); + return -EINVAL; + } + + if (erdt->header.length < sizeof(*erdt)) { + pr_warn(FW_BUG "ERDT: Invalid table length %u bytes\n", erdt->header.len= gth); + return -EINVAL; + } + + for (subtbl =3D (void *)erdt + sizeof(*erdt); + subtbl_valid((void *)erdt + erdt->header.length, subtbl); + subtbl =3D next_subtbl(subtbl)) { + if (subtbl->type =3D=3D ACPI_ERDT_TYPE_RMDD && + !parse_rmdd_table(subtbl)) + goto cleanup; + } + + if (list_empty(&domain_info_list)) + goto cleanup; + + erdt_enabled =3D true; + + return 0; + +cleanup: + erdt_exit(); + return -EINVAL; +} + +int __init erdt_init(void) +{ + return acpi_table_parse(ACPI_SIG_ERDT, enumerate_erdt_table); +} diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/r= esctrl/internal.h index e3cfa0c10e92..156206088372 100644 --- a/arch/x86/kernel/cpu/resctrl/internal.h +++ b/arch/x86/kernel/cpu/resctrl/internal.h @@ -21,6 +21,31 @@ =20 #define RMID_VAL_UNAVAIL BIT_ULL(62) =20 +/* + * Index into erdt_domain_info::base[] for each MMIO region. + * @ERDT_MMIO_RMDD_CREG: RMDD control register base address + */ +enum erdt_mmio_type { + ERDT_MMIO_RMDD_CREG, + ERDT_MMIO_LAST =3D ERDT_MMIO_RMDD_CREG +}; + +#define ERDT_MMIO_NUM_TYPES (ERDT_MMIO_LAST + 1) + +/** + * struct erdt_domain_info - Per-domain ERDT information + * @base: Array of ioremapped MMIO region base addresses, indexed by ERDT_= MMIO_* + * @cpu_mask: CPUs belonging to this resource management domain + * @dom_id: L3 cache ID shared by all CPUs in this domain (-1 if unset) + * @entry: Links into the global domain_info_list + */ +struct erdt_domain_info { + void __iomem *base[ERDT_MMIO_NUM_TYPES]; + struct cpumask cpu_mask; + int dom_id; + struct list_head entry; +}; + /* * With the above fields in use 62 bits remain in MSR_IA32_QM_CTR for * data to be returned. The counter width is discovered from the hardware @@ -253,4 +278,8 @@ static inline void intel_aet_mon_domain_setup(int cpu, = int id, struct rdt_resour static inline bool intel_handle_aet_option(bool force_off, char *tok) { re= turn false; } #endif =20 +unsigned int erdt_get_max_rmid(void); +int erdt_init(void); +void erdt_exit(void); + #endif /* _ASM_X86_RESCTRL_INTERNAL_H */ --=20 2.25.1 From nobody Fri Sep 25 01:18:32 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.7]) (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 64D9934C98C for ; Fri, 18 Sep 2026 05:00:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789707638; cv=none; b=MIONimPkjbbMQ202BLvjsq9osGIgct7skLf0U1xEu2sKI+wXri3JuxEMGRcF3JvYkN1bXLsdeyhbCfS84C+PSNR5bY39HlA6bL9KB7Ik/VyCHWMbSW80mnFpDY7mKUnJYuPZNjJUeVa2XAwwuk6FJbgAt8jBjw7X1JJRwO0zh38= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789707638; c=relaxed/simple; bh=CJbNOXkL5i5iOuj4FQjb8Zr4pzFe7cKFZHXbVN0RM8E=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=CFxJ0L8nCiLvQbnji7PToU2V09L9VNyIndB+UdFvxhnRmayhrY44SiCBhBoxW2CXnHrfEDYqkavoepJ/UTSD9q2tBfDxvB/H1APsLsWJHhFaqpO3cHbvVINsB0aBQUYo572UxFmtPL2qZpjY+ZHobE91oTH41Zrr13AHNIyOp70= 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=UzYkECOJ; arc=none smtp.client-ip=192.198.163.7 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="UzYkECOJ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789707636; x=1821243636; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=CJbNOXkL5i5iOuj4FQjb8Zr4pzFe7cKFZHXbVN0RM8E=; b=UzYkECOJcDoRfKX7L1YnihO8lykYJTBynIqU2GKWqdsO5iZwsvbpLRLB xAfGoIkiODz6z2mgDhlLTQoG1D7vvKuYVTwxSRzMwUKvJMzUZEX0fcfiJ vRugfEqx0rZvGThL4egvgjRiTmoe+hgdF9s1OJ9mSzQ41Zs+yhcl5hjIZ IURBGU4aAPW95+XuPYvYPDnDZC1R38a6L0Dt7UVR/La+Aie31OWVkC5yL rKDJ44RKMOr6QppQtBAF3BJ6ju1ejwBmSS43qmsZEeMpw08zBW61OknqC e8Xq7i3NEXECImqjIk9A2FHdFoW0pZ94YeWgmIfBTnUJueqEABwXN+Omm Q==; X-CSE-ConnectionGUID: O3e9m6UDT6i9NHHeTQ4uwA== X-CSE-MsgGUID: 9odPqIwVRwmlurPA/ld4Dw== X-IronPort-AV: E=McAfee;i="6800,10657,11905"; a="115722576" X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="115722576" Received: from fmviesa012.fm.intel.com ([10.60.135.152]) by fmvoesa101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2026 22:00:33 -0700 X-CSE-ConnectionGUID: dGJ0nmibSGe2Aj5zIHiG4g== X-CSE-MsgGUID: vu5FiOpKQeOgdVSNEbFZ+Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="2395347" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by fmviesa012.fm.intel.com with ESMTP; 17 Sep 2026 22:00:30 -0700 From: Chen Yu To: tony.luck@intel.com, reinette.chatre@intel.com Cc: tglx@kernel.org, bp@alien8.de, mingo@redhat.com, dave.hansen@linux.intel.com, hpa@zytor.com, fenghuay@nvidia.com, babu.moger@amd.com, hongyu.ning@intel.com, chen.yu@linux.dev, x86@kernel.org, linux-kernel@vger.kernel.org, Chen Yu , Hongyu Ning Subject: [PATCH v8 4/9] x86/resctrl: Attach ACPI ERDT information to L3 mon domain on CPU online Date: Fri, 18 Sep 2026 12:50:03 +0800 Message-Id: <1299d05391a5095a151d6204a459d6ca0f431462.1789705667.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: quoted-printable Content-Type: text/plain; charset="utf-8" Reading LLC occupancy counters via MMIO requires the per-domain ERDT information, parsed from the ACPI ERDT table, to be reachable from the resc= trl L3 monitoring domain. Nothing links the two yet, so the monitoring code can= not locate the MMIO registers of a domain. ERDT and CPUID enumerate CPU-to-L3-domain membership independently: CPUID l= eaf 4 describes the L3 cache topology, while the firmware CACD sub-table lists the CPUs of each ERDT domain. Both views must agree on a CPU's L3 domain for th= at CPU to be monitored safely. When a CPU comes online, validate that firmware and CPUID agree on its L3 d= omain before adding it to any resctrl domain. Exclude the CPU from all resctrl do= mains on a mismatch because a topology inconsistency between ERDT and CPUID indic= ates a firmware defect that makes the CPU's domain placement unreliable for any resource. Otherwise attach the matching ERDT domain information to the L3 monitoring domain so that monitoring data can be read via ERDT and its sub-tables. Suggested-by: Reinette Chatre Signed-off-by: Chen Yu Tested-by: Hongyu Ning --- arch/x86/kernel/cpu/resctrl/core.c | 16 ++++ arch/x86/kernel/cpu/resctrl/erdt.c | 109 +++++++++++++++++++++++++ arch/x86/kernel/cpu/resctrl/internal.h | 5 ++ 3 files changed, 130 insertions(+) diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resct= rl/core.c index 54cfdf12dfbb..3514d73a8056 100644 --- a/arch/x86/kernel/cpu/resctrl/core.c +++ b/arch/x86/kernel/cpu/resctrl/core.c @@ -34,6 +34,9 @@ * the domain list must either take cpus_read_lock(), or rely on an RCU * read-side critical section, to avoid observing concurrent modification. * All writers take this mutex: + * + * This mutex also protects the ERDT domain_info_list, which is modified w= hen a + * CPU comes online. */ static DEFINE_MUTEX(domain_list_lock); =20 @@ -564,6 +567,8 @@ static void l3_mon_domain_setup(int cpu, int id, struct= rdt_resource *r, struct return; } list_add_tail_rcu(&d->hdr.list, add_pos); + + erdt_l3_mon_domain_setup(id, &d->hdr); } =20 static void domain_add_cpu_mon(int cpu, struct rdt_resource *r) @@ -742,6 +747,17 @@ static int resctrl_arch_online_cpu(unsigned int cpu) struct rdt_resource *r; =20 mutex_lock(&domain_list_lock); + /* + * A CPU whose ERDT and CPUID L3 domain views disagree is not added to + * any domain. resctrl_arch_offline_cpu() still tries to remove it when + * it goes offline and warns that no domain contains it. That warning is + * expected. + */ + if (!erdt_cpu_valid(cpu)) { + mutex_unlock(&domain_list_lock); + return 0; + } + for_each_capable_rdt_resource(r) domain_add_cpu(cpu, r); mutex_unlock(&domain_list_lock); diff --git a/arch/x86/kernel/cpu/resctrl/erdt.c b/arch/x86/kernel/cpu/resct= rl/erdt.c index 0dfe5eda166c..249ba547d7c8 100644 --- a/arch/x86/kernel/cpu/resctrl/erdt.c +++ b/arch/x86/kernel/cpu/resctrl/erdt.c @@ -209,6 +209,115 @@ static __init bool parse_rmdd_table(struct acpi_subtb= l_hdr_16 *rmdd_hdr) return false; } =20 +bool erdt_cpu_valid(int cpu) +{ + struct erdt_domain_info *d, *cpu_dom =3D NULL; + int dom_id; + + /* Without ERDT there is no firmware topology to disagree with. */ + if (!erdt_enabled) + return true; + + dom_id =3D get_cpu_cacheinfo_id(cpu, RESCTRL_L3_CACHE); + if (dom_id < 0) { + pr_warn(FW_BUG "Can't find L3 id for CPU:%d\n", cpu); + return false; + } + + /* + * Find the erdt_domain_info that contains this CPU, then bind that ERDT + * domain to this CPU's L3 id. A CPU whose L3 id does not match the bindi= ng + * of its ERDT domain cannot be covered by resctrl. + * + * For example, the CACD sub-tables report: + * domain0: CPU0, CPU2, domain1: CPU1, CPU3 + * while CPUID/cacheinfo reports the L3 cache is shared by: + * id0: CPU0, CPU1, id1: CPU2, CPU3 + * With the CPUs coming online in order, CPU0 binds domain0 to L3 id0 and + * CPU3 binds domain1 to L3 id1, so CPU1 and CPU2 are not covered by + * resctrl. + */ + list_for_each_entry(d, &domain_info_list, entry) { + if (cpumask_test_cpu(cpu, &d->cpu_mask)) { + cpu_dom =3D d; + break; + } + } + + if (!cpu_dom) { + pr_warn(FW_BUG "Cannot find the ERDT domain which has CPU%d\n", cpu); + return false; + } + + /* This ERDT domain is already bound to this CPU's L3 domain. */ + if (cpu_dom->dom_id =3D=3D dom_id) + return true; + + /* + * This ERDT domain is already bound to a different L3 domain. Rebinding = it + * would leave two L3 domains reading the counters of one ERDT domain, so + * skip this CPU instead: + * When CPU2 is brought online, domain0 is found. But then it found that + * domain0's ID is 0, which is not -1(new domain), so CPU2 is ineligible. + */ + if (cpu_dom->dom_id !=3D -1) { + pr_warn(FW_BUG "CPU%d's id=3D%d not equal to CACD domain(%*pbl) id=3D%d,= skip this CPU\n", + cpu, dom_id, cpumask_pr_args(&cpu_dom->cpu_mask), cpu_dom->dom_id); + + return false; + } + + /* + * A possible new binding. Check if another ERDT domain shares the same + * L3 id. If yes, this is a conflict and this CPU should not be considered + * by resctrl: + * When CPU1 is brought online, a new domain1 is found. But then it found= that + * domain0's ID is 0, which is the same as CPU1's dom_id, so CPU1 is inel= igible. + */ + list_for_each_entry(d, &domain_info_list, entry) { + if (d =3D=3D cpu_dom) + continue; + + if (d->dom_id =3D=3D dom_id) { + pr_warn(FW_BUG "CPU%d's id=3D%d is already used by CACD domain(%*pbl), = skip this CPU\n", + cpu, dom_id, cpumask_pr_args(&d->cpu_mask)); + + return false; + } + } + + /* Eligible new binding, assign the L3 id. */ + cpu_dom->dom_id =3D dom_id; + + return true; +} + +/* + * Associate ERDT table information with this domain. + */ +void erdt_l3_mon_domain_setup(int id, struct rdt_domain_hdr *hdr) +{ + struct rdt_hw_l3_mon_domain *hw_dom; + struct erdt_domain_info *d; + + if (!erdt_enabled) + return; + + hw_dom =3D resctrl_to_arch_mon_dom(container_of(hdr, struct rdt_l3_mon_do= main, hdr)); + + list_for_each_entry(d, &domain_info_list, entry) { + if (d->dom_id =3D=3D id) { + /* Assign the ERDT information to hw_dom */ + if (hw_dom->d_info) { + pr_warn(FW_BUG "Duplicated ERDT domains are mapped to an existing L3 d= omain\n"); + return; + } + hw_dom->d_info =3D d; + return; + } + } +} + void erdt_exit(void) { struct erdt_domain_info *d, *tmp; diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/r= esctrl/internal.h index 156206088372..2e8fb36ad804 100644 --- a/arch/x86/kernel/cpu/resctrl/internal.h +++ b/arch/x86/kernel/cpu/resctrl/internal.h @@ -97,14 +97,19 @@ struct rdt_hw_ctrl_domain { * @arch_mbm_states: Per-event pointer to the MBM event's saved state. * An MBM event's state is an array of struct arch_mbm_state * indexed by RMID on x86. + * @d_info: ERDT table information of this domain * * Members of this structure are accessed via helpers that provide abstrac= tion. */ struct rdt_hw_l3_mon_domain { struct rdt_l3_mon_domain d_resctrl; struct arch_mbm_state *arch_mbm_states[QOS_NUM_L3_MBM_EVENTS]; + const struct erdt_domain_info *d_info; }; =20 +bool erdt_cpu_valid(int cpu); +void erdt_l3_mon_domain_setup(int id, struct rdt_domain_hdr *hdr); + static inline struct rdt_hw_ctrl_domain *resctrl_to_arch_ctrl_dom(struct r= dt_ctrl_domain *r) { return container_of(r, struct rdt_hw_ctrl_domain, d_resctrl); --=20 2.25.1 From nobody Fri Sep 25 01:18:32 2026 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 9B062379EC1 for ; Fri, 18 Sep 2026 05:00:58 +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=1789707660; cv=none; b=gd8NCEE7rcFO5HaBG5RXE5H3A/a19uRTnx99omMkHPsCa0nWCZKJfoQZ7OAYICcVkwAnAxjTt1S1g9KHOG5pULnlcIPFuC14qu3dN8sjlZ7qfWlTX/Lr8u4VinIgx2a+J3987KbLENaPaJetpKApuQvv984bq8dvstBTAVA8+nM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789707660; c=relaxed/simple; bh=EvTSYSAw1pZwy4SODPFNStgvITm06LetBqNDGk7GQ0M=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=PFJJ7RkFQOEprNSKPfMiKHZ9BqTuG0Z9ZSKyXcSo2h9EXAWRH7iFfCcs1jUd+XT/ZGAJyvNupao0euSz7aWG1MgMBpyR3YxunexyZzFTj8WnVRU4s8z7XQfti8WmyZijIww7/hysca3js2icWBLjhMTAryjMn472Gqm4oBOYokw= 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=T9ayVUi5; 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="T9ayVUi5" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789707658; x=1821243658; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=EvTSYSAw1pZwy4SODPFNStgvITm06LetBqNDGk7GQ0M=; b=T9ayVUi5b+hKL00DDOhBGmGYSu6Dt1SAhGmiTKxA8x6f6LXfQpr49Dj3 jHLlNTOv16tJbYGaotrM/KKXH21U/+cyLHQIFlaWNVTxFzhWPxp6YBRUw sKjaVHmoXy78FLkugyX+t6LhcfsSvzl6RDSm8Zo1oDUkGfrQP6i0dVJpb iBS5Zx0QeR8xkd1BMjdYir9p32pjhie6Tn4iY0UzqS78g7vCvxC36UcKN LyYuZf/wA0HkwtEB+icOmM2X3zpZVjNsm9iitxyxm68rG4O5xfwidcL41 osTukPCEUG6m/vSiv++yG0YWEZ7EHhUhcNlHzMwsgrUi1f5diT1XmMb51 g==; X-CSE-ConnectionGUID: +61WbYewQxSEtn+zykfx9A== X-CSE-MsgGUID: gOvmCYzqSRGuy7a5VK5Flg== X-IronPort-AV: E=McAfee;i="6800,10657,11905"; a="107693036" X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="107693036" Received: from fmviesa013.fm.intel.com ([10.60.135.153]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2026 22:00:57 -0700 X-CSE-ConnectionGUID: 3yxps+WmSI2nYtatXAHm1A== X-CSE-MsgGUID: u6s5+UEDRm2BqWl1zdF21w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="2612089" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by fmviesa013.fm.intel.com with ESMTP; 17 Sep 2026 22:00:54 -0700 From: Chen Yu To: tony.luck@intel.com, reinette.chatre@intel.com Cc: tglx@kernel.org, bp@alien8.de, mingo@redhat.com, dave.hansen@linux.intel.com, hpa@zytor.com, fenghuay@nvidia.com, babu.moger@amd.com, hongyu.ning@intel.com, chen.yu@linux.dev, x86@kernel.org, linux-kernel@vger.kernel.org, Chen Yu , Hongyu Ning Subject: [PATCH v8 5/9] x86/resctrl: Parse ACPI CMRC table Date: Fri, 18 Sep 2026 12:50:15 +0800 Message-Id: <51bf1ffbd3a6efe53dc457f32b0863cc6aff0e3f.1789705667.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: quoted-printable Content-Type: text/plain; charset="utf-8" The CMRC (Cache Monitoring Registers for CPU Agents Description) sub-table = of ERDT describes the MMIO registers used to read cache monitoring counters (e= .g. LLC occupancy) for a monitoring domain. Parse each CMRC sub-table, ioremap its register window, and save a copy of = the CMRC table in the corresponding ERDT domain entry so that monitoring code c= an read the counters via MMIO. Suggested-by: Tony Luck Signed-off-by: Chen Yu Tested-by: Hongyu Ning --- arch/x86/include/asm/resctrl.h | 2 + arch/x86/kernel/cpu/resctrl/erdt.c | 73 ++++++++++++++++++++++++++ arch/x86/kernel/cpu/resctrl/internal.h | 6 ++- 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h index 8f6edcdcfd87..9a32ed418c33 100644 --- a/arch/x86/include/asm/resctrl.h +++ b/arch/x86/include/asm/resctrl.h @@ -49,6 +49,8 @@ DECLARE_STATIC_KEY_FALSE(rdt_enable_key); DECLARE_STATIC_KEY_FALSE(rdt_alloc_enable_key); DECLARE_STATIC_KEY_FALSE(rdt_mon_enable_key); =20 +unsigned int erdt_get_scale(void); + static inline bool resctrl_arch_alloc_capable(void) { return rdt_alloc_capable; diff --git a/arch/x86/kernel/cpu/resctrl/erdt.c b/arch/x86/kernel/cpu/resct= rl/erdt.c index 249ba547d7c8..a8a7417c2f82 100644 --- a/arch/x86/kernel/cpu/resctrl/erdt.c +++ b/arch/x86/kernel/cpu/resctrl/erdt.c @@ -23,6 +23,7 @@ static LIST_HEAD(domain_info_list); static bool erdt_enabled; =20 #define ERDT_VALID_VERSION 1 +#define CMRC_SUPPORTED_INDEX_FN 1 #define RMDD_FLAG_CPU_L3_DOMAIN BIT(0) =20 /* Bitmask of valid sub-tables found in the first RMDD, used to ensure all= RMDDs match. */ @@ -37,11 +38,26 @@ static u16 first_rmdd_domain_id; */ static unsigned int erdt_max_rmid; =20 +/* + * Used only by the limbo handler to round resctrl_rmid_realloc_threshold. + * resctrl_rmid_realloc_threshold is a single global value, and + * resctrl_arch_round_mon_val() takes no domain argument, so a single scal= e has + * to be derived from the per-domain cmrc->up_scale. max() is chosen becau= se the + * rounding is a floor: a larger scale yields a slightly lower threshold, = i.e. an + * RMID has to drop to a slightly lower occupancy before it is reused. + */ +static unsigned int erdt_scale; + unsigned int erdt_get_max_rmid(void) { return erdt_max_rmid; } =20 +unsigned int erdt_get_scale(void) +{ + return erdt_scale; +} + static void __iomem *erdt_ioremap(resource_size_t base, u32 num_pages, con= st char *desc) { void __iomem *addr; @@ -71,6 +87,7 @@ static void erdt_iounmap_domain(struct erdt_domain_info *= domain) static void cleanup_one_domain(struct erdt_domain_info *d) { erdt_iounmap_domain(d); + kfree(d->cmrc); kfree(d); } =20 @@ -105,6 +122,49 @@ static __init int cacd_init(struct acpi_subtbl_hdr_16 = *subtbl, return 0; } =20 +static __init int cmrc_init(struct acpi_subtbl_hdr_16 *subtbl, + struct erdt_domain_info *domain_info) +{ + struct acpi_erdt_cmrc *cmrc =3D (struct acpi_erdt_cmrc *)subtbl; + + if (cmrc->header.length < sizeof(*cmrc)) { + pr_warn(FW_BUG "Truncated CMRC sub-table\n"); + return -EIO; + } + + if (cmrc->index_fn !=3D CMRC_SUPPORTED_INDEX_FN) { + pr_info("Unsupported CMRC index function %u\n", cmrc->index_fn); + return -EIO; + } + + if (!cmrc->clump_size) { + pr_warn(FW_BUG "CMRC clump_size is zero\n"); + return -EIO; + } + + /* resctrl scales monitoring values with an unsigned int. */ + if (cmrc->up_scale > UINT_MAX) { + pr_warn(FW_BUG "Insane CMRC up_scale value 0x%llx\n", cmrc->up_scale); + return -EIO; + } + + domain_info->base[ERDT_MMIO_CMRC_BASE] =3D + erdt_ioremap(cmrc->cmt_reg_base, cmrc->cmt_reg_size, "CMRC base"); + if (!domain_info->base[ERDT_MMIO_CMRC_BASE]) + return -EIO; + + domain_info->cmrc =3D kmemdup(cmrc, cmrc->header.length, GFP_KERNEL); + if (!domain_info->cmrc) { + iounmap(domain_info->base[ERDT_MMIO_CMRC_BASE]); + domain_info->base[ERDT_MMIO_CMRC_BASE] =3D NULL; + return -ENOMEM; + } + + erdt_scale =3D max(erdt_scale, cmrc->up_scale); + + return 0; +} + static inline struct acpi_subtbl_hdr_16 *rmdd_subtbl(struct acpi_erdt_rmdd= *rmdd) { return (void *)rmdd + sizeof(*rmdd); @@ -170,6 +230,19 @@ static __init bool parse_rmdd_table(struct acpi_subtbl= _hdr_16 *rmdd_hdr) =20 subtbl_mask |=3D BIT(ACPI_ERDT_TYPE_CACD); break; + case ACPI_ERDT_TYPE_CMRC: + /* + * Only one CMRC is supported per domain as there is no + * method to distinguish different CMRCs within a domain. + */ + if (subtbl_mask & BIT(ACPI_ERDT_TYPE_CMRC)) + break; + + if (cmrc_init(subtbl, domain_info)) + goto cleanup; + + subtbl_mask |=3D BIT(ACPI_ERDT_TYPE_CMRC); + break; default: break; } diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/r= esctrl/internal.h index 2e8fb36ad804..26c3e0c546ad 100644 --- a/arch/x86/kernel/cpu/resctrl/internal.h +++ b/arch/x86/kernel/cpu/resctrl/internal.h @@ -24,10 +24,12 @@ /* * Index into erdt_domain_info::base[] for each MMIO region. * @ERDT_MMIO_RMDD_CREG: RMDD control register base address + * @ERDT_MMIO_CMRC_BASE: CMRC monitoring register base address */ enum erdt_mmio_type { ERDT_MMIO_RMDD_CREG, - ERDT_MMIO_LAST =3D ERDT_MMIO_RMDD_CREG + ERDT_MMIO_CMRC_BASE, + ERDT_MMIO_LAST =3D ERDT_MMIO_CMRC_BASE }; =20 #define ERDT_MMIO_NUM_TYPES (ERDT_MMIO_LAST + 1) @@ -35,12 +37,14 @@ enum erdt_mmio_type { /** * struct erdt_domain_info - Per-domain ERDT information * @base: Array of ioremapped MMIO region base addresses, indexed by ERDT_= MMIO_* + * @cmrc: Copy of the ACPI CMRC sub-table for this domain * @cpu_mask: CPUs belonging to this resource management domain * @dom_id: L3 cache ID shared by all CPUs in this domain (-1 if unset) * @entry: Links into the global domain_info_list */ struct erdt_domain_info { void __iomem *base[ERDT_MMIO_NUM_TYPES]; + struct acpi_erdt_cmrc *cmrc; struct cpumask cpu_mask; int dom_id; struct list_head entry; --=20 2.25.1 From nobody Fri Sep 25 01:18:32 2026 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 227EB37BE8E for ; Fri, 18 Sep 2026 05:01:10 +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=1789707673; cv=none; b=Qf0VwDHt5EqFXaXKCdTQyZcRD/bxJxkXW8srGUhJWcVeFKCW4XvWJKkjzJhYqM5oTH+6LlRonCFaqHVxzYfVdxhrPmiPPZBwGneOOeQc3P95k/cPcfK8gqWjr2nOcIwKXHd8bn2cI8O581TdkCR5Wfdm81tJ1B6D7FtTdUzaOkw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789707673; c=relaxed/simple; bh=Fnz2mSyZbEjv8xagaQfGCXTO7opPZat3MHmf6dKakhI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=r7FqAaO8QiT6tyVzDOm6hAZ7xTfu/s6/S/q5yaIBegNNrbouYCgKEvtUQxunJTEUloIZe3R3uUoHWVopssYewb2M8+hAK/OYVaa+Qv71KmXjLYIESI7gctYj38MUY7+QF+8QpFwzE2CvjWqkguK4kVFz8tvqf2YyOZaY+NWGN7U= 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=LGRVKmB0; 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="LGRVKmB0" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789707671; x=1821243671; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Fnz2mSyZbEjv8xagaQfGCXTO7opPZat3MHmf6dKakhI=; b=LGRVKmB0UHfiIFdjR814s3Ygap4XLXM1Ff+kSew7sozIkEWJW29PJZJf iggH4lNrw9M5n8uxljIVRhe7uct4oBcPCs+D6QHZft9ouFGZYm77u9Otv RKxFMuclWRbuBzhT+z5oyXOk7HpsHNeJthQvybB7iFhRxPHy6hvYmD7Wb jScqOY5v3s+VvwBFGySOjOrVXAyMxeVe/jwxZt4nn6othRW1og5VzWTn3 dXunDRque5G4P4k+fPV/jPgj4OqPuXmYjzUYoAD9zRygw4nc0Hi4YmMZU yDUFzZj2vWndWdfixIEhSNPHIcof2tnVvAMazPczFV3hXFMUXm97MNaJE A==; X-CSE-ConnectionGUID: fAkd3jVTSAaL2xihIgTNsA== X-CSE-MsgGUID: ERwRgazxSOGUC/5bZzwtCQ== X-IronPort-AV: E=McAfee;i="6800,10657,11905"; a="107693067" X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="107693067" Received: from fmviesa013.fm.intel.com ([10.60.135.153]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2026 22:01:10 -0700 X-CSE-ConnectionGUID: DzV++Gc1QSSoNl1Xs6yW7w== X-CSE-MsgGUID: 1BCUWGVCQKq/xaZZWGwoIw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="2612153" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by fmviesa013.fm.intel.com with ESMTP; 17 Sep 2026 22:01:07 -0700 From: Chen Yu To: tony.luck@intel.com, reinette.chatre@intel.com Cc: tglx@kernel.org, bp@alien8.de, mingo@redhat.com, dave.hansen@linux.intel.com, hpa@zytor.com, fenghuay@nvidia.com, babu.moger@amd.com, hongyu.ning@intel.com, chen.yu@linux.dev, x86@kernel.org, linux-kernel@vger.kernel.org, Chen Yu , Hongyu Ning Subject: [PATCH v8 6/9] x86/resctrl: Refactor the monitor read function Date: Fri, 18 Sep 2026 12:50:41 +0800 Message-Id: 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: quoted-printable Content-Type: text/plain; charset="utf-8" Split the monitor read helper into an L3 read path and an AET (Intel Applic= ation Energy Telemetry) read path. This makes the two distinct monitoring sources easier to extend independently and prepares the L3 path for ERDT-based MMIO reads. No functional change. Signed-off-by: Chen Yu Tested-by: Hongyu Ning --- arch/x86/kernel/cpu/resctrl/monitor.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/re= sctrl/monitor.c index 3838e0a13d36..138fd420131b 100644 --- a/arch/x86/kernel/cpu/resctrl/monitor.c +++ b/arch/x86/kernel/cpu/resctrl/monitor.c @@ -239,9 +239,8 @@ static u64 get_corrected_val(struct rdt_resource *r, st= ruct rdt_l3_mon_domain *d return chunks * hw_res->mon_scale; } =20 -int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain_hdr *= hdr, - u32 unused, u32 rmid, enum resctrl_event_id eventid, - void *arch_priv, u64 *val, void *ignored) +static int arch_l3_read_event(struct rdt_resource *r, struct rdt_domain_hd= r *hdr, + u32 rmid, enum resctrl_event_id eventid, u64 *val) { struct rdt_hw_l3_mon_domain *hw_dom; struct rdt_l3_mon_domain *d; @@ -251,11 +250,6 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, str= uct rdt_domain_hdr *hdr, int cpu; int ret; =20 - resctrl_arch_rmid_read_context_check(); - - if (r->rid =3D=3D RDT_RESOURCE_PERF_PKG) - return intel_aet_read_event(hdr->id, rmid, arch_priv, val); - if (!domain_header_is_valid(hdr, RESCTRL_MON_DOMAIN, RDT_RESOURCE_L3)) return -EINVAL; =20 @@ -281,6 +275,22 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, str= uct rdt_domain_hdr *hdr, return ret; } =20 +int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain_hdr *= hdr, + u32 unused, u32 rmid, enum resctrl_event_id eventid, + void *arch_priv, u64 *val, void *ignored) +{ + resctrl_arch_rmid_read_context_check(); + + switch (r->rid) { + case RDT_RESOURCE_L3: + return arch_l3_read_event(r, hdr, rmid, eventid, val); + case RDT_RESOURCE_PERF_PKG: + return intel_aet_read_event(hdr->id, rmid, arch_priv, val); + default: + return -EINVAL; + } +} + static int __cntr_id_read(u32 cntr_id, u64 *val) { struct msr msr_val =3D { --=20 2.25.1 From nobody Fri Sep 25 01:18:32 2026 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 9CFC92E737B for ; Fri, 18 Sep 2026 05:01: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=1789707683; cv=none; b=iQyZ3phCFBvH5WZ/KMoSN1HJNwPNYLR3fDU0Oj1MbmCdZlXn8l0SQozuTlbYkitvDq6aPLjVLU1EQVSNHvlD3kvulMBYEo3SvcTENOKtbJKfYw2beP+zvxTT/xvjQpOFp/nuJd4Zq/Egs6sxmZh400ZWkJ9wmiiiFmg/kPsQfv8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789707683; c=relaxed/simple; bh=vCOgFkquUfKp2S4mfMttclgB1SUTNvecrCaoIOtAvq0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=MD7AwK7h+aqUL2lOBmR7Xupzx/L4Wntoj5Ep2iO/ahsbum+kRjddKEKsH2bbaIkaNFpqr6HUPiN25FzhhOJEeEDNNgED3ex/r8KXRRfYiJMSELk8Rv2aOe4/X9sM25jv9ND3eNktkrZO0UOoyRl6ypRVDmTPEDHsP6SeSnJ2LDs= 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=AYl0yynV; 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="AYl0yynV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789707681; x=1821243681; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=vCOgFkquUfKp2S4mfMttclgB1SUTNvecrCaoIOtAvq0=; b=AYl0yynVVvLU5dx3kIzICQ/CFyvsQaa4dUGmnaCEd+jjlfEagWiM7uW0 oSHHmfkxs0XDXQPNtq7j6F97TsbTf9xWc569nsGQ4CJMJla9gs63B+RBK Ou9kQiFoSRj4sBa+gJo0Q01ocE0anX0bjhwnSetVqoXonmxy/ZRXdyj46 mABTMN3uDcgHyYvE/vvwPCwsuiXTO3coKMIlvzXvkPRgBVhq9yjsyQWiE 3zxXHI0lAKlHZDdLFum6YxDmRxDgXHEa5yLRJ59SjuL0cpyhiF56srAgx OBj0IPxAixAgdJby2FLODMg9K0HJ/RiEVVKpkyaCDpAaIeTP6llg/aovi g==; X-CSE-ConnectionGUID: 155B6O96RSiwiTCr5vESqg== X-CSE-MsgGUID: tMXAoN99SnyxLAvYdgKQ/g== X-IronPort-AV: E=McAfee;i="6800,10657,11905"; a="107693092" X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="107693092" Received: from fmviesa013.fm.intel.com ([10.60.135.153]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2026 22:01:21 -0700 X-CSE-ConnectionGUID: qUkR6JN/Ti6QpeyUqMHDBw== X-CSE-MsgGUID: KJyo+2mQSXSTiDwKm1wUHA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="2612218" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by fmviesa013.fm.intel.com with ESMTP; 17 Sep 2026 22:01:18 -0700 From: Chen Yu To: tony.luck@intel.com, reinette.chatre@intel.com Cc: tglx@kernel.org, bp@alien8.de, mingo@redhat.com, dave.hansen@linux.intel.com, hpa@zytor.com, fenghuay@nvidia.com, babu.moger@amd.com, hongyu.ning@intel.com, chen.yu@linux.dev, x86@kernel.org, linux-kernel@vger.kernel.org, Chen Yu , Hongyu Ning Subject: [PATCH v8 7/9] fs/resctrl: Do not invoke smp_processor_id() in preemptible context Date: Fri, 18 Sep 2026 12:50:51 +0800 Message-Id: <6e0ff955200ead6a2ac689d492a5e5c73ebc3552.1789705667.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: quoted-printable Content-Type: text/plain; charset="utf-8" From: Tony Luck An event flagged with mon_evt::any_cpu is read directly in preemptible task context instead of being dispatched to a CPU of the monitoring domain. Only Intel AET events set this flag, so __mon_event_count() rejects an any_cpu L3 event with WARN_ON_ONCE(). The L3 read paths can therefore call smp_processor_id() unconditionally to check that the current CPU belongs to= the domain being read. MMIO-based LLC occupancy counters can be read from any CPU, so the L3 read paths have to tolerate an any_cpu event. Move that check into a helper which returns early for any_cpu events, avoiding smp_processor_id() in preemptible context, and report a wrong CPU via rmid_read::err. Signed-off-by: Tony Luck Signed-off-by: Chen Yu Tested-by: Hongyu Ning --- fs/resctrl/monitor.c | 48 +++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c index 73413cb128ea..3e05b0271c58 100644 --- a/fs/resctrl/monitor.c +++ b/fs/resctrl/monitor.c @@ -422,9 +422,37 @@ static void mbm_cntr_free(struct rdt_l3_mon_domain *d,= int cntr_id) memset(&d->cntr_cfg[cntr_id], 0, sizeof(*d->cntr_cfg)); } =20 +/** + * cpu_on_correct_domain() - Check if current CPU is in the correct + * domain for the event. + * @rr: The rmid_read structure containing event and domain information. + * + * Context: Preemptible process context when @rr->evt->any_cpu is set. + * Non-migratable process context (via smp_call_on_cpu()) or + * non-preemptible context (via smp_call_function_any()) when + * the event must be read on a specific CPU. + * Return: true if the current CPU can read this event, false otherwise. + */ +static bool cpu_on_correct_domain(struct rmid_read *rr) +{ + int cpu; + + /* Any CPU is OK for this event */ + if (rr->evt->any_cpu) + return true; + + cpu =3D smp_processor_id(); + + /* Single domain. Must be on a CPU in that domain. */ + if (rr->hdr) + return cpumask_test_cpu(cpu, &rr->hdr->cpu_mask); + + /* Summing domains that share a cache, must be on a CPU for that cache. */ + return cpumask_test_cpu(cpu, &rr->ci->shared_cpu_map); +} + static int __l3_mon_event_count(struct rdtgroup *rdtgrp, struct rmid_read = *rr) { - int cpu =3D smp_processor_id(); u32 closid =3D rdtgrp->closid; u32 rmid =3D rdtgrp->mon.rmid; struct rdt_l3_mon_domain *d; @@ -457,11 +485,6 @@ static int __l3_mon_event_count(struct rdtgroup *rdtgr= p, struct rmid_read *rr) return 0; } =20 - /* Reading a single domain, must be on a CPU in that domain. */ - if (!cpumask_test_cpu(cpu, &d->hdr.cpu_mask)) { - rr->err =3D -EIO; - return -EINVAL; - } if (rr->is_mbm_cntr) rr->err =3D resctrl_arch_cntr_read(rr->r, d, closid, rmid, cntr_id, rr->evt->evtid, &tval); @@ -479,7 +502,6 @@ static int __l3_mon_event_count(struct rdtgroup *rdtgrp= , struct rmid_read *rr) =20 static int __l3_mon_event_count_sum(struct rdtgroup *rdtgrp, struct rmid_r= ead *rr) { - int cpu =3D smp_processor_id(); u32 closid =3D rdtgrp->closid; u32 rmid =3D rdtgrp->mon.rmid; struct rdt_l3_mon_domain *d; @@ -497,12 +519,6 @@ static int __l3_mon_event_count_sum(struct rdtgroup *r= dtgrp, struct rmid_read *r return -EINVAL; } =20 - /* Summing domains that share a cache, must be on a CPU for that cache. */ - if (!cpumask_test_cpu(cpu, &rr->ci->shared_cpu_map)) { - rr->err =3D -EIO; - return -EINVAL; - } - /* * Legacy files must report the sum of an event across all * domains that share the same L3 cache instance. @@ -538,7 +554,11 @@ static int __mon_event_count(struct rdtgroup *rdtgrp, = struct rmid_read *rr) { switch (rr->r->rid) { case RDT_RESOURCE_L3: - WARN_ON_ONCE(rr->evt->any_cpu); + if (!cpu_on_correct_domain(rr)) { + rr->err =3D -EIO; + return -EINVAL; + } + if (rr->hdr) return __l3_mon_event_count(rdtgrp, rr); else --=20 2.25.1 From nobody Fri Sep 25 01:18:32 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.6]) (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 8AA162F1FDF for ; Fri, 18 Sep 2026 05:01:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.6 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789707698; cv=none; b=hUDhgPBx7vfPwEIgTAOX+tgrSLqM0BoF39LgckFillEQc3yd/8USepgX0qyMpLcqQ6FIevGiRzloY60xXmtRE1TOUxK1z9S9cAeMhw8pfb4mzkSXZK3kdxB6KWOrpiCQbs7PhD7/hb997kddYbQRTQj7NB5LTnGGDE01IZVoAUQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789707698; c=relaxed/simple; bh=CnJhrUZO8DVP07la5kQeChxAKJ3RxLbg5ajonUKBR+E=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=pE+N+6KlFyrosg/BfY6RLi4YobXg6EVomYCz7i9YQM8WTp+GVx+RAzR6DgQEM4ejgPf5dmEOr9cqfRJDccKEpmJFlyBL5mt2kqbdDPmxjCEBNoBDianW/lKLcdjoNIb+PfeQM2Uxg6MCc3cc7Zv+wEDWId/3MTPlL+rDJN5i9Lk= 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=O3oMOaPX; arc=none smtp.client-ip=192.198.163.6 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="O3oMOaPX" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789707697; x=1821243697; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=CnJhrUZO8DVP07la5kQeChxAKJ3RxLbg5ajonUKBR+E=; b=O3oMOaPXQyJKAhgN8GIgc7azrULYp16ES4fdHIEYttcm7xpn3uguwVlS j1nQF39E0WmBHswCG9+DzW8SdxuiMriNXowQr+SW/a+R9emOg5HDw1Pin gdgMDJUd3DoN2b4O5IrP49wr+rv1tXNbNy5cBSYGL/b24uXTpsiobMNA3 0ZP8YJWAzE03EUczrI9e0E1hTplsuX0lO2s1F9dgiMp0jKzmzpm5oi/ja CycSeQvZ/hVTcxkhY8dIpW9kJeNXOvML0hzJAoGHnIsFhzP/QSRpYsc/p X1Auo+XvpNYEu/ALof4Xkjk8ZSafZJT8meIvPhD4aGAlISeIkp8/yfn4A Q==; X-CSE-ConnectionGUID: j+nQeGVjSeWBrg4h1om1jg== X-CSE-MsgGUID: 9IAHb7VUTPOkz7C7A36Y1w== X-IronPort-AV: E=McAfee;i="6800,10657,11905"; a="704909" X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="704909" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by fmvoesa116.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2026 22:01:37 -0700 X-CSE-ConnectionGUID: +7JWQMM4TuS7xz12/tEvWA== X-CSE-MsgGUID: xJsy1xeqQ5mvvhc++82ykQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="271542587" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by fmviesa008.fm.intel.com with ESMTP; 17 Sep 2026 22:01:32 -0700 From: Chen Yu To: tony.luck@intel.com, reinette.chatre@intel.com Cc: tglx@kernel.org, bp@alien8.de, mingo@redhat.com, dave.hansen@linux.intel.com, hpa@zytor.com, fenghuay@nvidia.com, babu.moger@amd.com, hongyu.ning@intel.com, chen.yu@linux.dev, x86@kernel.org, linux-kernel@vger.kernel.org, Chen Yu , Hongyu Ning Subject: [PATCH v8 8/9] x86/resctrl: Introduce erdt_cpu_has() and erdt_support() Date: Fri, 18 Sep 2026 12:51:02 +0800 Message-Id: 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: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce erdt_cpu_has() to verify if a specific RDT feature is backed by an ERDT table. erdt_cpu_has() is derived from rdt_cpu_has(), which not only considers firmware (ERDT table and its sub-tables) support for a feature, b= ut also considers userspace input like "rdt=3D!cmt". Similar to rdt_cpu_has(), erdt_cpu_has() expects an x86 feature flag as parameter. Introduce erdt_support() as a helper called by erdt_cpu_has() to check whet= her the ERDT firmware supports a given feature. erdt_support() deliberately claims no feature yet and returns false. A feat= ure may only be reported as ERDT backed once the low level accessors that access its data via MMIO exist, otherwise callers would take the ERDT path and fin= d no implementation behind it. Features should be added to erdt_support() as the= ir MMIO implementations are introduced. Signed-off-by: Chen Yu Tested-by: Hongyu Ning --- arch/x86/include/asm/resctrl.h | 1 + arch/x86/kernel/cpu/resctrl/core.c | 23 +++++++++++++++++++++++ arch/x86/kernel/cpu/resctrl/erdt.c | 5 +++++ arch/x86/kernel/cpu/resctrl/internal.h | 1 + 4 files changed, 30 insertions(+) diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h index 9a32ed418c33..bcfcc8ac1fe6 100644 --- a/arch/x86/include/asm/resctrl.h +++ b/arch/x86/include/asm/resctrl.h @@ -49,6 +49,7 @@ DECLARE_STATIC_KEY_FALSE(rdt_enable_key); DECLARE_STATIC_KEY_FALSE(rdt_alloc_enable_key); DECLARE_STATIC_KEY_FALSE(rdt_mon_enable_key); =20 +bool erdt_cpu_has(int flag); unsigned int erdt_get_scale(void); =20 static inline bool resctrl_arch_alloc_capable(void) diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resct= rl/core.c index 3514d73a8056..ca7e67f976d5 100644 --- a/arch/x86/kernel/cpu/resctrl/core.c +++ b/arch/x86/kernel/cpu/resctrl/core.c @@ -897,6 +897,29 @@ bool rdt_cpu_has(int flag) return ret; } =20 +bool erdt_cpu_has(int flag) +{ + struct rdt_options *o; + bool ret; + + ret =3D erdt_support(flag); + + if (!ret) + return ret; + + for (o =3D rdt_options; o < &rdt_options[NUM_RDT_OPTIONS]; o++) { + if (flag =3D=3D o->flag) { + if (o->force_off) + ret =3D false; + if (o->force_on) + ret =3D true; + break; + } + } + + return ret; +} + bool resctrl_arch_is_evt_configurable(enum resctrl_event_id evt) { if (!rdt_cpu_has(X86_FEATURE_BMEC)) diff --git a/arch/x86/kernel/cpu/resctrl/erdt.c b/arch/x86/kernel/cpu/resct= rl/erdt.c index a8a7417c2f82..400973ebf2b8 100644 --- a/arch/x86/kernel/cpu/resctrl/erdt.c +++ b/arch/x86/kernel/cpu/resctrl/erdt.c @@ -48,6 +48,11 @@ static unsigned int erdt_max_rmid; */ static unsigned int erdt_scale; =20 +bool erdt_support(int flag) +{ + return false; +} + unsigned int erdt_get_max_rmid(void) { return erdt_max_rmid; diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/r= esctrl/internal.h index 26c3e0c546ad..ce037e017fc3 100644 --- a/arch/x86/kernel/cpu/resctrl/internal.h +++ b/arch/x86/kernel/cpu/resctrl/internal.h @@ -287,6 +287,7 @@ static inline void intel_aet_mon_domain_setup(int cpu, = int id, struct rdt_resour static inline bool intel_handle_aet_option(bool force_off, char *tok) { re= turn false; } #endif =20 +bool erdt_support(int flag); unsigned int erdt_get_max_rmid(void); int erdt_init(void); void erdt_exit(void); --=20 2.25.1 From nobody Fri Sep 25 01:18:32 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.6]) (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 2C5D7547070 for ; Fri, 18 Sep 2026 05:01:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.6 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789707708; cv=none; b=pqHUtLJEYLfHA/GYDpRVVKcpsOepkVY+Q+0MUj4VKag08A0m7NgX1q4eSPNZ6GhcYSR1Vsz7830qoS8uTtUYjEH6Mf4HxJ50UfqBmp9AfqrZx525f+hsstKcIipyZ1WGbZwAIqOmyQP6PpDra/AB6F1xB1bYi6jeiAu524yGYVM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789707708; c=relaxed/simple; bh=iyhvSZKEJbUo1GxfN6urlameJ0XPTHn5O/gYeTE8UH8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=IAi5I4yuEmjdEhFLXh+XhbSelhiaqgorPzS8q/lWIyViVYptiCRXtEvcQkAmbDd97u50aQzN3wLrw0wygO/jTPcqoDA2101fR0CfYlZpNSZr59hb9mSFEEbjgjHYqsxjt6+h9ExNmIpWeosRzTs6wFSzf8ToVY//3qWMKSu8FnY= 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=SySM41DU; arc=none smtp.client-ip=192.198.163.6 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="SySM41DU" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789707708; x=1821243708; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=iyhvSZKEJbUo1GxfN6urlameJ0XPTHn5O/gYeTE8UH8=; b=SySM41DUqyduOABi7pSwr43gPqpOB8oIHbhP7gfGuiLeheLbyMBv2laz 4qy3LwFZ8StOXlgzl9BooBa3vXWEt8St9CTgxBofKQkDPOvf7mPBtNf/7 emTmV8PSBS0yFdmW3szEaRo291r2WuubVMan1C+94Ri03FTJbWM04OCuk /At5I7s3X9Yj/VCLz2ooD9Pjo/p0+v2hetEtgj4k3qlyGnmttIFvcjQxm qxG+P4nwAoGzPU5PfLwABDzPAbCbbXKLWl6EoItgjbK5TOP2h7yYtggHP M0fjW2uVv2OrnW8qEHGX+3pQKuadiusnhKmBM3B7HiO/+4wejXk5FD0Y7 A==; X-CSE-ConnectionGUID: 9pFfc9JXSB+m4Go5AppYbA== X-CSE-MsgGUID: hPAkl8ylTmScSzoZwZ5E0w== X-IronPort-AV: E=McAfee;i="6800,10657,11905"; a="704940" X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="704940" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by fmvoesa116.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2026 22:01:47 -0700 X-CSE-ConnectionGUID: dWcyI+e5SvKEicdBn6QSGw== X-CSE-MsgGUID: T9xlsuNGSGSFPBYFVD72Ag== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,103,1787036400"; d="scan'208";a="271542646" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by fmviesa008.fm.intel.com with ESMTP; 17 Sep 2026 22:01:43 -0700 From: Chen Yu To: tony.luck@intel.com, reinette.chatre@intel.com Cc: tglx@kernel.org, bp@alien8.de, mingo@redhat.com, dave.hansen@linux.intel.com, hpa@zytor.com, fenghuay@nvidia.com, babu.moger@amd.com, hongyu.ning@intel.com, chen.yu@linux.dev, x86@kernel.org, linux-kernel@vger.kernel.org, Chen Yu , Hongyu Ning Subject: [PATCH v8 9/9] x86/resctrl: Add MMIO-based LLC occupancy monitoring support Date: Fri, 18 Sep 2026 12:51:17 +0800 Message-Id: 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: quoted-printable Content-Type: text/plain; charset="utf-8" Add erdt_mon_read() to read LLC occupancy via MMIO and use it when the plat= form supports ERDT. Register the L3 occupancy event with ERDT enabled when avail= able, falling back to the MSR-based path otherwise. Use the CMRC (Cache Monitoring Registers for CPU Agents Description) ACPI sub-table to read LLC occupancy counters for each RMID via MMIO when ERDT is enabled. Store the CMRC information in the rdt_hw_l3_mon_domain, which coul= d be accessed directly. Although the occupancy counters can now be read from any CPU via MMIO, the per-domain limbo handler is kept. A global handler would still have to iter= ate over every domain and would only save one worker thread, which does not jus= tify maintaining two limbo handler models. Suggested-by: Reinette Chatre Signed-off-by: Chen Yu Tested-by: Hongyu Ning --- arch/x86/include/asm/resctrl.h | 8 ++- arch/x86/kernel/cpu/resctrl/core.c | 5 +- arch/x86/kernel/cpu/resctrl/erdt.c | 74 +++++++++++++++++++++++++- arch/x86/kernel/cpu/resctrl/internal.h | 9 +++- arch/x86/kernel/cpu/resctrl/monitor.c | 14 +++-- 5 files changed, 102 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h index bcfcc8ac1fe6..31c2f81cd06e 100644 --- a/arch/x86/include/asm/resctrl.h +++ b/arch/x86/include/asm/resctrl.h @@ -135,7 +135,13 @@ static inline void __resctrl_sched_in(struct task_stru= ct *tsk) =20 static inline unsigned int resctrl_arch_round_mon_val(unsigned int val) { - unsigned int scale =3D boot_cpu_data.x86_cache_occ_scale; + unsigned int scale =3D boot_cpu_data.x86_cache_occ_scale, escale; + + if (erdt_cpu_has(X86_FEATURE_CQM_OCCUP_LLC)) { + escale =3D erdt_get_scale(); + if (escale) + scale =3D escale; + } =20 /* h/w works in units of "boot_cpu_data.x86_cache_occ_scale" */ val /=3D scale; diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resct= rl/core.c index ca7e67f976d5..135f2eb2a5a5 100644 --- a/arch/x86/kernel/cpu/resctrl/core.c +++ b/arch/x86/kernel/cpu/resctrl/core.c @@ -1007,7 +1007,10 @@ static __init bool get_rdt_mon_resources(void) struct rdt_resource *r =3D &rdt_resources_all[RDT_RESOURCE_L3].r_resctrl; bool ret =3D false; =20 - if (rdt_cpu_has(X86_FEATURE_CQM_OCCUP_LLC)) { + if (erdt_cpu_has(X86_FEATURE_CQM_OCCUP_LLC)) { + resctrl_enable_mon_event(QOS_L3_OCCUP_EVENT_ID, true, 0, NULL); + ret =3D true; + } else if (rdt_cpu_has(X86_FEATURE_CQM_OCCUP_LLC)) { resctrl_enable_mon_event(QOS_L3_OCCUP_EVENT_ID, false, 0, NULL); ret =3D true; } diff --git a/arch/x86/kernel/cpu/resctrl/erdt.c b/arch/x86/kernel/cpu/resct= rl/erdt.c index 400973ebf2b8..f350a516d3d9 100644 --- a/arch/x86/kernel/cpu/resctrl/erdt.c +++ b/arch/x86/kernel/cpu/resctrl/erdt.c @@ -26,6 +26,10 @@ static bool erdt_enabled; #define CMRC_SUPPORTED_INDEX_FN 1 #define RMDD_FLAG_CPU_L3_DOMAIN BIT(0) =20 +/* Set in a monitoring counter when it holds no valid data to report. */ +#define UNAVAILABLE_COUNTER BIT_ULL(63) +#define CMRC_FLAG_UNAVAILABLE_BIT BIT(0) + /* Bitmask of valid sub-tables found in the first RMDD, used to ensure all= RMDDs match. */ static u32 valid_subtbl_mask; =20 @@ -50,7 +54,12 @@ static unsigned int erdt_scale; =20 bool erdt_support(int flag) { - return false; + switch (flag) { + case X86_FEATURE_CQM_OCCUP_LLC: + return valid_subtbl_mask & BIT(ACPI_ERDT_TYPE_CMRC); + default: + return false; + } } =20 unsigned int erdt_get_max_rmid(void) @@ -60,7 +69,68 @@ unsigned int erdt_get_max_rmid(void) =20 unsigned int erdt_get_scale(void) { - return erdt_scale; + /* Divided by snc_nodes_per_l3_cache, see erdt_read_l3_occupancy(). */ + return erdt_scale / snc_nodes_per_l3_cache; +} + +static u32 cmrc_index_function_1(struct acpi_erdt_cmrc *cmrc, u32 rmid) +{ + /* + * MMIO_offset_for_RMID# =3D + * (RMID / ClumpSize) * Stride + + * (RMID % ClumpSize) * 8 + */ + return (rmid / cmrc->clump_size) * cmrc->clump_stride + + (rmid % cmrc->clump_size) * 8; +} + +static int erdt_read_l3_occupancy(const struct erdt_domain_info *d, u32 rm= id, u64 *val) +{ + struct acpi_erdt_cmrc *cmrc; + u64 l3_cmt_count; + u32 offset; + + cmrc =3D d->cmrc; + if (!cmrc) + return -EIO; + + offset =3D cmrc_index_function_1(cmrc, rmid); + /* Overflow of cmt_reg_size * SZ_4K already validated in erdt_ioremap(). = */ + if (offset + sizeof(u64) > (u32)cmrc->cmt_reg_size * SZ_4K) + return -EINVAL; + + l3_cmt_count =3D readq(d->base[ERDT_MMIO_CMRC_BASE] + offset); + if ((cmrc->flags & CMRC_FLAG_UNAVAILABLE_BIT) && + (l3_cmt_count & UNAVAILABLE_COUNTER)) + return -EINVAL; + + /* + * In legacy mode, scale is divided by snc_nodes_per_l3_cache to + * prevent over-calculation of aggregated monitor data, do it + * the same for MMIO based access. + * This scaling factor might need to be revisited/tuned for future + * platforms that support both SNC and MMIO-based monitoring + * simultaneously. + */ + *val =3D l3_cmt_count * cmrc->up_scale / snc_nodes_per_l3_cache; + + return 0; +} + +int erdt_mon_read(struct rdt_domain_hdr *hdr, enum resctrl_event_id evtid,= u32 rmid, u64 *val) +{ + struct rdt_hw_l3_mon_domain *hw_dom; + const struct erdt_domain_info *d; + + hw_dom =3D resctrl_to_arch_mon_dom(container_of(hdr, struct rdt_l3_mon_do= main, hdr)); + d =3D hw_dom->d_info; + if (!d) + return -EIO; + + if (evtid =3D=3D QOS_L3_OCCUP_EVENT_ID) + return erdt_read_l3_occupancy(d, rmid, val); + + return -EIO; } =20 static void __iomem *erdt_ioremap(resource_size_t base, u32 num_pages, con= st char *desc) diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/r= esctrl/internal.h index ce037e017fc3..e2d0d6c76b20 100644 --- a/arch/x86/kernel/cpu/resctrl/internal.h +++ b/arch/x86/kernel/cpu/resctrl/internal.h @@ -156,7 +156,11 @@ struct msr_param { * which has been corrected for features like CDP. * @msr_base: Base MSR address for CBMs * @msr_update: Function pointer to update QOS MSRs - * @mon_scale: cqm counter * mon_scale =3D occupancy in bytes + * @mon_scale: Scale factor applied to a raw counter value on the + * MSR-based read path: CMT occupancy counter * mon_scale =3D + * occupancy in bytes, and MBM chunk count * mon_scale =3D bytes + * transferred. ERDT reads occupancy via MMIO and applies its + * own firmware-provided scale instead. * @mbm_width: Monitor width, to detect and correct for overflow. * @cdp_enabled: CDP state of this resource * @mbm_cntr_assign_enabled: ABMC feature is enabled @@ -185,6 +189,8 @@ static inline struct rdt_hw_resource *resctrl_to_arch_r= es(struct rdt_resource *r =20 extern struct rdt_hw_resource rdt_resources_all[]; =20 +extern int snc_nodes_per_l3_cache; + void arch_mon_domain_online(struct rdt_resource *r, struct rdt_l3_mon_doma= in *d); =20 /* CPUID.(EAX=3D10H, ECX=3DResID=3D1).EAX */ @@ -289,6 +295,7 @@ static inline bool intel_handle_aet_option(bool force_o= ff, char *tok) { return f =20 bool erdt_support(int flag); unsigned int erdt_get_max_rmid(void); +int erdt_mon_read(struct rdt_domain_hdr *hdr, enum resctrl_event_id evtid,= u32 rmid, u64 *val); int erdt_init(void); void erdt_exit(void); =20 diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/re= sctrl/monitor.c index 138fd420131b..1fc02020dbc9 100644 --- a/arch/x86/kernel/cpu/resctrl/monitor.c +++ b/arch/x86/kernel/cpu/resctrl/monitor.c @@ -34,7 +34,7 @@ bool rdt_mon_capable; =20 #define CF(cf) ((unsigned long)(1048576 * (cf) + 0.5)) =20 -static int snc_nodes_per_l3_cache =3D 1; +int snc_nodes_per_l3_cache =3D 1; =20 /* * The correction factor table is documented in Documentation/filesystems/= resctrl.rst. @@ -283,6 +283,10 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, str= uct rdt_domain_hdr *hdr, =20 switch (r->rid) { case RDT_RESOURCE_L3: + if (eventid =3D=3D QOS_L3_OCCUP_EVENT_ID && + erdt_cpu_has(X86_FEATURE_CQM_OCCUP_LLC)) + return erdt_mon_read(hdr, eventid, rmid, val); + return arch_l3_read_event(r, hdr, rmid, eventid, val); case RDT_RESOURCE_PERF_PKG: return intel_aet_read_event(hdr->id, rmid, arch_priv, val); @@ -432,12 +436,16 @@ int __init rdt_get_l3_mon_config(struct rdt_resource = *r) struct rdt_hw_resource *hw_res =3D resctrl_to_arch_res(r); unsigned int threshold; u32 eax, ebx, ecx, edx; + int max_rmid; =20 snc_nodes_per_l3_cache =3D snc_get_config(); =20 + max_rmid =3D erdt_cpu_has(X86_FEATURE_CQM_OCCUP_LLC) ? + min_t(int, erdt_get_max_rmid(), boot_cpu_data.x86_cache_max_rmid) : + boot_cpu_data.x86_cache_max_rmid; resctrl_rmid_realloc_limit =3D boot_cpu_data.x86_cache_size * 1024; hw_res->mon_scale =3D boot_cpu_data.x86_cache_occ_scale / snc_nodes_per_l= 3_cache; - r->mon.num_rmid =3D (boot_cpu_data.x86_cache_max_rmid + 1) / snc_nodes_pe= r_l3_cache; + r->mon.num_rmid =3D (max_rmid + 1) / snc_nodes_per_l3_cache; hw_res->mbm_width =3D MBM_CNTR_WIDTH_BASE; =20 if (mbm_offset > 0 && mbm_offset <=3D MBM_CNTR_WIDTH_OFFSET_MAX) @@ -456,7 +464,7 @@ int __init rdt_get_l3_mon_config(struct rdt_resource *r) =20 /* * Because num_rmid may not be a power of two, round the value - * to the nearest multiple of hw_res->mon_scale so it matches a + * to the nearest multiple of hw_res->mon_scale or mmio scale so it match= es a * value the hardware will measure. mon_scale may not be a power of 2. */ resctrl_rmid_realloc_threshold =3D resctrl_arch_round_mon_val(threshold); --=20 2.25.1