1 // SPDX-License-Identifier: GPL-2.0-only
3 * Intel Running Average Power Limit (RAPL) Driver via MSR interface
4 * Copyright (c) 2019, Intel Corporation.
6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/list.h>
11 #include <linux/types.h>
12 #include <linux/device.h>
13 #include <linux/slab.h>
14 #include <linux/log2.h>
15 #include <linux/bitmap.h>
16 #include <linux/delay.h>
17 #include <linux/sysfs.h>
18 #include <linux/cpu.h>
19 #include <linux/powercap.h>
20 #include <linux/suspend.h>
21 #include <linux/intel_rapl.h>
22 #include <linux/processor.h>
23 #include <linux/platform_device.h>
25 #include <asm/cpu_device_id.h>
26 #include <asm/intel-family.h>
29 #define MSR_PLATFORM_POWER_LIMIT 0x0000065C
30 #define MSR_VR_CURRENT_CONFIG 0x00000601
32 /* private data for RAPL MSR Interface */
33 static struct rapl_if_priv
*rapl_msr_priv
;
35 static struct rapl_if_priv rapl_msr_priv_intel
= {
37 .reg_unit
.msr
= MSR_RAPL_POWER_UNIT
,
38 .regs
[RAPL_DOMAIN_PACKAGE
][RAPL_DOMAIN_REG_LIMIT
].msr
= MSR_PKG_POWER_LIMIT
,
39 .regs
[RAPL_DOMAIN_PACKAGE
][RAPL_DOMAIN_REG_STATUS
].msr
= MSR_PKG_ENERGY_STATUS
,
40 .regs
[RAPL_DOMAIN_PACKAGE
][RAPL_DOMAIN_REG_PERF
].msr
= MSR_PKG_PERF_STATUS
,
41 .regs
[RAPL_DOMAIN_PACKAGE
][RAPL_DOMAIN_REG_INFO
].msr
= MSR_PKG_POWER_INFO
,
42 .regs
[RAPL_DOMAIN_PP0
][RAPL_DOMAIN_REG_LIMIT
].msr
= MSR_PP0_POWER_LIMIT
,
43 .regs
[RAPL_DOMAIN_PP0
][RAPL_DOMAIN_REG_STATUS
].msr
= MSR_PP0_ENERGY_STATUS
,
44 .regs
[RAPL_DOMAIN_PP0
][RAPL_DOMAIN_REG_POLICY
].msr
= MSR_PP0_POLICY
,
45 .regs
[RAPL_DOMAIN_PP1
][RAPL_DOMAIN_REG_LIMIT
].msr
= MSR_PP1_POWER_LIMIT
,
46 .regs
[RAPL_DOMAIN_PP1
][RAPL_DOMAIN_REG_STATUS
].msr
= MSR_PP1_ENERGY_STATUS
,
47 .regs
[RAPL_DOMAIN_PP1
][RAPL_DOMAIN_REG_POLICY
].msr
= MSR_PP1_POLICY
,
48 .regs
[RAPL_DOMAIN_DRAM
][RAPL_DOMAIN_REG_LIMIT
].msr
= MSR_DRAM_POWER_LIMIT
,
49 .regs
[RAPL_DOMAIN_DRAM
][RAPL_DOMAIN_REG_STATUS
].msr
= MSR_DRAM_ENERGY_STATUS
,
50 .regs
[RAPL_DOMAIN_DRAM
][RAPL_DOMAIN_REG_PERF
].msr
= MSR_DRAM_PERF_STATUS
,
51 .regs
[RAPL_DOMAIN_DRAM
][RAPL_DOMAIN_REG_INFO
].msr
= MSR_DRAM_POWER_INFO
,
52 .regs
[RAPL_DOMAIN_PLATFORM
][RAPL_DOMAIN_REG_LIMIT
].msr
= MSR_PLATFORM_POWER_LIMIT
,
53 .regs
[RAPL_DOMAIN_PLATFORM
][RAPL_DOMAIN_REG_STATUS
].msr
= MSR_PLATFORM_ENERGY_STATUS
,
54 .limits
[RAPL_DOMAIN_PACKAGE
] = BIT(POWER_LIMIT2
),
55 .limits
[RAPL_DOMAIN_PLATFORM
] = BIT(POWER_LIMIT2
),
58 static struct rapl_if_priv rapl_msr_priv_amd
= {
60 .reg_unit
.msr
= MSR_AMD_RAPL_POWER_UNIT
,
61 .regs
[RAPL_DOMAIN_PACKAGE
][RAPL_DOMAIN_REG_STATUS
].msr
= MSR_AMD_PKG_ENERGY_STATUS
,
62 .regs
[RAPL_DOMAIN_PP0
][RAPL_DOMAIN_REG_STATUS
].msr
= MSR_AMD_CORE_ENERGY_STATUS
,
65 /* Handles CPU hotplug on multi-socket systems.
66 * If a CPU goes online as the first CPU of the physical package
67 * we add the RAPL package to the system. Similarly, when the last
68 * CPU of the package is removed, we remove the RAPL package and its
69 * associated domains. Cooling devices are handled accordingly at
72 static int rapl_cpu_online(unsigned int cpu
)
74 struct rapl_package
*rp
;
76 rp
= rapl_find_package_domain_cpuslocked(cpu
, rapl_msr_priv
, true);
78 rp
= rapl_add_package_cpuslocked(cpu
, rapl_msr_priv
, true);
82 cpumask_set_cpu(cpu
, &rp
->cpumask
);
86 static int rapl_cpu_down_prep(unsigned int cpu
)
88 struct rapl_package
*rp
;
91 rp
= rapl_find_package_domain_cpuslocked(cpu
, rapl_msr_priv
, true);
95 cpumask_clear_cpu(cpu
, &rp
->cpumask
);
96 lead_cpu
= cpumask_first(&rp
->cpumask
);
97 if (lead_cpu
>= nr_cpu_ids
)
98 rapl_remove_package_cpuslocked(rp
);
99 else if (rp
->lead_cpu
== cpu
)
100 rp
->lead_cpu
= lead_cpu
;
104 static int rapl_msr_read_raw(int cpu
, struct reg_action
*ra
)
106 if (rdmsrl_safe_on_cpu(cpu
, ra
->reg
.msr
, &ra
->value
)) {
107 pr_debug("failed to read msr 0x%x on cpu %d\n", ra
->reg
.msr
, cpu
);
110 ra
->value
&= ra
->mask
;
114 static void rapl_msr_update_func(void *info
)
116 struct reg_action
*ra
= info
;
119 ra
->err
= rdmsrl_safe(ra
->reg
.msr
, &val
);
126 ra
->err
= wrmsrl_safe(ra
->reg
.msr
, val
);
129 static int rapl_msr_write_raw(int cpu
, struct reg_action
*ra
)
133 ret
= smp_call_function_single(cpu
, rapl_msr_update_func
, ra
, 1);
134 if (WARN_ON_ONCE(ret
))
140 /* List of verified CPUs. */
141 static const struct x86_cpu_id pl4_support_ids
[] = {
142 X86_MATCH_VFM(INTEL_TIGERLAKE_L
, NULL
),
143 X86_MATCH_VFM(INTEL_ALDERLAKE
, NULL
),
144 X86_MATCH_VFM(INTEL_ALDERLAKE_L
, NULL
),
145 X86_MATCH_VFM(INTEL_ATOM_GRACEMONT
, NULL
),
146 X86_MATCH_VFM(INTEL_RAPTORLAKE
, NULL
),
147 X86_MATCH_VFM(INTEL_RAPTORLAKE_P
, NULL
),
148 X86_MATCH_VFM(INTEL_METEORLAKE
, NULL
),
149 X86_MATCH_VFM(INTEL_METEORLAKE_L
, NULL
),
150 X86_MATCH_VFM(INTEL_ARROWLAKE_U
, NULL
),
151 X86_MATCH_VFM(INTEL_ARROWLAKE_H
, NULL
),
155 static int rapl_msr_probe(struct platform_device
*pdev
)
157 const struct x86_cpu_id
*id
= x86_match_cpu(pl4_support_ids
);
160 switch (boot_cpu_data
.x86_vendor
) {
161 case X86_VENDOR_INTEL
:
162 rapl_msr_priv
= &rapl_msr_priv_intel
;
164 case X86_VENDOR_HYGON
:
166 rapl_msr_priv
= &rapl_msr_priv_amd
;
169 pr_err("intel-rapl does not support CPU vendor %d\n", boot_cpu_data
.x86_vendor
);
172 rapl_msr_priv
->read_raw
= rapl_msr_read_raw
;
173 rapl_msr_priv
->write_raw
= rapl_msr_write_raw
;
176 rapl_msr_priv
->limits
[RAPL_DOMAIN_PACKAGE
] |= BIT(POWER_LIMIT4
);
177 rapl_msr_priv
->regs
[RAPL_DOMAIN_PACKAGE
][RAPL_DOMAIN_REG_PL4
].msr
=
178 MSR_VR_CURRENT_CONFIG
;
179 pr_info("PL4 support detected.\n");
182 rapl_msr_priv
->control_type
= powercap_register_control_type(NULL
, "intel-rapl", NULL
);
183 if (IS_ERR(rapl_msr_priv
->control_type
)) {
184 pr_debug("failed to register powercap control_type.\n");
185 return PTR_ERR(rapl_msr_priv
->control_type
);
188 ret
= cpuhp_setup_state(CPUHP_AP_ONLINE_DYN
, "powercap/rapl:online",
189 rapl_cpu_online
, rapl_cpu_down_prep
);
192 rapl_msr_priv
->pcap_rapl_online
= ret
;
198 powercap_unregister_control_type(rapl_msr_priv
->control_type
);
202 static void rapl_msr_remove(struct platform_device
*pdev
)
204 cpuhp_remove_state(rapl_msr_priv
->pcap_rapl_online
);
205 powercap_unregister_control_type(rapl_msr_priv
->control_type
);
208 static const struct platform_device_id rapl_msr_ids
[] = {
209 { .name
= "intel_rapl_msr", },
212 MODULE_DEVICE_TABLE(platform
, rapl_msr_ids
);
214 static struct platform_driver intel_rapl_msr_driver
= {
215 .probe
= rapl_msr_probe
,
216 .remove
= rapl_msr_remove
,
217 .id_table
= rapl_msr_ids
,
219 .name
= "intel_rapl_msr",
223 module_platform_driver(intel_rapl_msr_driver
);
225 MODULE_DESCRIPTION("Driver for Intel RAPL (Running Average Power Limit) control via MSR interface");
226 MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>");
227 MODULE_LICENSE("GPL v2");