3 * Intel RAPL (Sandy Bridge and above) Accessor
4 * (c) Kyle C. Hale, Chang Bae 2013
9 #include <asm/msr-index.h>
10 #include <linux/math64.h>
12 #include <palacios/vmm_types.h>
13 #include <palacios/vmm_util.h>
15 #include <interfaces/vmm_pwrstat.h>
19 #include "util-queue.h"
20 #include "linux-exts.h"
21 #include "iface-pwrstat.h"
33 struct rapl_domain_msr {
40 enum rapl_domain_id domain_id;
41 struct rapl_domain_msr msrs;
46 static struct rapl_domain rapl_domains[] = {
48 .domain_id = RAPL_DOMAIN_PKG,
50 .limit = MSR_PKG_POWER_LIMIT,
51 .status = MSR_PKG_ENERGY_STATUS,
56 .domain_id = RAPL_DOMAIN_PP0,
58 .limit = MSR_PP0_POWER_LIMIT,
59 .status = MSR_PP0_ENERGY_STATUS,
64 .domain_id = RAPL_DOMAIN_PP1,
66 .limit = MSR_PP1_POWER_LIMIT,
67 .status = MSR_PP1_ENERGY_STATUS,
70 [RAPL_DOMAIN_DRAM] = {
71 .domain_id = RAPL_DOMAIN_DRAM,
73 .limit = MSR_DRAM_POWER_LIMIT,
74 .status = MSR_DRAM_ENERGY_STATUS,
79 static unsigned int power_unit_divisor;
80 static unsigned int energy_unit_divisor;
81 static unsigned int time_unit_divisor;
89 static inline void cpuid_string(u32 id, u32 dest[4]) {
91 :"=a"(*dest),"=b"(*(dest+1)),"=c"(*(dest+2)),"=d"(*(dest+3))
96 static int rapl_check_unit (void)
101 rdmsrl(MSR_RAPL_POWER_UNIT, output);
103 /* energy unit: 1/enery_unit_divisor Joules */
104 value = (output & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET;
105 energy_unit_divisor = 1 << value;
107 /* power unit: 1/power_unit_divisor Watts */
108 value = (output & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET;
109 power_unit_divisor = 1 << value;
111 /* time unit: 1/time_unit_divisor Seconds */
112 value = (output & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET;
113 time_unit_divisor = 1 << value;
119 static u64 rapl_unit_xlate(enum unit_type type, u64 value, int action)
125 divisor = power_unit_divisor;
128 divisor = energy_unit_divisor;
131 divisor = time_unit_divisor;
138 return value * divisor; /* value is from users */
140 return div64_u64(value, divisor); /* value is from MSR */
144 static int rapl_read_energy(struct rapl_domain * domain)
147 u32 msr = domain->msrs.status;
150 return rapl_unit_xlate(ENERGY_UNIT, value, 0);
154 static int rapl_ctr_valid (v3_pwrstat_ctr_t ctr)
157 case V3_PWRSTAT_PKG_ENERGY:
158 return rapl_domains[RAPL_DOMAIN_PKG].valid;
159 case V3_PWRSTAT_CORE_ENERGY:
160 return rapl_domains[RAPL_DOMAIN_PP0].valid;
161 case V3_PWRSTAT_EXT_ENERGY:
162 return rapl_domains[RAPL_DOMAIN_PP1].valid;
163 case V3_PWRSTAT_DRAM_ENERGY:
164 return rapl_domains[RAPL_DOMAIN_DRAM].valid;
173 static uint64_t rapl_get_value (v3_pwrstat_ctr_t ctr)
176 case V3_PWRSTAT_PKG_ENERGY:
177 return rapl_read_energy(&rapl_domains[RAPL_DOMAIN_PKG]);
178 case V3_PWRSTAT_CORE_ENERGY:
179 return rapl_read_energy(&rapl_domains[RAPL_DOMAIN_PP0]);
180 case V3_PWRSTAT_EXT_ENERGY:
181 return rapl_read_energy(&rapl_domains[RAPL_DOMAIN_PP1]);
182 case V3_PWRSTAT_DRAM_ENERGY:
183 return rapl_read_energy(&rapl_domains[RAPL_DOMAIN_DRAM]);
185 ERROR("Invalid Powerstat Counter\n");
193 static int get_cpu_vendor (char name[13])
198 cpuid_string(0,dest);
200 ((u32*)name)[0]=dest[1];
201 ((u32*)name)[1]=dest[3];
202 ((u32*)name)[2]=dest[2];
209 static int get_cpu_model (void)
211 u32 dest[4] = {0, 0, 0, 0};
213 cpuid_string(1, dest);
214 ex_model = (dest[0] & 0xF0000U) >> 16;
215 model = (dest[0] & 0xF0U) >> 4;
216 return (model + (ex_model << 4));
220 static int supports_rapl (void)
222 unsigned int model = get_cpu_model();
224 case SANDY_BRIDGE_E3_MODEL_NO:
226 case SANDY_BRIDGE_E5_MODEL_NO:
228 case IVY_BRIDGE_MODEL_NO:
230 case HASWELL_MODEL_NO:
240 static int is_intel(void)
243 get_cpu_vendor(name);
244 return !strcmp(name,"GenuineIntel");
248 static int rapl_init (void)
250 if (supports_rapl()) {
251 INFO("Intel RAPL featureset detected\n");
253 ERROR("This machine does not support Intel RAPL functionality\n");
257 if (get_cpu_model() == SANDY_BRIDGE_E3_MODEL_NO) {
258 INFO("Sandy Bridge E3, supports PP1 (no DRAM)\n");
259 rapl_domains[RAPL_DOMAIN_PP1].valid = 1;
260 } else if (get_cpu_model() == SANDY_BRIDGE_E5_MODEL_NO) {
261 INFO("Sandy Bridge E5, supports DRAM domain\n");
262 rapl_domains[RAPL_DOMAIN_DRAM].valid = 1;
265 if (rapl_check_unit()) {
273 static int rapl_deinit (void)
275 INFO("Intel RAPL deinit\n");
280 static struct v3_pwrstat_iface intel_rapl_pwrstat = {
282 .deinit = rapl_deinit,
283 .ctr_valid = rapl_ctr_valid,
284 .get_value = rapl_get_value,
288 static int pwrstat_init (void)
291 if (supports_rapl()) {
292 INFO("Palacios Power stats using Intel RAPL\n");
293 V3_Init_Pwrstat(&intel_rapl_pwrstat);
295 INFO("Intel machine, but no RAPL functionality, so no power statistics available\n");
299 ERROR("Not an Intel Machine, no power statistics available\n");
307 static int pwrstat_deinit(void)
314 static struct linux_ext pwrstat_ext = {
316 .init = pwrstat_init,
317 .deinit = pwrstat_deinit,
322 register_extension(&pwrstat_ext);