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 28 /* Local defines */ 29 #define MSR_PLATFORM_POWER_LIMIT 0x0000065C 30 #define MSR_VR_CURRENT_CONFIG 0x00000601 31 32 /* private data for RAPL MSR Interface */ 33 static struct rapl_if_priv *rapl_msr_priv; 34 35 static struct rapl_if_priv rapl_msr_priv_intel = { 36 .type = RAPL_IF_MSR, 37 .reg_unit = MSR_RAPL_POWER_UNIT, 38 .regs[RAPL_DOMAIN_PACKAGE] = { 39 MSR_PKG_POWER_LIMIT, MSR_PKG_ENERGY_STATUS, MSR_PKG_PERF_STATUS, 0, MSR_PKG_POWER_INFO }, 40 .regs[RAPL_DOMAIN_PP0] = { 41 MSR_PP0_POWER_LIMIT, MSR_PP0_ENERGY_STATUS, 0, MSR_PP0_POLICY, 0 }, 42 .regs[RAPL_DOMAIN_PP1] = { 43 MSR_PP1_POWER_LIMIT, MSR_PP1_ENERGY_STATUS, 0, MSR_PP1_POLICY, 0 }, 44 .regs[RAPL_DOMAIN_DRAM] = { 45 MSR_DRAM_POWER_LIMIT, MSR_DRAM_ENERGY_STATUS, MSR_DRAM_PERF_STATUS, 0, MSR_DRAM_POWER_INFO }, 46 .regs[RAPL_DOMAIN_PLATFORM] = { 47 MSR_PLATFORM_POWER_LIMIT, MSR_PLATFORM_ENERGY_STATUS, 0, 0, 0}, 48 .limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2), 49 .limits[RAPL_DOMAIN_PLATFORM] = BIT(POWER_LIMIT2), 50 }; 51 52 static struct rapl_if_priv rapl_msr_priv_amd = { 53 .type = RAPL_IF_MSR, 54 .reg_unit = MSR_AMD_RAPL_POWER_UNIT, 55 .regs[RAPL_DOMAIN_PACKAGE] = { 56 0, MSR_AMD_PKG_ENERGY_STATUS, 0, 0, 0 }, 57 .regs[RAPL_DOMAIN_PP0] = { 58 0, MSR_AMD_CORE_ENERGY_STATUS, 0, 0, 0 }, 59 }; 60 61 /* Handles CPU hotplug on multi-socket systems. 62 * If a CPU goes online as the first CPU of the physical package 63 * we add the RAPL package to the system. Similarly, when the last 64 * CPU of the package is removed, we remove the RAPL package and its 65 * associated domains. Cooling devices are handled accordingly at 66 * per-domain level. 67 */ 68 static int rapl_cpu_online(unsigned int cpu) 69 { 70 struct rapl_package *rp; 71 72 rp = rapl_find_package_domain(cpu, rapl_msr_priv, true); 73 if (!rp) { 74 rp = rapl_add_package(cpu, rapl_msr_priv, true); 75 if (IS_ERR(rp)) 76 return PTR_ERR(rp); 77 } 78 cpumask_set_cpu(cpu, &rp->cpumask); 79 return 0; 80 } 81 82 static int rapl_cpu_down_prep(unsigned int cpu) 83 { 84 struct rapl_package *rp; 85 int lead_cpu; 86 87 rp = rapl_find_package_domain(cpu, rapl_msr_priv, true); 88 if (!rp) 89 return 0; 90 91 cpumask_clear_cpu(cpu, &rp->cpumask); 92 lead_cpu = cpumask_first(&rp->cpumask); 93 if (lead_cpu >= nr_cpu_ids) 94 rapl_remove_package(rp); 95 else if (rp->lead_cpu == cpu) 96 rp->lead_cpu = lead_cpu; 97 return 0; 98 } 99 100 static int rapl_msr_read_raw(int cpu, struct reg_action *ra) 101 { 102 u32 msr = (u32)ra->reg; 103 104 if (rdmsrl_safe_on_cpu(cpu, msr, &ra->value)) { 105 pr_debug("failed to read msr 0x%x on cpu %d\n", msr, cpu); 106 return -EIO; 107 } 108 ra->value &= ra->mask; 109 return 0; 110 } 111 112 static void rapl_msr_update_func(void *info) 113 { 114 struct reg_action *ra = info; 115 u32 msr = (u32)ra->reg; 116 u64 val; 117 118 ra->err = rdmsrl_safe(msr, &val); 119 if (ra->err) 120 return; 121 122 val &= ~ra->mask; 123 val |= ra->value; 124 125 ra->err = wrmsrl_safe(msr, val); 126 } 127 128 static int rapl_msr_write_raw(int cpu, struct reg_action *ra) 129 { 130 int ret; 131 132 ret = smp_call_function_single(cpu, rapl_msr_update_func, ra, 1); 133 if (WARN_ON_ONCE(ret)) 134 return ret; 135 136 return ra->err; 137 } 138 139 /* List of verified CPUs. */ 140 static const struct x86_cpu_id pl4_support_ids[] = { 141 X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, NULL), 142 X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, NULL), 143 X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, NULL), 144 X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, NULL), 145 X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, NULL), 146 X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, NULL), 147 X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE, NULL), 148 X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE_L, NULL), 149 {} 150 }; 151 152 static int rapl_msr_probe(struct platform_device *pdev) 153 { 154 const struct x86_cpu_id *id = x86_match_cpu(pl4_support_ids); 155 int ret; 156 157 switch (boot_cpu_data.x86_vendor) { 158 case X86_VENDOR_INTEL: 159 rapl_msr_priv = &rapl_msr_priv_intel; 160 break; 161 case X86_VENDOR_HYGON: 162 case X86_VENDOR_AMD: 163 rapl_msr_priv = &rapl_msr_priv_amd; 164 break; 165 default: 166 pr_err("intel-rapl does not support CPU vendor %d\n", boot_cpu_data.x86_vendor); 167 return -ENODEV; 168 } 169 rapl_msr_priv->read_raw = rapl_msr_read_raw; 170 rapl_msr_priv->write_raw = rapl_msr_write_raw; 171 172 if (id) { 173 rapl_msr_priv->limits[RAPL_DOMAIN_PACKAGE] |= BIT(POWER_LIMIT4); 174 rapl_msr_priv->regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PL4] = 175 MSR_VR_CURRENT_CONFIG; 176 pr_info("PL4 support detected.\n"); 177 } 178 179 rapl_msr_priv->control_type = powercap_register_control_type(NULL, "intel-rapl", NULL); 180 if (IS_ERR(rapl_msr_priv->control_type)) { 181 pr_debug("failed to register powercap control_type.\n"); 182 return PTR_ERR(rapl_msr_priv->control_type); 183 } 184 185 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powercap/rapl:online", 186 rapl_cpu_online, rapl_cpu_down_prep); 187 if (ret < 0) 188 goto out; 189 rapl_msr_priv->pcap_rapl_online = ret; 190 191 return 0; 192 193 out: 194 if (ret) 195 powercap_unregister_control_type(rapl_msr_priv->control_type); 196 return ret; 197 } 198 199 static int rapl_msr_remove(struct platform_device *pdev) 200 { 201 cpuhp_remove_state(rapl_msr_priv->pcap_rapl_online); 202 powercap_unregister_control_type(rapl_msr_priv->control_type); 203 return 0; 204 } 205 206 static const struct platform_device_id rapl_msr_ids[] = { 207 { .name = "intel_rapl_msr", }, 208 {} 209 }; 210 MODULE_DEVICE_TABLE(platform, rapl_msr_ids); 211 212 static struct platform_driver intel_rapl_msr_driver = { 213 .probe = rapl_msr_probe, 214 .remove = rapl_msr_remove, 215 .id_table = rapl_msr_ids, 216 .driver = { 217 .name = "intel_rapl_msr", 218 }, 219 }; 220 221 module_platform_driver(intel_rapl_msr_driver); 222 223 MODULE_DESCRIPTION("Driver for Intel RAPL (Running Average Power Limit) control via MSR interface"); 224 MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>"); 225 MODULE_LICENSE("GPL v2"); 226