linux/arch/x86/events/rapl.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Support Intel/AMD RAPL energy consumption counters
 * Copyright (C) 2013 Google, Inc., Stephane Eranian
 *
 * Intel RAPL interface is specified in the IA-32 Manual Vol3b
 * section 14.7.1 (September 2013)
 *
 * AMD RAPL interface for Fam17h is described in the public PPR:
 * https://bugzilla.kernel.org/show_bug.cgi?id=206537
 *
 * RAPL provides more controls than just reporting energy consumption
 * however here we only expose the 3 energy consumption free running
 * counters (pp0, pkg, dram).
 *
 * Each of those counters increments in a power unit defined by the
 * RAPL_POWER_UNIT MSR. On SandyBridge, this unit is 1/(2^16) Joules
 * but it can vary.
 *
 * Counter to rapl events mappings:
 *
 *  pp0 counter: consumption of all physical cores (power plane 0)
 * 	  event: rapl_energy_cores
 *    perf code: 0x1
 *
 *  pkg counter: consumption of the whole processor package
 *	  event: rapl_energy_pkg
 *    perf code: 0x2
 *
 * dram counter: consumption of the dram domain (servers only)
 *	  event: rapl_energy_dram
 *    perf code: 0x3
 *
 * gpu counter: consumption of the builtin-gpu domain (client only)
 *	  event: rapl_energy_gpu
 *    perf code: 0x4
 *
 *  psys counter: consumption of the builtin-psys domain (client only)
 *	  event: rapl_energy_psys
 *    perf code: 0x5
 *
 * We manage those counters as free running (read-only). They may be
 * use simultaneously by other tools, such as turbostat.
 *
 * The events only support system-wide mode counting. There is no
 * sampling support because it does not make sense and is not
 * supported by the RAPL hardware.
 *
 * Because we want to avoid floating-point operations in the kernel,
 * the events are all reported in fixed point arithmetic (32.32).
 * Tools must adjust the counts to convert them to Watts using
 * the duration of the measurement. Tools may use a function such as
 * ldexp(raw_count, -32);
 */

#define pr_fmt(fmt)

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/perf_event.h>
#include <linux/nospec.h>
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
#include "perf_event.h"
#include "probe.h"

MODULE_DESCRIPTION();
MODULE_LICENSE();

/*
 * RAPL energy status counters
 */
enum perf_rapl_events {};

static const char *const rapl_domain_names[NR_RAPL_DOMAINS] __initconst =;

/*
 * event code: LSB 8 bits, passed in attr->config
 * any other bit is reserved
 */
#define RAPL_EVENT_MASK
#define RAPL_CNTR_WIDTH

#define RAPL_EVENT_ATTR_STR(_name, v, str)

struct rapl_pmu {};

struct rapl_pmus {};

enum rapl_unit_quirk {};

struct rapl_model {};

 /* 1/2^hw_unit Joule */
static int rapl_hw_unit[NR_RAPL_DOMAINS] __read_mostly;
static struct rapl_pmus *rapl_pmus;
static cpumask_t rapl_cpu_mask;
static unsigned int rapl_cntr_mask;
static u64 rapl_timer_ms;
static struct perf_msr *rapl_msrs;

static inline struct rapl_pmu *cpu_to_rapl_pmu(unsigned int cpu)
{}

static inline u64 rapl_read_counter(struct perf_event *event)
{}

static inline u64 rapl_scale(u64 v, int cfg)
{}

static u64 rapl_event_update(struct perf_event *event)
{}

static void rapl_start_hrtimer(struct rapl_pmu *pmu)
{}

static enum hrtimer_restart rapl_hrtimer_handle(struct hrtimer *hrtimer)
{}

static void rapl_hrtimer_init(struct rapl_pmu *pmu)
{}

static void __rapl_pmu_event_start(struct rapl_pmu *pmu,
				   struct perf_event *event)
{}

static void rapl_pmu_event_start(struct perf_event *event, int mode)
{}

static void rapl_pmu_event_stop(struct perf_event *event, int mode)
{}

static int rapl_pmu_event_add(struct perf_event *event, int mode)
{}

static void rapl_pmu_event_del(struct perf_event *event, int flags)
{}

static int rapl_pmu_event_init(struct perf_event *event)
{}

static void rapl_pmu_event_read(struct perf_event *event)
{}

static ssize_t rapl_get_attr_cpumask(struct device *dev,
				struct device_attribute *attr, char *buf)
{}

