From nobody Mon Feb 9 13:37:12 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.17]) (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 5535223E226 for ; Mon, 3 Mar 2025 23:34:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.17 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741044894; cv=none; b=Luk34Ch/S4mOZf8O1u1e50aPzjKIt77jJOt3/E1IlO3ngISdktUJLOwcWhXSFxmUKTx9904BwvuotiOR72+2TaP/xmZLAhwEovJEdSDO3vdVzL6/XNz1jeJdaQlCqUuvNCwARHLO4nbMfoAf/7UeD+YC95hQBzJkBKP/U7CfvQ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741044894; c=relaxed/simple; bh=bl4AE5B4dRHgkyzVt059Ks754gGBJoIMCieRISa5Q+Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uez71tHPdPOmFBRnM95tYRwAtef228PP+ES0JfkuC1ltC16wJNN5kp6XQ6/Z+udS0nQGm8WhDyyEo4oaflxy2Ab+hCWI6J4r75wmoDNY7feXd+30HiJQ1nX9l8IeNK7+R8zZBuglmrYQhTqX3ysBr2Xk6Cp0H9saAxALWG1/kmE= 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=OwX2e6vf; arc=none smtp.client-ip=192.198.163.17 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="OwX2e6vf" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1741044892; x=1772580892; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=bl4AE5B4dRHgkyzVt059Ks754gGBJoIMCieRISa5Q+Q=; b=OwX2e6vf50ow3JBeY654ntUlmfMng2kNuZxxuNbs9SN+uqutJ94RAgjl L8O5mPQdf0I28eUHeRCuJazlSMr71hsnf8kCGMll10yQwTKv3a3Z8xUEC jTs10RnfOA5hzAPcj4DLDsiHlvlMTqjKu8HDiG+rgFeBf7g0mChTJFhqG k1UdkjCKjNj/llLs8yKDEZgzmrHX8E5Wj+JT2kT4PHYBBzSPY+kQy/pVi V0YixyPj5FpOPUoFwE7wC9B1awT3HLwnT1wks6djES0zrR4Uy2LqmPc7B MmUMJcVTv28jTVBf7fjw+16wuWJw+kI3TP2wbmE2eL8Z/k6VtAvibmTtz w==; X-CSE-ConnectionGUID: R/s3OyOnQiidoZ1ZneFCiQ== X-CSE-MsgGUID: 4MtnbGL3Q3qKOaVzlDSc8Q== X-IronPort-AV: E=McAfee;i="6700,10204,11362"; a="41835949" X-IronPort-AV: E=Sophos;i="6.13,330,1732608000"; d="scan'208";a="41835949" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by fmvoesa111.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Mar 2025 15:34:47 -0800 X-CSE-ConnectionGUID: vck0jeC+QSSNw+vCsiPgqQ== X-CSE-MsgGUID: V7CDaGh5SsOpEu+d/8Hhcw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.13,330,1732608000"; d="scan'208";a="117982294" Received: from agluck-desk3.sc.intel.com ([172.25.222.70]) by fmviesa006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Mar 2025 15:33:52 -0800 From: Tony Luck To: Fenghua Yu , Reinette Chatre , Maciej Wieczor-Retman , Peter Newman , James Morse , Babu Moger , Drew Fustini , Dave Martin Cc: linux-kernel@vger.kernel.org, patches@lists.linux.dev, Tony Luck Subject: [RFC PATCH 08/17] x86/resctrl: Add initialization hook for Intel PMT events Date: Mon, 3 Mar 2025 15:33:28 -0800 Message-ID: <20250303233340.333743-9-tony.luck@intel.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250303233340.333743-1-tony.luck@intel.com> References: <20250303233340.333743-1-tony.luck@intel.com> 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" Call the OOBMSM discovery code to find out if there are any event groups that match unique identifiers understood by resctrl. Note that initiialzation must happen in two phases because the OOBMSM VSEC discovery process is not complete at resctrl "lateinit()" initialization time. So there is an initial hook that assumes that Intel PMT will exist, called early so that package scoped domain groups are initialized. At first mount the remainder of initialization is done. If there are no Intel PMT events, the package domain lists are removed. Events for specific systems to be added by a separate patch. Signed-off-by: Tony Luck --- include/linux/resctrl.h | 8 ++ arch/x86/kernel/cpu/resctrl/internal.h | 7 + arch/x86/kernel/cpu/resctrl/core.c | 9 +- arch/x86/kernel/cpu/resctrl/intel_pmt.c | 169 ++++++++++++++++++++++++ arch/x86/kernel/cpu/resctrl/rdtgroup.c | 3 + arch/x86/kernel/cpu/resctrl/Makefile | 1 + 6 files changed, 194 insertions(+), 3 deletions(-) create mode 100644 arch/x86/kernel/cpu/resctrl/intel_pmt.c diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h index 9b64993a6cc8..6e463c65451b 100644 --- a/include/linux/resctrl.h +++ b/include/linux/resctrl.h @@ -118,6 +118,14 @@ struct rdt_mon_domain { int cqm_work_cpu; }; =20 +/** + * struct rdt_core_mon_domain - CPUs sharing an Intel-PMT-scoped resctrl m= onitor resource + * @hdr: common header for different domain types + */ +struct rdt_core_mon_domain { + struct rdt_domain_hdr hdr; +}; + /** * struct resctrl_cache - Cache allocation related data * @cbm_len: Length of the cache bit mask diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/r= esctrl/internal.h index c8da6fac4720..f530382d8871 100644 --- a/arch/x86/kernel/cpu/resctrl/internal.h +++ b/arch/x86/kernel/cpu/resctrl/internal.h @@ -637,6 +637,13 @@ void closid_free(int closid); int alloc_rmid(u32 closid); void free_rmid(u32 closid, u32 rmid); int rdt_get_mon_l3_config(struct rdt_resource *r); +#ifdef CONFIG_INTEL_PMT_RESCTRL +int rdt_get_intel_pmt_mon_config(void); +void rdt_get_intel_pmt_mount(void); +#else +static inline int rdt_get_intel_pmt_mon_config(void) { return 0; } +static inline void rdt_get_intel_pmt_mount(void) { } +#endif void __exit rdt_put_mon_l3_config(void); bool __init rdt_cpu_has(int flag); void mon_event_count(void *info); diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resct= rl/core.c index 75a815383427..c18d79e470d2 100644 --- a/arch/x86/kernel/cpu/resctrl/core.c +++ b/arch/x86/kernel/cpu/resctrl/core.c @@ -972,6 +972,7 @@ static __init bool get_rdt_alloc_resources(void) static __init bool get_rdt_mon_resources(void) { struct rdt_resource *r =3D &rdt_resources_all[RDT_RESOURCE_L3].r_resctrl; + int ret1 =3D -EINVAL, ret2; =20 if (rdt_cpu_has(X86_FEATURE_CQM_OCCUP_LLC)) rdt_mon_features |=3D (1 << QOS_L3_OCCUP_EVENT_ID); @@ -980,15 +981,17 @@ static __init bool get_rdt_mon_resources(void) if (rdt_cpu_has(X86_FEATURE_CQM_MBM_LOCAL)) rdt_mon_features |=3D (1 << QOS_L3_MBM_LOCAL_EVENT_ID); =20 - if (!rdt_mon_features) - return false; + if (rdt_mon_features) + ret1 =3D rdt_get_mon_l3_config(r); + + ret2 =3D rdt_get_intel_pmt_mon_config(); =20 if (is_mbm_local_enabled()) mba_mbps_default_event =3D QOS_L3_MBM_LOCAL_EVENT_ID; else if (is_mbm_total_enabled()) mba_mbps_default_event =3D QOS_L3_MBM_TOTAL_EVENT_ID; =20 - return !rdt_get_mon_l3_config(r); + return ret1 =3D=3D 0 || ret2; } =20 static __init void __check_quirks_intel(void) diff --git a/arch/x86/kernel/cpu/resctrl/intel_pmt.c b/arch/x86/kernel/cpu/= resctrl/intel_pmt.c new file mode 100644 index 000000000000..44373052ca49 --- /dev/null +++ b/arch/x86/kernel/cpu/resctrl/intel_pmt.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Resource Director Technology(RDT) + * - Intel Telemetry Event Monitoring code + * + * Copyright (C) 2025 Intel Corporation + * + * Author: + * Tony Luck + */ + +#define pr_fmt(fmt) "resctrl: " fmt + +#include +#include +#include +#include "fake_intel_pmt_features.h" +#include +#include + +#include "internal.h" + +static struct pmt_feature_group *feat_energy; +static struct pmt_feature_group *feat_perf; + +enum pmt_event_id { + PMT_EVENT_ENERGY, + PMT_EVENT_ACTIVITY, + PMT_EVENT_STALLS_LLC_HIT, + PMT_EVENT_C1_RES, + PMT_EVENT_UNHALTED_CORE_CYCLES, + PMT_EVENT_STALLS_LLC_MISS, + PMT_EVENT_AUTO_C6_RES, + PMT_EVENT_UNHALTED_REF_CYCLES, + PMT_EVENT_UOPS_RETIRED, + + PMT_NUM_EVENTS +}; + +enum evt_type { + EVT_U64, + EVT_U46_18, +}; + +#define EVT(id, evtname, offset, t) \ + { \ + .evt =3D { \ + .evtid =3D id, \ + .name =3D evtname \ + }, \ + .evt_offset =3D offset, \ + .evt_type =3D t \ + } + +struct pmt_event { + struct mon_evt evt; + int evt_offset; + enum evt_type evt_type; +}; + +struct telem_entry { + char *name; + int guid; + int num_rmids; + int stride; + int overflow_counter_off; + int last_overflow_tstamp_off; + int last_update_tstamp_off; + bool active; + struct pmt_event evts[]; +}; + +static struct telem_entry *telem_entry[] =3D { + NULL +}; + +static struct pkg_info { + int count; + struct telemetry_region *regions; +} *pkg_info; + +static bool count_events(struct pkg_info *pkg, int max_pkgs, struct pmt_fe= ature_group *p) +{ + struct telem_entry **tentry; + bool found =3D false; + + for (int i =3D 0; i < p->count; i++) { + struct telemetry_region *tr =3D &p->regions[i]; + + for (tentry =3D telem_entry; *tentry; tentry++) { + if (tr->guid =3D=3D (*tentry)->guid) { + if (tr->plat_info.package_id > max_pkgs) { + pr_warn_once("Bad package %d\n", tr->plat_info.package_id); + continue; + } + found =3D true; + (*tentry)->active =3D true; + pkg[tr->plat_info.package_id].count++; + break; + } + } + } + + return found; +} + +DEFINE_FREE(intel_pmt_put_feature_group, struct pmt_feature_group *, \ + if (!IS_ERR_OR_NULL(_T)) \ + intel_pmt_put_feature_group(_T)) + +static bool get_events(void) +{ + struct pmt_feature_group *p1 __free(intel_pmt_put_feature_group) =3D NULL; + struct pmt_feature_group *p2 __free(intel_pmt_put_feature_group) =3D NULL; + int num_pkgs =3D topology_max_packages(); + struct pkg_info *pkg __free(kfree) =3D NULL; + + pkg =3D kmalloc_array(num_pkgs, sizeof(*pkg_info), GFP_KERNEL | __GFP_ZER= O); + if (!pkg) + return false; + + p1 =3D intel_pmt_get_regions_by_feature(FEATURE_PER_RMID_ENERGY_TELEM); + p2 =3D intel_pmt_get_regions_by_feature(FEATURE_PER_RMID_PERF_TELEM); + + if (IS_ERR_VALUE(p1) && IS_ERR_VALUE(p1)) + return false; + + if (!IS_ERR_VALUE(p1)) + if (!count_events(pkg, num_pkgs, p1)) + intel_pmt_put_feature_group(no_free_ptr(p1)); + if (!IS_ERR_VALUE(p2)) + if (!count_events(pkg, num_pkgs, p2)) + intel_pmt_put_feature_group(no_free_ptr(p2)); + + if (!IS_ERR_OR_NULL(p1)) + feat_energy =3D no_free_ptr(p1); + if (!IS_ERR_OR_NULL(p2)) + feat_perf =3D no_free_ptr(p2); + pkg_info =3D no_free_ptr(pkg); + + return true; +} + +int rdt_get_intel_pmt_mon_config(void) +{ + struct rdt_resource *r =3D &rdt_resources_all[RDT_RESOURCE_INTEL_PMT].r_r= esctrl; + + INIT_LIST_HEAD(&r->evt_list); + + return 1; +} + +void rdt_get_intel_pmt_mount(void) +{ + struct rdt_resource *r =3D &rdt_resources_all[RDT_RESOURCE_INTEL_PMT].r_r= esctrl; + struct rdt_core_mon_domain *d, *tmp; + static int do_one_time; + + if (do_one_time) + return; + + do_one_time =3D 1; + + if (!get_events()) { + list_for_each_entry_safe(d, tmp, &r->mon_domains, hdr.list) + kfree(d); + r->mon_capable =3D false; + } +} diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/r= esctrl/rdtgroup.c index d2f3718f16af..4259bded5b7b 100644 --- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c +++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c @@ -2645,6 +2645,9 @@ static int rdt_get_tree(struct fs_context *fc) =20 cpus_read_lock(); mutex_lock(&rdtgroup_mutex); + + rdt_get_intel_pmt_mount(); + /* * resctrl file system can only be mounted once. */ diff --git a/arch/x86/kernel/cpu/resctrl/Makefile b/arch/x86/kernel/cpu/res= ctrl/Makefile index 72621ea6cd6a..fc79e767b263 100644 --- a/arch/x86/kernel/cpu/resctrl/Makefile +++ b/arch/x86/kernel/cpu/resctrl/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_X86_CPU_RESCTRL) +=3D core.o rdtgroup.o monitor.o obj-$(CONFIG_X86_CPU_RESCTRL) +=3D ctrlmondata.o pseudo_lock.o +obj-$(CONFIG_INTEL_PMT_RESCTRL) +=3D intel_pmt.o obj-$(CONFIG_INTEL_PMT_RESCTRL) +=3D fake_intel_pmt_features.o CFLAGS_pseudo_lock.o =3D -I$(src) --=20 2.48.1