Lines Matching +full:energy +full:- +full:empty
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Support Intel/AMD RAPL energy consumption counters
6 * Intel RAPL interface is specified in the IA-32 Manual Vol3b
12 * RAPL provides more controls than just reporting energy consumption
13 * however here we only expose the 3 energy consumption free running
34 * gpu counter: consumption of the builtin-gpu domain (client only)
38 * psys counter: consumption of the builtin-psys domain (client only)
42 * We manage those counters as free running (read-only). They may be
45 * The events only support system-wide mode counting. There is no
49 * Because we want to avoid floating-point operations in the kernel,
53 * ldexp(raw_count, -32);
63 #include <asm/intel-family.h>
70 * RAPL energy status counters
84 "pp0-core",
87 "pp1-gpu",
92 * event code: LSB 8 bits, passed in attr->config
147 * The unsigned check also catches the '-1' return value for non in cpu_to_rapl_pmu()
150 return dieid < rapl_pmus->maxdie ? rapl_pmus->pmus[dieid] : NULL; in cpu_to_rapl_pmu()
156 rdmsrl(event->hw.event_base, raw); in rapl_read_counter()
169 * or use ldexp(count, -32). in rapl_scale()
172 return v << (32 - rapl_hw_unit[cfg - 1]); in rapl_scale()
177 struct hw_perf_event *hwc = &event->hw; in rapl_event_update()
183 prev_raw_count = local64_read(&hwc->prev_count); in rapl_event_update()
184 rdmsrl(event->hw.event_base, new_raw_count); in rapl_event_update()
186 if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, in rapl_event_update()
195 * (event-)time and add that to the generic event. in rapl_event_update()
197 * Careful, not all hw sign-extends above the physical width in rapl_event_update()
200 delta = (new_raw_count << shift) - (prev_raw_count << shift); in rapl_event_update()
203 sdelta = rapl_scale(delta, event->hw.config); in rapl_event_update()
205 local64_add(sdelta, &event->count); in rapl_event_update()
212 hrtimer_start(&pmu->hrtimer, pmu->timer_interval, in rapl_start_hrtimer()
222 if (!pmu->n_active) in rapl_hrtimer_handle()
225 raw_spin_lock_irqsave(&pmu->lock, flags); in rapl_hrtimer_handle()
227 list_for_each_entry(event, &pmu->active_list, active_entry) in rapl_hrtimer_handle()
230 raw_spin_unlock_irqrestore(&pmu->lock, flags); in rapl_hrtimer_handle()
232 hrtimer_forward_now(hrtimer, pmu->timer_interval); in rapl_hrtimer_handle()
239 struct hrtimer *hr = &pmu->hrtimer; in rapl_hrtimer_init()
242 hr->function = rapl_hrtimer_handle; in rapl_hrtimer_init()
248 if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED))) in __rapl_pmu_event_start()
251 event->hw.state = 0; in __rapl_pmu_event_start()
253 list_add_tail(&event->active_entry, &pmu->active_list); in __rapl_pmu_event_start()
255 local64_set(&event->hw.prev_count, rapl_read_counter(event)); in __rapl_pmu_event_start()
257 pmu->n_active++; in __rapl_pmu_event_start()
258 if (pmu->n_active == 1) in __rapl_pmu_event_start()
264 struct rapl_pmu *pmu = event->pmu_private; in rapl_pmu_event_start()
267 raw_spin_lock_irqsave(&pmu->lock, flags); in rapl_pmu_event_start()
269 raw_spin_unlock_irqrestore(&pmu->lock, flags); in rapl_pmu_event_start()
274 struct rapl_pmu *pmu = event->pmu_private; in rapl_pmu_event_stop()
275 struct hw_perf_event *hwc = &event->hw; in rapl_pmu_event_stop()
278 raw_spin_lock_irqsave(&pmu->lock, flags); in rapl_pmu_event_stop()
281 if (!(hwc->state & PERF_HES_STOPPED)) { in rapl_pmu_event_stop()
282 WARN_ON_ONCE(pmu->n_active <= 0); in rapl_pmu_event_stop()
283 pmu->n_active--; in rapl_pmu_event_stop()
284 if (pmu->n_active == 0) in rapl_pmu_event_stop()
285 hrtimer_cancel(&pmu->hrtimer); in rapl_pmu_event_stop()
287 list_del(&event->active_entry); in rapl_pmu_event_stop()
289 WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED); in rapl_pmu_event_stop()
290 hwc->state |= PERF_HES_STOPPED; in rapl_pmu_event_stop()
294 if ((mode & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) { in rapl_pmu_event_stop()
300 hwc->state |= PERF_HES_UPTODATE; in rapl_pmu_event_stop()
303 raw_spin_unlock_irqrestore(&pmu->lock, flags); in rapl_pmu_event_stop()
308 struct rapl_pmu *pmu = event->pmu_private; in rapl_pmu_event_add()
309 struct hw_perf_event *hwc = &event->hw; in rapl_pmu_event_add()
312 raw_spin_lock_irqsave(&pmu->lock, flags); in rapl_pmu_event_add()
314 hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED; in rapl_pmu_event_add()
319 raw_spin_unlock_irqrestore(&pmu->lock, flags); in rapl_pmu_event_add()
331 u64 cfg = event->attr.config & RAPL_EVENT_MASK; in rapl_pmu_event_init()
336 if (event->attr.type != rapl_pmus->pmu.type) in rapl_pmu_event_init()
337 return -ENOENT; in rapl_pmu_event_init()
340 if (event->attr.config & ~RAPL_EVENT_MASK) in rapl_pmu_event_init()
341 return -EINVAL; in rapl_pmu_event_init()
343 if (event->cpu < 0) in rapl_pmu_event_init()
344 return -EINVAL; in rapl_pmu_event_init()
346 event->event_caps |= PERF_EV_CAP_READ_ACTIVE_PKG; in rapl_pmu_event_init()
349 return -EINVAL; in rapl_pmu_event_init()
352 bit = cfg - 1; in rapl_pmu_event_init()
356 return -EINVAL; in rapl_pmu_event_init()
359 if (event->attr.sample_period) /* no sampling */ in rapl_pmu_event_init()
360 return -EINVAL; in rapl_pmu_event_init()
363 pmu = cpu_to_rapl_pmu(event->cpu); in rapl_pmu_event_init()
365 return -EINVAL; in rapl_pmu_event_init()
366 event->cpu = pmu->cpu; in rapl_pmu_event_init()
367 event->pmu_private = pmu; in rapl_pmu_event_init()
368 event->hw.event_base = rapl_msrs[bit].msr; in rapl_pmu_event_init()
369 event->hw.config = cfg; in rapl_pmu_event_init()
370 event->hw.idx = bit; in rapl_pmu_event_init()
397 RAPL_EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01");
398 RAPL_EVENT_ATTR_STR(energy-pkg , rapl_pkg, "event=0x02");
399 RAPL_EVENT_ATTR_STR(energy-ram , rapl_ram, "event=0x03");
400 RAPL_EVENT_ATTR_STR(energy-gpu , rapl_gpu, "event=0x04");
401 RAPL_EVENT_ATTR_STR(energy-psys, rapl_psys, "event=0x05");
403 RAPL_EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules");
404 RAPL_EVENT_ATTR_STR(energy-pkg.unit , rapl_pkg_unit, "Joules");
405 RAPL_EVENT_ATTR_STR(energy-ram.unit , rapl_ram_unit, "Joules");
406 RAPL_EVENT_ATTR_STR(energy-gpu.unit , rapl_gpu_unit, "Joules");
407 RAPL_EVENT_ATTR_STR(energy-psys.unit, rapl_psys_unit, "Joules");
412 RAPL_EVENT_ATTR_STR(energy-cores.scale, rapl_cores_scale, "2.3283064365386962890625e-10");
413 RAPL_EVENT_ATTR_STR(energy-pkg.scale, rapl_pkg_scale, "2.3283064365386962890625e-10");
414 RAPL_EVENT_ATTR_STR(energy-ram.scale, rapl_ram_scale, "2.3283064365386962890625e-10");
415 RAPL_EVENT_ATTR_STR(energy-gpu.scale, rapl_gpu_scale, "2.3283064365386962890625e-10");
416 RAPL_EVENT_ATTR_STR(energy-psys.scale, rapl_psys_scale, "2.3283064365386962890625e-10");
420 * "events" group (with empty attrs) before updating
432 PMU_FORMAT_ATTR(event, "config:0-7");
515 /* Only lower 32bits of the MSR represents the energy counter */
536 * - perf_msr_probe(PERF_RAPL_MAX)
537 * - want to use same event codes across both architectures
556 pmu->cpu = -1; in rapl_cpu_offline()
563 pmu->cpu = target; in rapl_cpu_offline()
564 perf_pmu_migrate_context(pmu->pmu, cpu, target); in rapl_cpu_offline()
577 return -ENOMEM; in rapl_cpu_online()
579 raw_spin_lock_init(&pmu->lock); in rapl_cpu_online()
580 INIT_LIST_HEAD(&pmu->active_list); in rapl_cpu_online()
581 pmu->pmu = &rapl_pmus->pmu; in rapl_cpu_online()
582 pmu->timer_interval = ms_to_ktime(rapl_timer_ms); in rapl_cpu_online()
585 rapl_pmus->pmus[topology_logical_die_id(cpu)] = pmu; in rapl_cpu_online()
597 pmu->cpu = cpu; in rapl_cpu_online()
607 if (rdmsrl_safe(rm->msr_power_unit, &msr_rapl_power_unit_bits)) in rapl_check_hw_unit()
608 return -1; in rapl_check_hw_unit()
612 switch (rm->unit_quirk) { in rapl_check_hw_unit()
614 * DRAM domain on HSW server and KNL has fixed energy unit which can be in rapl_check_hw_unit()
616 * "Intel Xeon Processor E5-1600 and E5-2600 v3 Product Families, V2 in rapl_check_hw_unit()
617 * of 2. Datasheet, September 2014, Reference Number: 330784-001 " in rapl_check_hw_unit()
622 /* SPR uses a fixed energy unit for Psys domain. */ in rapl_check_hw_unit()
641 rapl_timer_ms *= (1ULL << (32 - rapl_hw_unit[0] - 1)); in rapl_check_hw_unit()
650 pr_info("API unit is 2^-32 Joules, %d fixed counters, %llu ms ovfl timer\n", in rapl_advertise()
655 pr_info("hw unit of domain %s 2^-%d Joules\n", in rapl_advertise()
665 for (i = 0; i < rapl_pmus->maxdie; i++) in cleanup_rapl_pmus()
666 kfree(rapl_pmus->pmus[i]); in cleanup_rapl_pmus()
687 return -ENOMEM; in init_rapl_pmus()
689 rapl_pmus->maxdie = maxdie; in init_rapl_pmus()
690 rapl_pmus->pmu.attr_groups = rapl_attr_groups; in init_rapl_pmus()
691 rapl_pmus->pmu.attr_update = rapl_attr_update; in init_rapl_pmus()
692 rapl_pmus->pmu.task_ctx_nr = perf_invalid_context; in init_rapl_pmus()
693 rapl_pmus->pmu.event_init = rapl_pmu_event_init; in init_rapl_pmus()
694 rapl_pmus->pmu.add = rapl_pmu_event_add; in init_rapl_pmus()
695 rapl_pmus->pmu.del = rapl_pmu_event_del; in init_rapl_pmus()
696 rapl_pmus->pmu.start = rapl_pmu_event_start; in init_rapl_pmus()
697 rapl_pmus->pmu.stop = rapl_pmu_event_stop; in init_rapl_pmus()
698 rapl_pmus->pmu.read = rapl_pmu_event_read; in init_rapl_pmus()
699 rapl_pmus->pmu.module = THIS_MODULE; in init_rapl_pmus()
700 rapl_pmus->pmu.capabilities = PERF_PMU_CAP_NO_EXCLUDE; in init_rapl_pmus()
827 return -ENODEV; in rapl_pmu_init()
829 rm = (struct rapl_model *) id->driver_data; in rapl_pmu_init()
831 rapl_msrs = rm->rapl_msrs; in rapl_pmu_init()
834 false, (void *) &rm->events); in rapl_pmu_init()
853 ret = perf_pmu_register(&rapl_pmus->pmu, "power", -1); in rapl_pmu_init()
872 perf_pmu_unregister(&rapl_pmus->pmu); in intel_rapl_exit()