static DEVICE_ATTR(cpumask, S_IRUGO, rapl_get_attr_cpumask, NULL);

static struct attribute *rapl_pmu_attrs[] =;

static struct attribute_group rapl_pmu_attr_group =;

RAPL_EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01");
RAPL_EVENT_ATTR_STR(energy-pkg  ,   rapl_pkg, "event=0x02");
RAPL_EVENT_ATTR_STR(energy-ram  ,   rapl_ram, "event=0x03");
RAPL_EVENT_ATTR_STR(energy-gpu  ,   rapl_gpu, "event=0x04");
RAPL_EVENT_ATTR_STR(energy-psys,   rapl_psys, "event=0x05");

RAPL_EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules");
RAPL_EVENT_ATTR_STR(energy-pkg.unit  ,   rapl_pkg_unit, "Joules");
RAPL_EVENT_ATTR_STR(energy-ram.unit  ,   rapl_ram_unit, "Joules");
RAPL_EVENT_ATTR_STR(energy-gpu.unit  ,   rapl_gpu_unit, "Joules");
RAPL_EVENT_ATTR_STR(energy-psys.unit,   rapl_psys_unit, "Joules");

/*
 * we compute in 0.23 nJ increments regardless of MSR
 */
RAPL_EVENT_ATTR_STR(energy-cores.scale, rapl_cores_scale, "2.3283064365386962890625e-10");
RAPL_EVENT_ATTR_STR(energy-pkg.scale,     rapl_pkg_scale, "2.3283064365386962890625e-10");
RAPL_EVENT_ATTR_STR(energy-ram.scale,     rapl_ram_scale, "2.3283064365386962890625e-10");
RAPL_EVENT_ATTR_STR(energy-gpu.scale,     rapl_gpu_scale, "2.3283064365386962890625e-10");
RAPL_EVENT_ATTR_STR(energy-psys.scale,   rapl_psys_scale, "2.3283064365386962890625e-10");

/*
 * There are no default events, but we need to create
 * "events" group (with empty attrs) before updating
 * it with detected events.
 */
static struct attribute *attrs_empty[] =;

static struct attribute_group rapl_pmu_events_group =;

PMU_FORMAT_ATTR();
static struct attribute *rapl_formats_attr[] =;

static struct attribute_group rapl_pmu_format_group =;

static const struct attribute_group *rapl_attr_groups[] =;

static struct attribute *rapl_events_cores[] =;

static struct attribute_group rapl_events_cores_group =;

static struct attribute *rapl_events_pkg[] =;

static struct attribute_group rapl_events_pkg_group =;

static struct attribute *rapl_events_ram[] =;

static struct attribute_group rapl_events_ram_group =;

static struct attribute *rapl_events_gpu[] =;

static struct attribute_group rapl_events_gpu_group =;

static struct attribute *rapl_events_psys[] =;

static struct attribute_group rapl_events_psys_group =;

static bool test_msr(int idx, void *data)
{}

/* Only lower 32bits of the MSR represents the energy counter */
#define RAPL_MSR_MASK

static struct perf_msr intel_rapl_msrs[] =;

static struct perf_msr intel_rapl_spr_msrs[] =;

/*
 * Force to PERF_RAPL_MAX size due to:
 * - perf_msr_probe(PERF_RAPL_MAX)
 * - want to use same event codes across both architectures
 */
static struct perf_msr amd_rapl_msrs[] =;

static int rapl_cpu_offline(unsigned int cpu)
{}

static int rapl_cpu_online(unsigned int cpu)
{}

static int rapl_check_hw_unit(struct rapl_model *rm)
{}

static void __init rapl_advertise(void)
{}

static void cleanup_rapl_pmus(void)
{}

static const struct attribute_group *rapl_attr_update[] =;

static int __init init_rapl_pmus(void)
{}

static struct rapl_model model_snb =;

static struct rapl_model model_snbep =;

static struct rapl_model model_hsw =;

static struct rapl_model model_hsx =;

static struct rapl_model model_knl =;

static struct rapl_model model_skl =;

static struct rapl_model model_spr =;

static struct rapl_model model_amd_hygon =;

static const struct x86_cpu_id rapl_model_match[] __initconst =;
MODULE_DEVICE_TABLE(x86cpu, rapl_model_match);

static int __init rapl_pmu_init(void)
{}
module_init();

static void __exit intel_rapl_exit(void)
{}
module_exit(intel_rapl_exit);