xref: /linux-6.15/include/linux/intel_rapl.h (revision 575024a8)
1ff956826SZhang Rui /* SPDX-License-Identifier: GPL-2.0 */
2ff956826SZhang Rui /*
3ff956826SZhang Rui  *  Data types and headers for RAPL support
4ff956826SZhang Rui  *
5ff956826SZhang Rui  *  Copyright (C) 2019  Intel Corporation.
6ff956826SZhang Rui  *
7ff956826SZhang Rui  *  Author: Zhang Rui <[email protected]>
8ff956826SZhang Rui  */
9ff956826SZhang Rui 
10ff956826SZhang Rui #ifndef __INTEL_RAPL_H__
11ff956826SZhang Rui #define __INTEL_RAPL_H__
12ff956826SZhang Rui 
13ff956826SZhang Rui #include <linux/types.h>
14ff956826SZhang Rui #include <linux/powercap.h>
158da04e05SStephen Rothwell #include <linux/cpuhotplug.h>
16ff956826SZhang Rui 
17b4288ce7SZhang Rui enum rapl_if_type {
18b4288ce7SZhang Rui 	RAPL_IF_MSR,	/* RAPL I/F using MSR registers */
19b4288ce7SZhang Rui 	RAPL_IF_MMIO,	/* RAPL I/F using MMIO registers */
20e12dee18SZhang Rui 	RAPL_IF_TPMI,	/* RAPL I/F using TPMI registers */
21b4288ce7SZhang Rui };
22b4288ce7SZhang Rui 
23ff956826SZhang Rui enum rapl_domain_type {
24ff956826SZhang Rui 	RAPL_DOMAIN_PACKAGE,	/* entire package/socket */
25ff956826SZhang Rui 	RAPL_DOMAIN_PP0,	/* core power plane */
26ff956826SZhang Rui 	RAPL_DOMAIN_PP1,	/* graphics uncore */
27ff956826SZhang Rui 	RAPL_DOMAIN_DRAM,	/* DRAM control_type */
28ff956826SZhang Rui 	RAPL_DOMAIN_PLATFORM,	/* PSys control_type */
29ff956826SZhang Rui 	RAPL_DOMAIN_MAX,
30ff956826SZhang Rui };
31ff956826SZhang Rui 
32ff956826SZhang Rui enum rapl_domain_reg_id {
33ff956826SZhang Rui 	RAPL_DOMAIN_REG_LIMIT,
34ff956826SZhang Rui 	RAPL_DOMAIN_REG_STATUS,
35ff956826SZhang Rui 	RAPL_DOMAIN_REG_PERF,
36ff956826SZhang Rui 	RAPL_DOMAIN_REG_POLICY,
37ff956826SZhang Rui 	RAPL_DOMAIN_REG_INFO,
388365a898SSumeet Pawnikar 	RAPL_DOMAIN_REG_PL4,
39cb532e72SZhang Rui 	RAPL_DOMAIN_REG_UNIT,
40e12dee18SZhang Rui 	RAPL_DOMAIN_REG_PL2,
41ff956826SZhang Rui 	RAPL_DOMAIN_REG_MAX,
42ff956826SZhang Rui };
43ff956826SZhang Rui 
4435eb1f50SWan Jiabing struct rapl_domain;
45ff956826SZhang Rui 
46ff956826SZhang Rui enum rapl_primitives {
47ff956826SZhang Rui 	POWER_LIMIT1,
48ff956826SZhang Rui 	POWER_LIMIT2,
498365a898SSumeet Pawnikar 	POWER_LIMIT4,
50045610c3SZhang Rui 	ENERGY_COUNTER,
51ff956826SZhang Rui 	FW_LOCK,
52f442bd27SZhang Rui 	FW_HIGH_LOCK,
53e12dee18SZhang Rui 	PL1_LOCK,
54e12dee18SZhang Rui 	PL2_LOCK,
55e12dee18SZhang Rui 	PL4_LOCK,
56ff956826SZhang Rui 
57ff956826SZhang Rui 	PL1_ENABLE,		/* power limit 1, aka long term */
58ff956826SZhang Rui 	PL1_CLAMP,		/* allow frequency to go below OS request */
59ff956826SZhang Rui 	PL2_ENABLE,		/* power limit 2, aka short term, instantaneous */
60ff956826SZhang Rui 	PL2_CLAMP,
618365a898SSumeet Pawnikar 	PL4_ENABLE,		/* power limit 4, aka max peak power */
62ff956826SZhang Rui 
63ff956826SZhang Rui 	TIME_WINDOW1,		/* long term */
64ff956826SZhang Rui 	TIME_WINDOW2,		/* short term */
65ff956826SZhang Rui 	THERMAL_SPEC_POWER,
66ff956826SZhang Rui 	MAX_POWER,
67ff956826SZhang Rui 
68ff956826SZhang Rui 	MIN_POWER,
69ff956826SZhang Rui 	MAX_TIME_WINDOW,
70ff956826SZhang Rui 	THROTTLED_TIME,
71ff956826SZhang Rui 	PRIORITY_LEVEL,
72ff956826SZhang Rui 
73931da6a0SZhang Rui 	PSYS_POWER_LIMIT1,
74931da6a0SZhang Rui 	PSYS_POWER_LIMIT2,
75931da6a0SZhang Rui 	PSYS_PL1_ENABLE,
76931da6a0SZhang Rui 	PSYS_PL2_ENABLE,
77931da6a0SZhang Rui 	PSYS_TIME_WINDOW1,
78931da6a0SZhang Rui 	PSYS_TIME_WINDOW2,
79ff956826SZhang Rui 	/* below are not raw primitive data */
80ff956826SZhang Rui 	AVERAGE_POWER,
81ff956826SZhang Rui 	NR_RAPL_PRIMITIVES,
82ff956826SZhang Rui };
83ff956826SZhang Rui 
84ff956826SZhang Rui struct rapl_domain_data {
85ff956826SZhang Rui 	u64 primitives[NR_RAPL_PRIMITIVES];
86ff956826SZhang Rui 	unsigned long timestamp;
87ff956826SZhang Rui };
88ff956826SZhang Rui 
89045610c3SZhang Rui #define NR_POWER_LIMITS	(POWER_LIMIT4 + 1)
90045610c3SZhang Rui 
91ff956826SZhang Rui struct rapl_power_limit {
92ff956826SZhang Rui 	struct powercap_zone_constraint *constraint;
93ff956826SZhang Rui 	struct rapl_domain *domain;
94ff956826SZhang Rui 	const char *name;
95f442bd27SZhang Rui 	bool locked;
96ff956826SZhang Rui 	u64 last_power_limit;
97ff956826SZhang Rui };
98ff956826SZhang Rui 
99ff956826SZhang Rui struct rapl_package;
100ff956826SZhang Rui 
101f1e8d756SZhang Rui #define RAPL_DOMAIN_NAME_LENGTH 16
102f1e8d756SZhang Rui 
10316e95a62SZhang Rui union rapl_reg {
10416e95a62SZhang Rui 	void __iomem *mmio;
10516e95a62SZhang Rui 	u32 msr;
10616e95a62SZhang Rui 	u64 val;
10716e95a62SZhang Rui };
10816e95a62SZhang Rui 
109ff956826SZhang Rui struct rapl_domain {
110f1e8d756SZhang Rui 	char name[RAPL_DOMAIN_NAME_LENGTH];
111ff956826SZhang Rui 	enum rapl_domain_type id;
11216e95a62SZhang Rui 	union rapl_reg regs[RAPL_DOMAIN_REG_MAX];
113ff956826SZhang Rui 	struct powercap_zone power_zone;
114ff956826SZhang Rui 	struct rapl_domain_data rdd;
115ff956826SZhang Rui 	struct rapl_power_limit rpl[NR_POWER_LIMITS];
116ff956826SZhang Rui 	u64 attr_map;		/* track capabilities */
117ff956826SZhang Rui 	unsigned int state;
118cb532e72SZhang Rui 	unsigned int power_unit;
119cb532e72SZhang Rui 	unsigned int energy_unit;
120cb532e72SZhang Rui 	unsigned int time_unit;
121ff956826SZhang Rui 	struct rapl_package *rp;
122ff956826SZhang Rui };
123ff956826SZhang Rui 
124beea8df8SZhang Rui struct reg_action {
12516e95a62SZhang Rui 	union rapl_reg reg;
126beea8df8SZhang Rui 	u64 mask;
127beea8df8SZhang Rui 	u64 value;
128beea8df8SZhang Rui 	int err;
129beea8df8SZhang Rui };
130beea8df8SZhang Rui 
1317ebf8effSZhang Rui /**
1327ebf8effSZhang Rui  * struct rapl_if_priv: private data for different RAPL interfaces
1337ebf8effSZhang Rui  * @control_type:		Each RAPL interface must have its own powercap
1347ebf8effSZhang Rui  *				control type.
1357ebf8effSZhang Rui  * @platform_rapl_domain:	Optional. Some RAPL interface may have platform
1367ebf8effSZhang Rui  *				level RAPL control.
1377ebf8effSZhang Rui  * @pcap_rapl_online:		CPU hotplug state for each RAPL interface.
1387fde2712SZhang Rui  * @reg_unit:			Register for getting energy/power/time unit.
1397fde2712SZhang Rui  * @regs:			Register sets for different RAPL Domains.
1400c2ddeddSZhang Rui  * @limits:			Number of power limits supported by each domain.
141beea8df8SZhang Rui  * @read_raw:			Callback for reading RAPL interface specific
142beea8df8SZhang Rui  *				registers.
143beea8df8SZhang Rui  * @write_raw:			Callback for writing RAPL interface specific
144beea8df8SZhang Rui  *				registers.
145e8e28c2aSZhang Rui  * @defaults:			internal pointer to interface default settings
14698ff639aSZhang Rui  * @rpi:			internal pointer to interface primitive info
1477ebf8effSZhang Rui  */
1487ebf8effSZhang Rui struct rapl_if_priv {
149b4288ce7SZhang Rui 	enum rapl_if_type type;
1507ebf8effSZhang Rui 	struct powercap_control_type *control_type;
1517ebf8effSZhang Rui 	enum cpuhp_state pcap_rapl_online;
15216e95a62SZhang Rui 	union rapl_reg reg_unit;
15316e95a62SZhang Rui 	union rapl_reg regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX];
1540c2ddeddSZhang Rui 	int limits[RAPL_DOMAIN_MAX];
155bf44b901SZhang Rui 	int (*read_raw)(int id, struct reg_action *ra);
156bf44b901SZhang Rui 	int (*write_raw)(int id, struct reg_action *ra);
157e8e28c2aSZhang Rui 	void *defaults;
15898ff639aSZhang Rui 	void *rpi;
1597ebf8effSZhang Rui };
1607ebf8effSZhang Rui 
161*575024a8SZhang Rui #ifdef CONFIG_PERF_EVENTS
162*575024a8SZhang Rui /**
163*575024a8SZhang Rui  * struct rapl_package_pmu_data: Per package data for PMU support
164*575024a8SZhang Rui  * @scale:		Scale of 2^-32 Joules for each energy counter increase.
165*575024a8SZhang Rui  * @lock:		Lock to protect n_active and active_list.
166*575024a8SZhang Rui  * @n_active:		Number of active events.
167*575024a8SZhang Rui  * @active_list:	List of active events.
168*575024a8SZhang Rui  * @timer_interval:	Maximum timer expiration time before counter overflow.
169*575024a8SZhang Rui  * @hrtimer:		Periodically update the counter to prevent overflow.
170*575024a8SZhang Rui  */
171*575024a8SZhang Rui struct rapl_package_pmu_data {
172*575024a8SZhang Rui 	u64 scale[RAPL_DOMAIN_MAX];
173*575024a8SZhang Rui 	raw_spinlock_t lock;
174*575024a8SZhang Rui 	int n_active;
175*575024a8SZhang Rui 	struct list_head active_list;
176*575024a8SZhang Rui 	ktime_t timer_interval;
177*575024a8SZhang Rui 	struct hrtimer hrtimer;
178*575024a8SZhang Rui };
179*575024a8SZhang Rui #endif
180*575024a8SZhang Rui 
181ff956826SZhang Rui /* maximum rapl package domain name: package-%d-die-%d */
182ff956826SZhang Rui #define PACKAGE_DOMAIN_NAME_LENGTH 30
183ff956826SZhang Rui 
184ff956826SZhang Rui struct rapl_package {
185ff956826SZhang Rui 	unsigned int id;	/* logical die id, equals physical 1-die systems */
186ff956826SZhang Rui 	unsigned int nr_domains;
187ff956826SZhang Rui 	unsigned long domain_map;	/* bit map of active domains */
188ff956826SZhang Rui 	struct rapl_domain *domains;	/* array of domains, sized at runtime */
189ff956826SZhang Rui 	struct powercap_zone *power_zone;	/* keep track of parent zone */
190ff956826SZhang Rui 	unsigned long power_limit_irq;	/* keep track of package power limit
191ff956826SZhang Rui 					 * notify interrupt enable status.
192ff956826SZhang Rui 					 */
193ff956826SZhang Rui 	struct list_head plist;
194ff956826SZhang Rui 	int lead_cpu;		/* one active cpu per package for access */
195ff956826SZhang Rui 	/* Track active cpus */
196ff956826SZhang Rui 	struct cpumask cpumask;
197ff956826SZhang Rui 	char name[PACKAGE_DOMAIN_NAME_LENGTH];
1987ebf8effSZhang Rui 	struct rapl_if_priv *priv;
199*575024a8SZhang Rui #ifdef CONFIG_PERF_EVENTS
200*575024a8SZhang Rui 	bool has_pmu;
201*575024a8SZhang Rui 	struct rapl_package_pmu_data pmu_data;
202*575024a8SZhang Rui #endif
203ff956826SZhang Rui };
204ff956826SZhang Rui 
2051aa09b93SZhang Rui struct rapl_package *rapl_find_package_domain_cpuslocked(int id, struct rapl_if_priv *priv,
2061aa09b93SZhang Rui 						       bool id_is_cpu);
2071aa09b93SZhang Rui struct rapl_package *rapl_add_package_cpuslocked(int id, struct rapl_if_priv *priv,
2081aa09b93SZhang Rui 						 bool id_is_cpu);
2091aa09b93SZhang Rui void rapl_remove_package_cpuslocked(struct rapl_package *rp);
2101aa09b93SZhang Rui 
211bf44b901SZhang Rui struct rapl_package *rapl_find_package_domain(int id, struct rapl_if_priv *priv, bool id_is_cpu);
212bf44b901SZhang Rui struct rapl_package *rapl_add_package(int id, struct rapl_if_priv *priv, bool id_is_cpu);
2133382388dSZhang Rui void rapl_remove_package(struct rapl_package *rp);
2143382388dSZhang Rui 
215*575024a8SZhang Rui #ifdef CONFIG_PERF_EVENTS
216*575024a8SZhang Rui int rapl_package_add_pmu(struct rapl_package *rp);
217*575024a8SZhang Rui void rapl_package_remove_pmu(struct rapl_package *rp);
218*575024a8SZhang Rui #else
rapl_package_add_pmu(struct rapl_package * rp)219*575024a8SZhang Rui static inline int rapl_package_add_pmu(struct rapl_package *rp) { return 0; }
rapl_package_remove_pmu(struct rapl_package * rp)220*575024a8SZhang Rui static inline void rapl_package_remove_pmu(struct rapl_package *rp) { }
221*575024a8SZhang Rui #endif
222*575024a8SZhang Rui 
223ff956826SZhang Rui #endif /* __INTEL_RAPL_H__ */
224