summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86/Kconfig13
-rw-r--r--arch/x86/kernel/cpu/resctrl/Makefile1
-rw-r--r--arch/x86/kernel/cpu/resctrl/core.c4
-rw-r--r--arch/x86/kernel/cpu/resctrl/intel_aet.c109
-rw-r--r--arch/x86/kernel/cpu/resctrl/internal.h8
5 files changed, 135 insertions, 0 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 80527299f859..0d874a92daed 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -540,6 +540,19 @@ config X86_CPU_RESCTRL
Say N if unsure.
+config X86_CPU_RESCTRL_INTEL_AET
+ bool "Intel Application Energy Telemetry"
+ depends on X86_CPU_RESCTRL && CPU_SUP_INTEL && INTEL_PMT_TELEMETRY=y && INTEL_TPMI=y
+ help
+ Enable per-RMID telemetry events in resctrl.
+
+ Intel feature that collects per-RMID execution data
+ about energy consumption, measure of frequency independent
+ activity and other performance metrics. Data is aggregated
+ per package.
+
+ Say N if unsure.
+
config X86_FRED
bool "Flexible Return and Event Delivery"
depends on X86_64
diff --git a/arch/x86/kernel/cpu/resctrl/Makefile b/arch/x86/kernel/cpu/resctrl/Makefile
index d8a04b195da2..273ddfa30836 100644
--- a/arch/x86/kernel/cpu/resctrl/Makefile
+++ b/arch/x86/kernel/cpu/resctrl/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_X86_CPU_RESCTRL) += core.o rdtgroup.o monitor.o
obj-$(CONFIG_X86_CPU_RESCTRL) += ctrlmondata.o
+obj-$(CONFIG_X86_CPU_RESCTRL_INTEL_AET) += intel_aet.o
obj-$(CONFIG_RESCTRL_FS_PSEUDO_LOCK) += pseudo_lock.o
# To allow define_trace.h's recursive include:
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index f3d7e2263630..595f7eae9294 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -738,6 +738,8 @@ static int resctrl_arch_offline_cpu(unsigned int cpu)
void resctrl_arch_pre_mount(void)
{
+ if (!intel_aet_get_events())
+ return;
}
enum {
@@ -1099,6 +1101,8 @@ late_initcall(resctrl_arch_late_init);
static void __exit resctrl_arch_exit(void)
{
+ intel_aet_exit();
+
cpuhp_remove_state(rdt_online);
resctrl_exit();
diff --git a/arch/x86/kernel/cpu/resctrl/intel_aet.c b/arch/x86/kernel/cpu/resctrl/intel_aet.c
new file mode 100644
index 000000000000..404564739bef
--- /dev/null
+++ b/arch/x86/kernel/cpu/resctrl/intel_aet.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Resource Director Technology(RDT)
+ * - Intel Application Energy Telemetry
+ *
+ * Copyright (C) 2025 Intel Corporation
+ *
+ * Author:
+ * Tony Luck <tony.luck@intel.com>
+ */
+
+#define pr_fmt(fmt) "resctrl: " fmt
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/intel_pmt_features.h>
+#include <linux/intel_vsec.h>
+#include <linux/resctrl.h>
+#include <linux/stddef.h>
+
+#include "internal.h"
+
+/**
+ * struct event_group - Events with the same feature type ("energy" or "perf") and GUID.
+ * @pfname: PMT feature name ("energy" or "perf") of this event group.
+ * @pfg: Points to the aggregated telemetry space information
+ * returned by the intel_pmt_get_regions_by_feature()
+ * call to the INTEL_PMT_TELEMETRY driver that contains
+ * data for all telemetry regions of type @pfname.
+ * Valid if the system supports the event group,
+ * NULL otherwise.
+ */
+struct event_group {
+ /* Data fields for additional structures to manage this group. */
+ const char *pfname;
+ struct pmt_feature_group *pfg;
+};
+
+static struct event_group *known_event_groups[] = {
+};
+
+#define for_each_event_group(_peg) \
+ for (_peg = known_event_groups; \
+ _peg < &known_event_groups[ARRAY_SIZE(known_event_groups)]; \
+ _peg++)
+
+/* Stub for now */
+static bool enable_events(struct event_group *e, struct pmt_feature_group *p)
+{
+ return false;
+}
+
+static enum pmt_feature_id lookup_pfid(const char *pfname)
+{
+ if (!strcmp(pfname, "energy"))
+ return FEATURE_PER_RMID_ENERGY_TELEM;
+ else if (!strcmp(pfname, "perf"))
+ return FEATURE_PER_RMID_PERF_TELEM;
+
+ pr_warn("Unknown PMT feature name '%s'\n", pfname);
+
+ return FEATURE_INVALID;
+}
+
+/*
+ * Request a copy of struct pmt_feature_group for each event group. If there is
+ * one, the returned structure has an array of telemetry_region structures,
+ * each element of the array describes one telemetry aggregator. The
+ * telemetry aggregators may have different GUIDs so obtain duplicate struct
+ * pmt_feature_group for event groups with same feature type but different
+ * GUID. Post-processing ensures an event group can only use the telemetry
+ * aggregators that match its GUID. An event group keeps a pointer to its
+ * struct pmt_feature_group to indicate that its events are successfully
+ * enabled.
+ */
+bool intel_aet_get_events(void)
+{
+ struct pmt_feature_group *p;
+ enum pmt_feature_id pfid;
+ struct event_group **peg;
+ bool ret = false;
+
+ for_each_event_group(peg) {
+ pfid = lookup_pfid((*peg)->pfname);
+ p = intel_pmt_get_regions_by_feature(pfid);
+ if (IS_ERR_OR_NULL(p))
+ continue;
+ if (enable_events(*peg, p)) {
+ (*peg)->pfg = p;
+ ret = true;
+ } else {
+ intel_pmt_put_feature_group(p);
+ }
+ }
+
+ return ret;
+}
+
+void __exit intel_aet_exit(void)
+{
+ struct event_group **peg;
+
+ for_each_event_group(peg) {
+ if ((*peg)->pfg) {
+ intel_pmt_put_feature_group((*peg)->pfg);
+ (*peg)->pfg = NULL;
+ }
+ }
+}
diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h
index 11d06995810e..f2e6e3577df0 100644
--- a/arch/x86/kernel/cpu/resctrl/internal.h
+++ b/arch/x86/kernel/cpu/resctrl/internal.h
@@ -222,4 +222,12 @@ void __init intel_rdt_mbm_apply_quirk(void);
void rdt_domain_reconfigure_cdp(struct rdt_resource *r);
void resctrl_arch_mbm_cntr_assign_set_one(struct rdt_resource *r);
+#ifdef CONFIG_X86_CPU_RESCTRL_INTEL_AET
+bool intel_aet_get_events(void);
+void __exit intel_aet_exit(void);
+#else
+static inline bool intel_aet_get_events(void) { return false; }
+static inline void __exit intel_aet_exit(void) { }
+#endif
+
#endif /* _ASM_X86_RESCTRL_INTERNAL_H */