1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Intel Running Average Power Limit (RAPL) Driver via MSR interface 4 * Copyright (c) 2019, Intel Corporation. 5 */ 6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7 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> 24 25 #include <asm/cpu_device_id.h> 26 #include <asm/intel-family.h> 27 #include <asm/msr.h> 28 29 /* Local defines */ 30 #define MSR_PLATFORM_POWER_LIMIT 0x0000065C 31 #define MSR_VR_CURRENT_CONFIG 0x00000601 32 33 /* private data for RAPL MSR Interface */ 34 static struct rapl_if_priv *rapl_msr_priv; 35 36 static bool rapl_msr_pmu __ro_after_init; 37 38 static struct rapl_if_priv rapl_msr_priv_intel = { 39 .type = RAPL_IF_MSR, 40 .reg_unit.msr = MSR_RAPL_POWER_UNIT, 41 .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_LIMIT].msr = MSR_PKG_POWER_LIMIT, 42 .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_STATUS].msr = MSR_PKG_ENERGY_STATUS, 43 .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PERF].msr = MSR_PKG_PERF_STATUS, 44 .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_INFO].msr = MSR_PKG_POWER_INFO, 45 .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_LIMIT].msr = MSR_PP0_POWER_LIMIT, 46 .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_STATUS].msr = MSR_PP0_ENERGY_STATUS, 47 .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_POLICY].msr = MSR_PP0_POLICY, 48 .regs[RAPL_DOMAIN_PP1][RAPL_DOMAIN_REG_LIMIT].msr = MSR_PP1_POWER_LIMIT, 49 .regs[RAPL_DOMAIN_PP1][RAPL_DOMAIN_REG_STATUS].msr = MSR_PP1_ENERGY_STATUS, 50 .regs[RAPL_DOMAIN_PP1][RAPL_DOMAIN_REG_POLICY].msr = MSR_PP1_POLICY, 51 .regs[RAPL_DOMAIN_DRAM][RAPL_DOMAIN_REG_LIMIT].msr = MSR_DRAM_POWER_LIMIT, 52 .regs[RAPL_DOMAIN_DRAM][RAPL_DOMAIN_REG_STATUS].msr = MSR_DRAM_ENERGY_STATUS, 53 .regs[RAPL_DOMAIN_DRAM][RAPL_DOMAIN_REG_PERF].msr = MSR_DRAM_PERF_STATUS, 54 .regs[RAPL_DOMAIN_DRAM][RAPL_DOMAIN_REG_INFO].msr = MSR_DRAM_POWER_INFO, 55 .regs[RAPL_DOMAIN_PLATFORM][RAPL_DOMAIN_REG_LIMIT].msr = MSR_PLATFORM_POWER_LIMIT, 56 .regs[RAPL_DOMAIN_PLATFORM][RAPL_DOMAIN_REG_STATUS].msr = MSR_PLATFORM_ENERGY_STATUS, 57 .limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2), 58 .limits[RAPL_DOMAIN_PLATFORM] = BIT(POWER_LIMIT2), 59 }; 60 61 static struct rapl_if_priv rapl_msr_priv_amd = { 62 .type = RAPL_IF_MSR, 63 .reg_unit.msr = MSR_AMD_RAPL_POWER_UNIT, 64 .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_STATUS].msr = MSR_AMD_PKG_ENERGY_STATUS, 65 .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_STATUS].msr = MSR_AMD_CORE_ENERGY_STATUS, 66 }; 67 68 /* Handles CPU hotplug on multi-socket systems. 69 * If a CPU goes online as the first CPU of the physical package 70 * we add the RAPL package to the system. Similarly, when the last 71 * CPU of the package is removed, we remove the RAPL package and its 72 * associated domains. Cooling devices are handled accordingly at 73 * per-domain level. 74 */ 75 static int rapl_cpu_online(unsigned int cpu) 76 { 77 struct rapl_package *rp; 78 79 rp = rapl_find_package_domain_cpuslocked(cpu, rapl_msr_priv, true); 80 if (!rp) { 81 rp = rapl_add_package_cpuslocked(cpu, rapl_msr_priv, true); 82 if (IS_ERR(rp)) 83 return PTR_ERR(rp); 84 if (rapl_msr_pmu) 85 rapl_package_add_pmu(rp); 86 } 87 cpumask_set_cpu(cpu, &rp->cpumask); 88 return 0; 89 } 90 91 static int rapl_cpu_down_prep(unsigned int cpu) 92 { 93 struct rapl_package *rp; 94 int lead_cpu; 95 96 rp = rapl_find_package_domain_cpuslocked(cpu, rapl_msr_priv, true); 97 if (!rp) 98 return 0; 99 100 cpumask_clear_cpu(cpu, &rp->cpumask); 101 lead_cpu = cpumask_first(&rp->cpumask); 102 if (lead_cpu >= nr_cpu_ids) { 103 if (rapl_msr_pmu) 104 rapl_package_remove_pmu(rp); 105 rapl_remove_package_cpuslocked(rp); 106 } else if (rp->lead_cpu == cpu) { 107 rp->lead_cpu = lead_cpu; 108 } 109 110 return 0; 111 } 112 113 static int rapl_msr_read_raw(int cpu, struct reg_action *ra, bool atomic) 114 { 115 /* 116 * When called from atomic-context (eg PMU event handler) 117 * perform MSR read directly using rdmsrq(). 118 */ 119 if (atomic) { 120 if (unlikely(smp_processor_id() != cpu)) 121 return -EIO; 122 123 rdmsrq(ra->reg.msr, ra->value); 124 goto out; 125 } 126 127 if (rdmsrq_safe_on_cpu(cpu, ra->reg.msr, &ra->value)) { 128 pr_debug("failed to read msr 0x%x on cpu %d\n", ra->reg.msr, cpu); 129 return -EIO; 130 } 131 132 out: 133 ra->value &= ra->mask; 134 return 0; 135 } 136 137 static void rapl_msr_update_func(void *info) 138 { 139 struct reg_action *ra = info; 140 u64 val; 141 142 ra->err = rdmsrq_safe(ra->reg.msr, &val); 143 if (ra->err) 144 return; 145 146 val &= ~ra->mask; 147 val |= ra->value; 148 149 ra->err = wrmsrq_safe(ra->reg.msr, val); 150 } 151 152 static int rapl_msr_write_raw(int cpu, struct reg_action *ra) 153 { 154 int ret; 155 156 ret = smp_call_function_single(cpu, rapl_msr_update_func, ra, 1); 157 if (WARN_ON_ONCE(ret)) 158 return ret; 159 160 return ra->err; 161 } 162 163 /* List of verified CPUs. */ 164 static const struct x86_cpu_id pl4_support_ids[] = { 165 X86_MATCH_VFM(INTEL_TIGERLAKE_L, NULL), 166 X86_MATCH_VFM(INTEL_ALDERLAKE, NULL), 167 X86_MATCH_VFM(INTEL_ALDERLAKE_L, NULL), 168 X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, NULL), 169 X86_MATCH_VFM(INTEL_RAPTORLAKE, NULL), 170 X86_MATCH_VFM(INTEL_RAPTORLAKE_P, NULL), 171 X86_MATCH_VFM(INTEL_METEORLAKE, NULL), 172 X86_MATCH_VFM(INTEL_METEORLAKE_L, NULL), 173 X86_MATCH_VFM(INTEL_ARROWLAKE_U, NULL), 174 X86_MATCH_VFM(INTEL_ARROWLAKE_H, NULL), 175 X86_MATCH_VFM(INTEL_PANTHERLAKE_L, NULL), 176 X86_MATCH_VFM(INTEL_WILDCATLAKE_L, NULL), 177 X86_MATCH_VFM(INTEL_NOVALAKE, NULL), 178 X86_MATCH_VFM(INTEL_NOVALAKE_L, NULL), 179 {} 180 }; 181 182 /* List of MSR-based RAPL PMU support CPUs */ 183 static const struct x86_cpu_id pmu_support_ids[] = { 184 X86_MATCH_VFM(INTEL_PANTHERLAKE_L, NULL), 185 X86_MATCH_VFM(INTEL_WILDCATLAKE_L, NULL), 186 {} 187 }; 188 189 static int rapl_msr_probe(struct platform_device *pdev) 190 { 191 const struct x86_cpu_id *id = x86_match_cpu(pl4_support_ids); 192 int ret; 193 194 switch (boot_cpu_data.x86_vendor) { 195 case X86_VENDOR_INTEL: 196 rapl_msr_priv = &rapl_msr_priv_intel; 197 break; 198 case X86_VENDOR_HYGON: 199 case X86_VENDOR_AMD: 200 rapl_msr_priv = &rapl_msr_priv_amd; 201 break; 202 default: 203 pr_err("intel-rapl does not support CPU vendor %d\n", boot_cpu_data.x86_vendor); 204 return -ENODEV; 205 } 206 rapl_msr_priv->read_raw = rapl_msr_read_raw; 207 rapl_msr_priv->write_raw = rapl_msr_write_raw; 208 209 if (id) { 210 rapl_msr_priv->limits[RAPL_DOMAIN_PACKAGE] |= BIT(POWER_LIMIT4); 211 rapl_msr_priv->regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PL4].msr = 212 MSR_VR_CURRENT_CONFIG; 213 pr_info("PL4 support detected.\n"); 214 } 215 216 if (x86_match_cpu(pmu_support_ids)) { 217 rapl_msr_pmu = true; 218 pr_info("MSR-based RAPL PMU support enabled\n"); 219 } 220 221 rapl_msr_priv->control_type = powercap_register_control_type(NULL, "intel-rapl", NULL); 222 if (IS_ERR(rapl_msr_priv->control_type)) { 223 pr_debug("failed to register powercap control_type.\n"); 224 return PTR_ERR(rapl_msr_priv->control_type); 225 } 226 227 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powercap/rapl:online", 228 rapl_cpu_online, rapl_cpu_down_prep); 229 if (ret < 0) 230 goto out; 231 rapl_msr_priv->pcap_rapl_online = ret; 232 233 return 0; 234 235 out: 236 if (ret) 237 powercap_unregister_control_type(rapl_msr_priv->control_type); 238 return ret; 239 } 240 241 static void rapl_msr_remove(struct platform_device *pdev) 242 { 243 cpuhp_remove_state(rapl_msr_priv->pcap_rapl_online); 244 powercap_unregister_control_type(rapl_msr_priv->control_type); 245 } 246 247 static const struct platform_device_id rapl_msr_ids[] = { 248 { .name = "intel_rapl_msr", }, 249 {} 250 }; 251 MODULE_DEVICE_TABLE(platform, rapl_msr_ids); 252 253 static struct platform_driver intel_rapl_msr_driver = { 254 .probe = rapl_msr_probe, 255 .remove = rapl_msr_remove, 256 .id_table = rapl_msr_ids, 257 .driver = { 258 .name = "intel_rapl_msr", 259 }, 260 }; 261 262 module_platform_driver(intel_rapl_msr_driver); 263 264 MODULE_DESCRIPTION("Driver for Intel RAPL (Running Average Power Limit) control via MSR interface"); 265 MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>"); 266 MODULE_LICENSE("GPL v2"); 267