From nobody Mon Jun 8 06:35:56 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 81D5B175A9F for ; Sat, 6 Jun 2026 02:42:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780713771; cv=none; b=I/ka1duJr+06MazdzoigUErel3RLX5Bfbith6qw3+bh4uTCWtn7iEcLV112u+aBZ2Ebt0QonjMmijwD1TVmcnqmy0Vc2lJ0Gl5tGqc/72s2w3ZPhbbyoZ9j9NFt8nRLyhuXixi2y+ARa8tWV4EI7cDmgb0BEQhtqZGKA/Z2w7+Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780713771; c=relaxed/simple; bh=rTUHfEYPCXWbDS0idHtu8IHv8T8T+Gq1RSyZhcrdh9c=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=oGwoRNXBmwAmGfW9UUTWnVD+hMwinnrWvzNaZyvhpylr5pjkldPbGwYjSy/fheFNKu/md9ukKxrq5+osTcrdHb7YRFe7L+Y7OnmMECjr+kRDqmCSDcQKYkZReu4SsxQUVTj3ITpFfXea3XgJh4zqqHPdyD3UM6uEP26ZusN/8BE= 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=PJCB0j5s; arc=none smtp.client-ip=198.175.65.15 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="PJCB0j5s" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1780713769; x=1812249769; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=rTUHfEYPCXWbDS0idHtu8IHv8T8T+Gq1RSyZhcrdh9c=; b=PJCB0j5sbZdON1/y2QPA1Vqbqfeu0X8M3QsjXAWWV+xFbZ4RWVf35DMo NlgxEYKIfqMXm46+TDlxLcspiYBXrz/c/AV7TpZ3uqRKQalS2X/0RZN5/ CtWYnCfvjep2mumIQeyVcZsqwH+p6f6LSqDe4WHugEP5LHA9LgHME9n4e a78KQ9EncnhLj1+fN8gnCR+mCETAsonfU4feBsJD1O66AlXl3hVjgCXMf MUVKqSVQEtLH3b8QX+4AmL/HZWuR7+3NTbDn5tYvq3XtnYTSw6ttu0YwD MOV7qdkaK2IykeDs1SrHbPOz99dXqZ4Y6JdhWsZ/ivrAJy0vwFkn5wLvR g==; X-CSE-ConnectionGUID: s9rG/rmASluM4tcDaQ72IQ== X-CSE-MsgGUID: P0ugbhRTSTSz/ktqDfmNvQ== X-IronPort-AV: E=McAfee;i="6800,10657,11808"; a="85166949" X-IronPort-AV: E=Sophos;i="6.24,189,1774335600"; d="scan'208";a="85166949" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Jun 2026 19:42:48 -0700 X-CSE-ConnectionGUID: LoGUITzwRaC7iiq2ymdKRg== X-CSE-MsgGUID: aBTYASHbTIOkIS8Dj5jZ7Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.24,189,1774335600"; d="scan'208";a="283084020" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by orviesa001.jf.intel.com with ESMTP; 05 Jun 2026 19:42:43 -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 v3 1/6] x86/resctrl: Parse ACPI ERDT table and map RMDD domains by L3 cache ID Date: Sat, 6 Jun 2026 10:32:55 +0800 Message-Id: <53eeaead2d02cfa53204fe3101df3c0a09796ff9.1780710620.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: Anil S Keshavamurthy ERDT(Enhanced RDT) introduces a new top-level ACPI structure (the ERDT) that the kernel must parse before any enhanced RDT feature can be used. The ERDT improves the existing RDT by switching low-level register access from MSR-based to MMIO-based, which is more efficient. The ERDT structure may include several sub ACPI tables: - Resource Management Domain Description Structure (RMDD) - CPU Agent Collection Description Structure (CACD) - Cache Monitoring Registers for CPU Agents Description Structure (CMRC) There is one ERDT table per platform. Each RMDD substructure in ERDT represents one resource management domain (RMD), also known as an L3 domain. Thus, the total number of RMDDs equals the number of L3 domains on the platform. Each RMDD contains information such as MMIO addresses. This address is used to retrieve RDT metrics like L3 occupancy. Add basic ERDT ACPI table and sub-table parsing, and store the relevant tables for later processing. Among these sub-tables, RMDD requires special handling. There is one RMDD per domain, and the domain ID reuses the L3 cache ID. Many code paths need to retrieve an RMDD efficiently by domain ID (L3 cache ID). Because L3 cache IDs are derived from x2APIC IDs and are not contiguous, using a plain array indexed by domain ID would waste memory. As a trade-off, an xarray is used to store these tables, with the L3 cache ID as the key. Suggested-by: Tony Luck Co-developed-by: Chen Yu Signed-off-by: Chen Yu Signed-off-by: Anil S Keshavamurthy --- v2->v3: Wrap __resctrl_arch_late_init() to avoid the goto logic. (Thomas Gleixne= r) Make the variables in struct erdt_domain_info tabular format (Thomas Gle= ixner) Remove tail comments (Thomas Gleixner) Make the name of erdt_enabled() and variable in it consistent and comprehensible. (Thomas Gleixner) Use topo_lookup_cpuid() to search the CPU id according to the x2apic id (Thomas Gleixner) Fix kernel doc comment format (Thomas Gleixner) Use brackets for multiple lines "if" case. (Thomas Gleixner) Let the parameter for cacd_init() to fully utilize 100 characters. (Thomas Gleixner) Variables are reordered in reverse fir-tree.(Thomas Gleixner) Added a named constant and use it in the rmdd->flags check. (Thomas Gleixner) Introduce helper functions to make the code readable when iterating the RMDD tables. (Thomas Gleixner) v1->v2: Add #include to follow the "include-what-you-use" best. (Tony Luck) Remove the variable of cacd in struct erdt_domain_info as it will never be used after initialization.(sashiko) Invoke erdt_exit() to avoid resource leak if rdt_alloc_capable and rdt_mon_capable are both false.(sashiko) Refine comments.(sashiko) --- arch/x86/Kconfig | 4 +- arch/x86/include/asm/apic.h | 1 + arch/x86/include/asm/resctrl.h | 2 + arch/x86/kernel/cpu/resctrl/Makefile | 1 + arch/x86/kernel/cpu/resctrl/core.c | 14 +- arch/x86/kernel/cpu/resctrl/erdt.c | 304 +++++++++++++++++++++++++ arch/x86/kernel/cpu/resctrl/internal.h | 3 + arch/x86/kernel/cpu/topology.c | 2 +- 8 files changed, 327 insertions(+), 4 deletions(-) create mode 100644 arch/x86/kernel/cpu/resctrl/erdt.c diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index f3f7cb01d69d..97d210bd9bb5 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -515,7 +515,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 @@ -538,7 +538,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 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/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h index 575f8408a9e7..97c2f6bc7a5f 100644 --- a/arch/x86/include/asm/resctrl.h +++ b/arch/x86/include/asm/resctrl.h @@ -40,6 +40,8 @@ struct resctrl_pqr_state { u32 default_closid; }; =20 +bool erdt_enabled(void); + DECLARE_PER_CPU(struct resctrl_pqr_state, pqr_state); =20 extern bool rdt_alloc_capable; 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 7667cf7c4e94..90730f0851fa 100644 --- a/arch/x86/kernel/cpu/resctrl/core.c +++ b/arch/x86/kernel/cpu/resctrl/core.c @@ -1012,6 +1012,7 @@ static __init void check_quirks(void) =20 static __init bool get_rdt_resources(void) { + erdt_init(); rdt_alloc_capable =3D get_rdt_alloc_resources(); rdt_mon_capable =3D get_rdt_mon_resources(); =20 @@ -1113,7 +1114,7 @@ void resctrl_cpu_detect(struct cpuinfo_x86 *c) } } =20 -static int __init resctrl_arch_late_init(void) +static int __init __resctrl_arch_late_init(void) { struct rdt_resource *r; int state, ret, i; @@ -1156,6 +1157,15 @@ static int __init resctrl_arch_late_init(void) return 0; } =20 +static int __init resctrl_arch_late_init(void) +{ + int ret =3D __resctrl_arch_late_init(); + + if (ret) + erdt_exit(); + return ret; +} + late_initcall(resctrl_arch_late_init); =20 static void __exit resctrl_arch_exit(void) @@ -1165,6 +1175,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..51597a6e0058 --- /dev/null +++ b/arch/x86/kernel/cpu/resctrl/erdt.c @@ -0,0 +1,304 @@ +// 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 +#include +#include +#include "internal.h" + +enum erdt_mmio_type { + ERDT_MMIO_RMDD_CREG, + ERDT_MMIO_CMRC_BASE, + ERDT_MMIO_MAX +}; + +struct erdt_domain_info { + void __iomem *base[ERDT_MMIO_MAX]; + struct acpi_erdt_cmrc *cmrc; +}; + +static bool erdt_enabled_flag; + +static DEFINE_XARRAY(erdt_domain_xa); + +#define ERDT_VALID_VERSION 1 +#define RMDD_FLAG_CPU_DOMAIN BIT(0) + +static u32 valid_subtbl_mask; + +bool erdt_enabled(void) +{ + return erdt_enabled_flag; +} + +/** + * get_l3_cache_id_from_cacd - Resolve L3 cache ID from CACD subtable + * @cacd: Pointer to the ACPI ERDT CACD structure + * + * Parses the X2APIC ID list in the given CACD subtable to + * identify an online logical CPU and uses it to query the associated + * L3 cache ID. The first valid CPU found is used for this lookup. + * + * The L3 cache ID is used as a unique domain key for ERDT domain + * registration and lookup. + * + * Return: L3 cache ID for the first matching CPU, or -1 on failure. + */ +static __init int get_l3_cache_id_from_cacd(struct acpi_erdt_cacd *cacd) +{ + int num_ids, cpu, online_cpu =3D -1, cache_id =3D -1, tmp; + struct cacheinfo *ci; + + if (cacd->header.length < sizeof(*cacd) + sizeof(cacd->X2APICIDS[0])) { + pr_warn(FW_BUG "Invalid x2apicid CACD table\n"); + return -1; + } + + num_ids =3D (cacd->header.length - sizeof(*cacd)) / sizeof(cacd->X2APICID= S[0]); + + guard(cpus_read_lock)(); + + for (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 -1; + } + + if (!cpu_online(cpu)) + continue; + + tmp =3D get_cpu_cacheinfo_id(cpu, RESCTRL_L3_CACHE); + if (tmp =3D=3D -1) { + pr_warn(FW_BUG "Can not find L3 cache id for CPU%d\n", cpu); + return -1; + } + + if (cache_id =3D=3D -1) + cache_id =3D tmp; + + if (tmp !=3D cache_id) { + pr_warn(FW_BUG "CACD references multiple L3 cache instances\n"); + return -1; + } + online_cpu =3D cpu; + } + + if (online_cpu =3D=3D -1) + return -1; + + /* + * Check if CACD lists all CPUs in the LLC domain. + */ + ci =3D get_cpu_cacheinfo_level(online_cpu, RESCTRL_L3_CACHE); + if (!ci || num_ids !=3D cpumask_weight(&ci->shared_cpu_map)) { + pr_warn(FW_BUG "CACD does not list all the CPUs in L3 domain\n"); + return -1; + } + + return cache_id; +} + +static void __iomem *erdt_ioremap_checked(phys_addr_t base, u32 size, cons= t char *desc) +{ + void __iomem *addr =3D ioremap(base, size << 12); + + if (!addr) { + pr_err("ERDT: Failed to map %s at phys addr %#llx (size: %u pages)\n", + desc, (unsigned long long)base, size); + } + return addr; +} + +static void erdt_iounmap_domain(struct erdt_domain_info *domain) +{ + for (int i =3D 0; i < ERDT_MMIO_MAX; 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); +} + +static __init bool cacd_init(struct erdt_domain_info *d, struct acpi_subtb= l_hdr_16 *subtbl, + int *l3_cache_id) +{ + *l3_cache_id =3D get_l3_cache_id_from_cacd((struct acpi_erdt_cacd *)subtb= l); + + return *l3_cache_id !=3D -1; +} + +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(struct acpi_erdt_rmdd *rmdd, struct acpi_s= ubtbl_hdr_16 *subtbl) +{ + void *rmdd_end =3D (void *)rmdd + rmdd->header.length; + + if (subtbl->length < sizeof(*subtbl)) + return false; + + if ((void *)subtbl + sizeof(*subtbl) > rmdd_end) + return false; + + if ((void *)subtbl + subtbl->length > rmdd_end) + return false; + + return true; +} + +static __init bool parse_rmdd_entry(struct acpi_subtbl_hdr_16 *rmdd_hdr) +{ + struct erdt_domain_info *domain_info; + struct acpi_subtbl_hdr_16 *subtbl; + struct acpi_erdt_rmdd *rmdd; + int l3_cache_id =3D -1; + u32 subtbl_mask =3D 0; + + if (rmdd_hdr->length < sizeof(*rmdd)) { + pr_info(FW_BUG "Invalid RMDD length %u\n", rmdd_hdr->length); + return false; + } + + rmdd =3D (struct acpi_erdt_rmdd *)rmdd_hdr; + + /* Quietly ignore non-CPU-based L3 domains */ + if (!(rmdd->flags & RMDD_FLAG_CPU_DOMAIN)) + return true; + + domain_info =3D kzalloc(sizeof(*domain_info), GFP_KERNEL); + if (!domain_info) + return false; + + domain_info->base[ERDT_MMIO_RMDD_CREG] =3D + erdt_ioremap_checked(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(rmdd, subtbl); + subtbl =3D next_subtbl(subtbl)) { + switch (subtbl->type) { + case ACPI_ERDT_TYPE_CACD: + if (cacd_init(domain_info, subtbl, &l3_cache_id)) + subtbl_mask |=3D BIT(ACPI_ERDT_TYPE_CACD); + break; + default: + break; + } + } + + if (l3_cache_id =3D=3D -1) { + pr_info("ERDT: Failed to resolve L3 cache ID for RMDD domain %d\n", + rmdd->domain_id); + + goto cleanup; + } + + /* Require all RMDDs to support same set of sub-tables */ + if (!valid_subtbl_mask) { + valid_subtbl_mask =3D subtbl_mask; + } else if (subtbl_mask !=3D valid_subtbl_mask) { + pr_info(FW_BUG "Mismatch domain\n"); + goto cleanup; + } + + if (xa_insert(&erdt_domain_xa, l3_cache_id, domain_info, GFP_KERNEL)) { + pr_info("ERDT: Failed to store domain info for RMDD domain %d\n", + rmdd->domain_id); + goto cleanup; + } + + return true; + +cleanup: + cleanup_one_domain(domain_info); + return false; +} + +static void erdt_cleanup(void) +{ + struct erdt_domain_info *d; + unsigned long index; + + xa_for_each(&erdt_domain_xa, index, d) + cleanup_one_domain(d); + xa_destroy(&erdt_domain_xa); +} + +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; + void *table_end; + + if (erdt->header.revision !=3D ERDT_VALID_VERSION) { + pr_info("Unknown ERDT table revision %d\n", erdt->header.revision); + return -EINVAL; + } + + if (erdt->header.length < sizeof(*erdt)) { + pr_info(FW_BUG "ERDT: Invalid table length %u\n", erdt->header.length); + return -EINVAL; + } + + subtbl =3D (void *)erdt + sizeof(struct acpi_table_erdt); + table_end =3D (void *)erdt + erdt->header.length; + + while ((void *)subtbl + sizeof(*subtbl) <=3D table_end) { + if (subtbl->length < sizeof(*subtbl) || + (void *)subtbl + subtbl->length > table_end) { + pr_info("ERDT: Invalid subtable length\n"); + goto cleanup; + } + + if (subtbl->type =3D=3D ACPI_ERDT_TYPE_RMDD) + if (!parse_rmdd_entry(subtbl)) + goto cleanup; + + subtbl =3D (void *)subtbl + subtbl->length; + } + + erdt_enabled_flag =3D true; + + return 0; + +cleanup: + erdt_cleanup(); + return -EINVAL; +} + +int __init erdt_init(void) +{ + return acpi_table_parse(ACPI_SIG_ERDT, enumerate_erdt_table); +} + +void erdt_exit(void) +{ + erdt_cleanup(); +} diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/r= esctrl/internal.h index e3cfa0c10e92..9c59bd5e028e 100644 --- a/arch/x86/kernel/cpu/resctrl/internal.h +++ b/arch/x86/kernel/cpu/resctrl/internal.h @@ -253,4 +253,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 +int erdt_init(void); +void erdt_exit(void); + #endif /* _ASM_X86_RESCTRL_INTERNAL_H */ 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 Mon Jun 8 06:35:56 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (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 497BB22068D for ; Sat, 6 Jun 2026 02:43:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780713814; cv=none; b=kREfiGRdLNMlnitdaLHmivhKvyrAR3FKCBOF7UasJXepmwdODsV1yXhY41h43vSL8Cf/yB++rqn6cU9x1wa6zNQBTbCaOHrmFR7ROK8BPga2XwunSpG2hwfvWs65HI/EfpPAsrgFEMnwhNkZIfSrv0YqCWwmFAWHUGDQhmVmRzc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780713814; c=relaxed/simple; bh=YMgY9dYtJ0jgo09Am5FJC7XwC9n+mBt9lyZ4IoETPKs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=PBSbJML+IfuEua82fCQmOmEbYE3I8ygQypcYWoF2bXYi3TfUHAZXyvaFID0pU0jcGerrkr/UwJTEFRGUo9BK4Y1KmGaiY+AtMRgtGAZbNugWsEZfLqqPCDzOales4ldb2FRYfSPN3ZYglUs0ITNkDx4xWCJRLhnFSm4mCRAlxvE= 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=JWoZ3Ih6; arc=none smtp.client-ip=198.175.65.19 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="JWoZ3Ih6" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1780713813; x=1812249813; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=YMgY9dYtJ0jgo09Am5FJC7XwC9n+mBt9lyZ4IoETPKs=; b=JWoZ3Ih6wtI+yYNgEDiClSCMSdBgg5gZJGz6e0+NrWWdV8FUFjkTk6LU plJOYHbcchq0HPJGo+CV9FbPsb74fSrS6WPUc9lu4U3RXCPvw7ewUSG1S u28CCk2pxARFh1AQ95l7Y8TLjUOPo8FdkEXcGVpXnUEftRlgn/k/hAEQO Svi/HWD3e7W3UFlyL8vcvz30WgyaRFTDAj6TcFwiCpkY5ic30THiGhNSE G20WmEZRASH3N1hsUec20hnBUJVE0g8vJeK9KS9MeXBJlN5kDD06MadWY Kv4StmSeGc/qBwPX8r0hRVhwY2gpy79++5ruXwTH+lRfSkbz21nwlMsI+ g==; X-CSE-ConnectionGUID: kIIuHq4wR8C3dj4DIIY7uA== X-CSE-MsgGUID: bGbOwFihQCCFR68BJNXIEQ== X-IronPort-AV: E=McAfee;i="6800,10657,11808"; a="81523438" X-IronPort-AV: E=Sophos;i="6.24,189,1774335600"; d="scan'208";a="81523438" Received: from orviesa008.jf.intel.com ([10.64.159.148]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Jun 2026 19:43:33 -0700 X-CSE-ConnectionGUID: SvR8SV6sQU6WqbCOmXZvKQ== X-CSE-MsgGUID: S/brv2K+StSAXFHjg7sBrA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.24,189,1774335600"; d="scan'208";a="244844406" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by orviesa008.jf.intel.com with ESMTP; 05 Jun 2026 19:43:29 -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 v3 2/6] x86/resctrl: Parse ACPI CMRC table Date: Sat, 6 Jun 2026 10:33:40 +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" 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 an RMD. Parse each CMRC sub-table, ioremap its register window, and save the CMRC pointer in the corresponding ERDT domain entry so that later monitoring code can read the counters via MMIO. Suggested-by: Tony Luck Signed-off-by: Chen Yu --- v2->v3: Make the macros tabular format. (Thomas Gleixner) --- arch/x86/kernel/cpu/resctrl/erdt.c | 44 ++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/resctrl/erdt.c b/arch/x86/kernel/cpu/resct= rl/erdt.c index 51597a6e0058..8d0b9f4ad6d8 100644 --- a/arch/x86/kernel/cpu/resctrl/erdt.c +++ b/arch/x86/kernel/cpu/resctrl/erdt.c @@ -33,8 +33,9 @@ static bool erdt_enabled_flag; =20 static DEFINE_XARRAY(erdt_domain_xa); =20 -#define ERDT_VALID_VERSION 1 -#define RMDD_FLAG_CPU_DOMAIN BIT(0) +#define ERDT_VALID_VERSION 1 +#define CMRC_VALID_INDEX_FUNC_VERSION 1 +#define RMDD_FLAG_CPU_DOMAIN BIT(0) =20 static u32 valid_subtbl_mask; =20 @@ -136,6 +137,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 @@ -147,6 +149,40 @@ static __init bool cacd_init(struct erdt_domain_info *= d, struct acpi_subtbl_hdr_ return *l3_cache_id !=3D -1; } =20 +static __init bool cmrc_init(struct erdt_domain_info *d, struct acpi_subtb= l_hdr_16 *subtbl) +{ + struct acpi_erdt_cmrc *cmrc =3D (struct acpi_erdt_cmrc *)subtbl; + + if (subtbl->length < sizeof(*cmrc)) { + pr_warn(FW_BUG "Truncated CMRC subtable\n"); + return false; + } + + if (cmrc->index_fn !=3D CMRC_VALID_INDEX_FUNC_VERSION) { + pr_info("Unknown CMRC index function %d\n", cmrc->index_fn); + return false; + } + + if (!cmrc->clump_size) { + pr_warn(FW_BUG "CMRC clump_size is zero\n"); + return false; + } + + d->base[ERDT_MMIO_CMRC_BASE] =3D erdt_ioremap_checked(cmrc->cmt_reg_base, + cmrc->cmt_reg_size, "CMRC base"); + if (!d->base[ERDT_MMIO_CMRC_BASE]) + return false; + + d->cmrc =3D kmemdup(cmrc, subtbl->length, GFP_KERNEL); + if (!d->cmrc) { + iounmap(d->base[ERDT_MMIO_CMRC_BASE]); + d->base[ERDT_MMIO_CMRC_BASE] =3D NULL; + return false; + } + + return true; +} + static inline struct acpi_subtbl_hdr_16 *rmdd_subtbl(struct acpi_erdt_rmdd= *rmdd) { return (void *)rmdd + sizeof(*rmdd); @@ -208,6 +244,10 @@ static __init bool parse_rmdd_entry(struct acpi_subtbl= _hdr_16 *rmdd_hdr) if (cacd_init(domain_info, subtbl, &l3_cache_id)) subtbl_mask |=3D BIT(ACPI_ERDT_TYPE_CACD); break; + case ACPI_ERDT_TYPE_CMRC: + if (cmrc_init(domain_info, subtbl)) + subtbl_mask |=3D BIT(ACPI_ERDT_TYPE_CMRC); + break; default: break; } --=20 2.25.1 From nobody Mon Jun 8 06:35:56 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (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 D5D686DCE1 for ; Sat, 6 Jun 2026 02:45:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780713950; cv=none; b=qM4g+/2pNkNLWgA2r1wbOtr8AMuU6clYtTbHEwdvOOskyG3BT0gzgfxOVJbBX9+atOWM6IwNfDFIOYcIj+Tvcppf7yfiqGb1JLE0mvAZzr24LHPRbu3OwOlwlJ3TytCdiB3hPyKUBdUib5YS3EQr54dg7yh9gCjwFQ+NKi5wB3w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780713950; c=relaxed/simple; bh=Ol3GK2bhNyW7W2cSLGJsd4SLc+O/dkv6xNklq+RMDgA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=puu+1Dn8+yo72Cuu9xkEupguPJhcna2lhmtyEszITLimjSTU/LAzNcrRW3FHNS5Koz/TprxWjryFjkB5QScoksvgYb6hyVv/SQwWCcLzvu7j0oQzlUyCQ4PvYCEtrJzpSEvDgX5azfkJ8nnO4wWfJrzRBZHs8F54n1XPxWOjhFI= 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=E1epwxhN; arc=none smtp.client-ip=198.175.65.19 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="E1epwxhN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1780713949; x=1812249949; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Ol3GK2bhNyW7W2cSLGJsd4SLc+O/dkv6xNklq+RMDgA=; b=E1epwxhNZJzWH8ckv5mJA/43YnWO9cnngYMJu6lcIbvfybqYKsNrUt/M D0vsa7tKXSZnm0kyWv6hAfJLgj9gLFgAWCBw/gLch1v1PGi6gGrabDVJd rDuvWVundraia6zVkDXl6ha7AWxAi9tLovDlBafEJgXCBZ71Z0ytcVLJj Kgd4Nbog2AKcqtpP5SRNhlE7j5chDM+IMdrU6reNWMmyKw/Qh5VvuROXt rTZDkH0Eq7188KOIMTXunhvmmy0ufu9btYs7GzROUTDHgBt4NAt31TTK/ /DG/fzx4E2B8h7RkotszG4udgHK04+CEvheJp/+RFoCSLBaBQcqrLqFxs g==; X-CSE-ConnectionGUID: 2lkWDkGDRyqXOcRNbz6CyA== X-CSE-MsgGUID: RCAtRoYiQVCYaJRoYRuEnQ== X-IronPort-AV: E=McAfee;i="6800,10657,11808"; a="81523482" X-IronPort-AV: E=Sophos;i="6.24,189,1774335600"; d="scan'208";a="81523482" Received: from orviesa008.jf.intel.com ([10.64.159.148]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Jun 2026 19:45:48 -0700 X-CSE-ConnectionGUID: v5mjDpYVSWSLKpFAopmoMg== X-CSE-MsgGUID: h7mTrxW+RVi0tftw+C6JRA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.24,189,1774335600"; d="scan'208";a="244844682" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by orviesa008.jf.intel.com with ESMTP; 05 Jun 2026 19:45:44 -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 v3 3/6] x86/resctrl: Rename prev_msr to prev_mon_val Date: Sat, 6 Jun 2026 10:35:55 +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" Rename the prev_msr field in struct arch_mbm_state to prev_mon_val. With ERDT, the previous monitor value may come from an MMIO register rather than from an MSR, so the "msr" suffix is no longer accurate. The new name describes the field by its meaning (the previous monitor value) instead of by the access method. This is preparation for ERDT support, which reads monitoring counters via MMIO. No functional change. Co-developed-by: Anil S Keshavamurthy Signed-off-by: Anil S Keshavamurthy Signed-off-by: Chen Yu --- arch/x86/kernel/cpu/resctrl/internal.h | 8 +++---- arch/x86/kernel/cpu/resctrl/monitor.c | 30 +++++++++++++------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/r= esctrl/internal.h index 9c59bd5e028e..97065dc6e14f 100644 --- a/arch/x86/kernel/cpu/resctrl/internal.h +++ b/arch/x86/kernel/cpu/resctrl/internal.h @@ -31,13 +31,13 @@ /** * struct arch_mbm_state - values used to compute resctrl_arch_rmid_read()s * return value. - * @chunks: Total data moved (multiply by rdt_group.mon_scale to get bytes) - * @prev_msr: Value of IA32_QM_CTR last time it was read for the RMID used= to - * find this struct. + * @chunks: Total data moved (multiply by rdt_group.mon_scale to get byte= s) + * @prev_mon_val: Previous monitor counter value for the RMID used to + * find this struct. */ struct arch_mbm_state { u64 chunks; - u64 prev_msr; + u64 prev_mon_val; }; =20 /* Setting bit 0 in L3_QOS_EXT_CFG enables the ABMC feature. */ diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/re= sctrl/monitor.c index 9bd87bae4983..991f0a796551 100644 --- a/arch/x86/kernel/cpu/resctrl/monitor.c +++ b/arch/x86/kernel/cpu/resctrl/monitor.c @@ -186,7 +186,7 @@ void resctrl_arch_reset_rmid(struct rdt_resource *r, st= ruct rdt_l3_mon_domain *d =20 prmid =3D logical_rmid_to_physical_rmid(cpu, rmid); /* Record any initial, non-zero count value. */ - __rmid_read_phys(prmid, eventid, &am->prev_msr); + __rmid_read_phys(prmid, eventid, &am->prev_mon_val); } } =20 @@ -209,16 +209,16 @@ void resctrl_arch_reset_rmid_all(struct rdt_resource = *r, struct rdt_l3_mon_domai } } =20 -static u64 mbm_overflow_count(u64 prev_msr, u64 cur_msr, unsigned int widt= h) +static u64 mbm_overflow_count(u64 prev_val, u64 cur_val, unsigned int widt= h) { u64 shift =3D 64 - width, chunks; =20 - chunks =3D (cur_msr << shift) - (prev_msr << shift); + chunks =3D (cur_val << shift) - (prev_val << shift); return chunks >> shift; } =20 static u64 get_corrected_val(struct rdt_resource *r, struct rdt_l3_mon_dom= ain *d, - u32 rmid, enum resctrl_event_id eventid, u64 msr_val) + u32 rmid, enum resctrl_event_id eventid, u64 mon_val) { struct rdt_hw_l3_mon_domain *hw_dom =3D resctrl_to_arch_mon_dom(d); struct rdt_hw_resource *hw_res =3D resctrl_to_arch_res(r); @@ -227,12 +227,12 @@ static u64 get_corrected_val(struct rdt_resource *r, = struct rdt_l3_mon_domain *d =20 am =3D get_arch_mbm_state(hw_dom, rmid, eventid); if (am) { - am->chunks +=3D mbm_overflow_count(am->prev_msr, msr_val, + am->chunks +=3D mbm_overflow_count(am->prev_mon_val, mon_val, hw_res->mbm_width); chunks =3D get_corrected_mbm_count(rmid, am->chunks); - am->prev_msr =3D msr_val; + am->prev_mon_val =3D mon_val; } else { - chunks =3D msr_val; + chunks =3D mon_val; } =20 return chunks * hw_res->mon_scale; @@ -245,7 +245,7 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, stru= ct rdt_domain_hdr *hdr, struct rdt_hw_l3_mon_domain *hw_dom; struct rdt_l3_mon_domain *d; struct arch_mbm_state *am; - u64 msr_val; + u64 mon_val; u32 prmid; int cpu; int ret; @@ -262,14 +262,14 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, st= ruct rdt_domain_hdr *hdr, hw_dom =3D resctrl_to_arch_mon_dom(d); cpu =3D cpumask_any(&hdr->cpu_mask); prmid =3D logical_rmid_to_physical_rmid(cpu, rmid); - ret =3D __rmid_read_phys(prmid, eventid, &msr_val); + ret =3D __rmid_read_phys(prmid, eventid, &mon_val); =20 if (!ret) { - *val =3D get_corrected_val(r, d, rmid, eventid, msr_val); + *val =3D get_corrected_val(r, d, rmid, eventid, mon_val); } else if (ret =3D=3D -EINVAL) { am =3D get_arch_mbm_state(hw_dom, rmid, eventid); if (am) - am->prev_msr =3D 0; + am->prev_mon_val =3D 0; } =20 return ret; @@ -324,7 +324,7 @@ void resctrl_arch_reset_cntr(struct rdt_resource *r, st= ruct rdt_l3_mon_domain *d memset(am, 0, sizeof(*am)); =20 /* Record any initial, non-zero count value. */ - __cntr_id_read(cntr_id, &am->prev_msr); + __cntr_id_read(cntr_id, &am->prev_mon_val); } } =20 @@ -332,14 +332,14 @@ int resctrl_arch_cntr_read(struct rdt_resource *r, st= ruct rdt_l3_mon_domain *d, u32 unused, u32 rmid, int cntr_id, enum resctrl_event_id eventid, u64 *val) { - u64 msr_val; + u64 mon_val; int ret; =20 - ret =3D __cntr_id_read(cntr_id, &msr_val); + ret =3D __cntr_id_read(cntr_id, &mon_val); if (ret) return ret; =20 - *val =3D get_corrected_val(r, d, rmid, eventid, msr_val); + *val =3D get_corrected_val(r, d, rmid, eventid, mon_val); =20 return 0; } --=20 2.25.1 From nobody Mon Jun 8 06:35:56 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 CFEFC27453 for ; Sat, 6 Jun 2026 02:47:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780714078; cv=none; b=EwlSOt4P6B2BSx4VThl6CqTb8Lq0JT8BijwpoIHccRhGJ8kQZzgZ1nQl4ojujzdk8bRzi1+sKM5h2lIVKnNSJfQFsTAT7P6+yFkD7SM+lMPbGfYSv3KGefGEyCt3e5r4ZvlE7WWoOjTsmd54NmlrOPigMzQJkBOByA45NnopoCo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780714078; c=relaxed/simple; bh=DXjWYUqL/p3I6jaimKyFhAfO3bSHjncfHRSrw5AoCpg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=NjbC1NX8bQAqKN5/idlpQK7VAO8nlkzNBVPSQgKosaT0FgYj+vb/W9YJhkaCcw/p3bIzGPj6zJZs300o+g8z/rpSHLc2iGHeOGEzhHYsnbRYLhhBmccscC2OGtSEvqUcgpYkPNpyroGm+fzytcFugzC0Ouenm1/ZMZOJzz+pTmA= 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=VZf0BOtZ; arc=none smtp.client-ip=198.175.65.15 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="VZf0BOtZ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1780714077; x=1812250077; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=DXjWYUqL/p3I6jaimKyFhAfO3bSHjncfHRSrw5AoCpg=; b=VZf0BOtZHiEjQWACpDHRfvdqFVvfck7dL788qy03QcMYdYeK97nDOj3J 60ThL82Xhg+tF3d9ZGsEyHp4jbatt5NdptapfB/PuRopgJmzfn5KQzGOr HA8WLh4bs6+8PSpUdyZWCa+5BSpnn+T38LiHtDiDiU8svH/zW5GUcRL7n 1xljrQaKKKXFhuwH4iTlctK0nJDFEOvIbZ5tH1T37U1NFIIroeYrqHSDJ WRnLbHl9ZPjsMSl59JWZJAjy6KuC03q+Bj3+cqjJ56yZB68lL3dg5Q3ca xiFwH7KU/ll4pSVVJhoBapxpdmGrNnZlB1I1qVDFU4Wru6EO1sHTArsFw Q==; X-CSE-ConnectionGUID: YMex1cTHTBqKR7vmgjbwbA== X-CSE-MsgGUID: 0E4P1w9TS1myto6C/PzwGg== X-IronPort-AV: E=McAfee;i="6800,10657,11808"; a="85167147" X-IronPort-AV: E=Sophos;i="6.24,189,1774335600"; d="scan'208";a="85167147" Received: from fmviesa002.fm.intel.com ([10.60.135.142]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Jun 2026 19:47:56 -0700 X-CSE-ConnectionGUID: pB749uvTSg+IJFSd4SrukA== X-CSE-MsgGUID: m/Omie4RTbmxwfNm9J0+qQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.24,189,1774335600"; d="scan'208";a="268690916" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by fmviesa002.fm.intel.com with ESMTP; 05 Jun 2026 19:47:52 -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 v3 4/6] x86/resctrl: Refactor the monitor read function Date: Sat, 6 Jun 2026 10:38:03 +0800 Message-Id: <290192b9586f642a37618bb38fc055047d9dd688.1780710620.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" Split the monitor read helper into an L3 read path and an AET (Intel Application 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 added in a later patch. No functional change. Signed-off-by: Chen Yu --- arch/x86/kernel/cpu/resctrl/monitor.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/re= sctrl/monitor.c index 991f0a796551..1e81b3c33843 100644 --- a/arch/x86/kernel/cpu/resctrl/monitor.c +++ b/arch/x86/kernel/cpu/resctrl/monitor.c @@ -238,9 +238,9 @@ 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_domain_hdr *hdr, u32 rmid, + enum resctrl_event_id eventid, u64 *val, + struct rdt_resource *r) { struct rdt_hw_l3_mon_domain *hw_dom; struct rdt_l3_mon_domain *d; @@ -250,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 @@ -275,6 +270,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(hdr, rmid, eventid, val, r); + 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) { u64 msr_val; --=20 2.25.1 From nobody Mon Jun 8 06:35:56 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 651D027453 for ; Sat, 6 Jun 2026 02:48:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780714089; cv=none; b=jbAVIvJiiWWiC5A83M9+pfbavpC/7qwr9cizf0luUHAvlS3k8zDdpfVekv1EvBZKsZkQuVLipb32+ernbz+w+YxOv1Qe1bbT8Y3zdXv+NRGzY7AnDIye8qe/7MkgBgm+R1doZxFYzfs1TIGKgI+HBky3qfakPa8XmLy2kb4ez0s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780714089; c=relaxed/simple; bh=wzycBpk0BYouCw7/j6yjLbFp+R+53GVLGnC97Isy0Hg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=IXPif9VdEaeek71LP04XC9rvqhc3DaO3qgjXK2j2R9y5DD2QBNDe/MNAb2yP1gGIsheK9L3slBsmL5HxCSI+tfydHWtGhyEgt1nKHFICTPU54cHUxqarlFdr/W3v94XnmD+h0USRlNkrDrujAngWbGyQync8Zd0G8lkU54WqAh8= 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=eNFovORJ; arc=none smtp.client-ip=198.175.65.15 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="eNFovORJ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1780714088; x=1812250088; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=wzycBpk0BYouCw7/j6yjLbFp+R+53GVLGnC97Isy0Hg=; b=eNFovORJMPaT/J5KRajXGo2tmWlpSMrmcH1MAROcqGYYGgR3aEVtowHr TRT/yzpHZSJfR4euzr4FnXmzIErxE9loOn4cHXfbiB15S/kn/+ZrQpThI jz17m4OxWHuMPlvJXVOmTbzfJSTboqMggThGD2n383u3tQtfLtdzi10bl K9Op3gzbDWG5XbqAdtlp9QahPIyuNvWY5Ag+4p8LnrSvqb1ib7//AX8IG c+axRkE2HdYor9bz0DvfJLmmAru5U6zu2m/ZM4pv1MOXhl0mp62OJuKBf 5ZVmHylgmQ/znjMCRzZDRBz1S3Nyy3fafOU9YEvKlszfyKPy1eWxNdDq+ Q==; X-CSE-ConnectionGUID: xzUbmiwlQHmPDTJKIBbfQA== X-CSE-MsgGUID: X1u3HkV7TL2/gusfKH6jXw== X-IronPort-AV: E=McAfee;i="6800,10657,11808"; a="85167163" X-IronPort-AV: E=Sophos;i="6.24,189,1774335600"; d="scan'208";a="85167163" Received: from fmviesa002.fm.intel.com ([10.60.135.142]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Jun 2026 19:48:07 -0700 X-CSE-ConnectionGUID: A8w5I5u+SHaInGhZlhRx8w== X-CSE-MsgGUID: wH7zkJE7QJ2TQk/Xr8sA1Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.24,189,1774335600"; d="scan'208";a="268690967" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by fmviesa002.fm.intel.com with ESMTP; 05 Jun 2026 19:48:02 -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 v3 5/6] fs/resctrl: Do not invoke smp_processor_id() in preemptible context Date: Sat, 6 Jun 2026 10:38:13 +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" From: Tony Luck __l3_mon_event_count() and __l3_mon_event_count_sum() call smp_processor_id() to obtain the current CPU. However, some monitor events can be read from any CPU in task context via mon_event_count(); in that case the calling context is preemptible and smp_processor_id() triggers a debug warning. Fix this by skipping the current-CPU lookup when the event's any_cpu flag is set, since such events do not need to run on a specific CPU. Signed-off-by: Tony Luck Signed-off-by: Chen Yu --- fs/resctrl/monitor.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c index 9fd901c78dc6..3e8995e3380e 100644 --- a/fs/resctrl/monitor.c +++ b/fs/resctrl/monitor.c @@ -417,9 +417,36 @@ 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; @@ -452,9 +479,6 @@ static int __l3_mon_event_count(struct rdtgroup *rdtgrp= , 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)) - 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); @@ -472,7 +496,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; @@ -490,10 +513,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)) - return -EINVAL; - /* * Legacy files must report the sum of an event across all * domains that share the same L3 cache instance. @@ -524,7 +543,9 @@ static int __mon_event_count(struct rdtgroup *rdtgrp, s= truct rmid_read *rr) { switch (rr->r->rid) { case RDT_RESOURCE_L3: - WARN_ON_ONCE(rr->evt->any_cpu); + if (!cpu_on_correct_domain(rr)) + return -EINVAL; + if (rr->hdr) return __l3_mon_event_count(rdtgrp, rr); else --=20 2.25.1 From nobody Mon Jun 8 06:35:56 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.20]) (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 017E2246762 for ; Sat, 6 Jun 2026 02:48:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.20 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780714099; cv=none; b=qT8G2iUSv3wWVyYyavDp+0XGz8hHAX118ksBRlSa9iovRWFf1/71kNPoF6Y23G/ZnDeSGziQf7erpPvYVRGrRQNRD4NzOcl4STSyt3DFVMEApbQiDBOaG6iPOhx+aM2bfc4WwZZjXKgIz0ZFhwu4qCudGUHl0BAgf9k2vbZKrKw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780714099; c=relaxed/simple; bh=LDJxzaRx9wJxiTzVJp+ZZn6mvFRGGiMehWQ8GkJw9EY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=DlG/tQS96KW01sXN+lDiB86LMYqROydcbSEQ4IY7ciKLkGySobeUag6hcZ+ZQcbtt7IEoVjw3288OpksoWPRJbU85rO87tDvry2qG8hNpdTy9KBacpjCgdFfpIhhtJwxsRfBFNE1AaBiF2p4ssByq5I+SAGv2UYy+/T+um0J0hc= 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=IYAOV4+N; arc=none smtp.client-ip=198.175.65.20 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="IYAOV4+N" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1780714096; x=1812250096; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=LDJxzaRx9wJxiTzVJp+ZZn6mvFRGGiMehWQ8GkJw9EY=; b=IYAOV4+Ni/G40ng6jOkV0srccMTaCEyWPGTz5cYnc9Rw0l12FKbhabOO wY+kPOmXMiytP/fcxQDNQqyOz1/udWJc2r1Z1JKbiqy4MKtsnWtV4fOU0 cAV6wU8axsfTZtIp5jshUGBmavKRlwoZ32MEPDsu44h1IJGmtQiG2XEMf AUeLhDKz1SjSQkVSB1UQGx6qZxHXYO+k8ygY7MUUIyhK+/mgwnPHv6biF 9FCo0i6AF4/lc5TP6DV60EsXQvxS/Pu6jfB037FTAnw2+0rRZJy+MVQkc CmiqT+V31Gs6dLbYjtaEzXTcC9d9e6WXW7G7caE/iiPH/zgoYw7oA01JR g==; X-CSE-ConnectionGUID: grfndu21QeaULSi1cQu7WQ== X-CSE-MsgGUID: /4DQULiGSkGxvhNt+nByEQ== X-IronPort-AV: E=McAfee;i="6800,10657,11808"; a="81293475" X-IronPort-AV: E=Sophos;i="6.24,189,1774335600"; d="scan'208";a="81293475" Received: from orviesa006.jf.intel.com ([10.64.159.146]) by orvoesa112.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Jun 2026 19:48:16 -0700 X-CSE-ConnectionGUID: IImQI0WqS/eW2e4ftl5hQA== X-CSE-MsgGUID: BA3j5xaITZKk9UjH5C2peA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.24,189,1774335600"; d="scan'208";a="243901366" Received: from chenyu-dev.sh.intel.com ([10.239.62.107]) by orviesa006.jf.intel.com with ESMTP; 05 Jun 2026 19:48:12 -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 v3 6/6] x86/resctrl: Add support for L3 occupancy monitoring via RMID MMIO read Date: Sat, 6 Jun 2026 10:38:23 +0800 Message-Id: <8d3ae8b7f66f4ed2765cbe9c18d1d831ed28b894.1780710620.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) 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 | 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 { }; =20 bool erdt_enabled(void); +struct rdt_domain_hdr; +int erdt_mon_read(struct rdt_domain_hdr *hdr, int ev_id, int rmid, u64 *va= l); =20 DECLARE_PER_CPU(struct resctrl_pqr_state, pqr_state); =20 diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resct= rl/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 =3D false; =20 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 =3D 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/resct= rl/erdt.c index 8d0b9f4ad6d8..b000eaccc02e 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); =20 #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) =20 static u32 valid_subtbl_mask; @@ -44,6 +45,94 @@ bool erdt_enabled(void) return erdt_enabled_flag; } =20 +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 =3D cmrc->clump_size; + stride_size =3D cmrc->clump_stride; + + /* + * MMIO_ADDRESS_for_RMID# =3D CMRC Base + + * (RMID / ClumpSize) * Stride + + * (RMID % ClumpSize) * 8 + */ + vaddr =3D 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, u6= 4 *val) +{ + struct acpi_erdt_cmrc *cmrc; + void __iomem *vaddr; + u64 l3_cmt_count; + u32 offset; + + cmrc =3D d->cmrc; + if (!cmrc) + return -EIO; + + offset =3D (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 =3D cmrc_index_function_1(d, cmrc, rmid); + + l3_cmt_count =3D readq(vaddr); + if (l3_cmt_count & UNAVAILABLE_COUNTER) + return -EINVAL; + + *val =3D 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 *va= l) +{ + struct erdt_domain_info *d; + + d =3D xa_load(&erdt_domain_xa, hdr->id); + if (!d) + return -EIO; + + if (ev_id =3D=3D 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/re= sctrl/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, str= uct rdt_domain_hdr *hdr, =20 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 =3D=3D 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); --=20 2.25.1