xref: /linux/arch/x86/kernel/cpu/resctrl/intel_aet.c (revision 1fb2daa60de640efb13f907d43d72d28763f696c)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Resource Director Technology(RDT)
4  * - Intel Application Energy Telemetry
5  *
6  * Copyright (C) 2025 Intel Corporation
7  *
8  * Author:
9  *    Tony Luck <tony.luck@intel.com>
10  */
11 
12 #define pr_fmt(fmt)   "resctrl: " fmt
13 
14 #include <linux/err.h>
15 #include <linux/init.h>
16 #include <linux/intel_pmt_features.h>
17 #include <linux/intel_vsec.h>
18 #include <linux/resctrl.h>
19 #include <linux/stddef.h>
20 
21 #include "internal.h"
22 
23 /**
24  * struct event_group - Events with the same feature type ("energy" or "perf") and GUID.
25  * @pfname:		PMT feature name ("energy" or "perf") of this event group.
26  * @pfg:		Points to the aggregated telemetry space information
27  *			returned by the intel_pmt_get_regions_by_feature()
28  *			call to the INTEL_PMT_TELEMETRY driver that contains
29  *			data for all telemetry regions of type @pfname.
30  *			Valid if the system supports the event group,
31  *			NULL otherwise.
32  */
33 struct event_group {
34 	/* Data fields for additional structures to manage this group. */
35 	const char			*pfname;
36 	struct pmt_feature_group	*pfg;
37 };
38 
39 static struct event_group *known_event_groups[] = {
40 };
41 
42 #define for_each_event_group(_peg)						\
43 	for (_peg = known_event_groups;						\
44 	     _peg < &known_event_groups[ARRAY_SIZE(known_event_groups)];	\
45 	     _peg++)
46 
47 /* Stub for now */
48 static bool enable_events(struct event_group *e, struct pmt_feature_group *p)
49 {
50 	return false;
51 }
52 
53 static enum pmt_feature_id lookup_pfid(const char *pfname)
54 {
55 	if (!strcmp(pfname, "energy"))
56 		return FEATURE_PER_RMID_ENERGY_TELEM;
57 	else if (!strcmp(pfname, "perf"))
58 		return FEATURE_PER_RMID_PERF_TELEM;
59 
60 	pr_warn("Unknown PMT feature name '%s'\n", pfname);
61 
62 	return FEATURE_INVALID;
63 }
64 
65 /*
66  * Request a copy of struct pmt_feature_group for each event group. If there is
67  * one, the returned structure has an array of telemetry_region structures,
68  * each element of the array describes one telemetry aggregator. The
69  * telemetry aggregators may have different GUIDs so obtain duplicate struct
70  * pmt_feature_group for event groups with same feature type but different
71  * GUID. Post-processing ensures an event group can only use the telemetry
72  * aggregators that match its GUID. An event group keeps a pointer to its
73  * struct pmt_feature_group to indicate that its events are successfully
74  * enabled.
75  */
76 bool intel_aet_get_events(void)
77 {
78 	struct pmt_feature_group *p;
79 	enum pmt_feature_id pfid;
80 	struct event_group **peg;
81 	bool ret = false;
82 
83 	for_each_event_group(peg) {
84 		pfid = lookup_pfid((*peg)->pfname);
85 		p = intel_pmt_get_regions_by_feature(pfid);
86 		if (IS_ERR_OR_NULL(p))
87 			continue;
88 		if (enable_events(*peg, p)) {
89 			(*peg)->pfg = p;
90 			ret = true;
91 		} else {
92 			intel_pmt_put_feature_group(p);
93 		}
94 	}
95 
96 	return ret;
97 }
98 
99 void __exit intel_aet_exit(void)
100 {
101 	struct event_group **peg;
102 
103 	for_each_event_group(peg) {
104 		if ((*peg)->pfg) {
105 			intel_pmt_put_feature_group((*peg)->pfg);
106 			(*peg)->pfg = NULL;
107 		}
108 	}
109 }
110