linux/arch/x86/events/intel/cstate.c

/*
 * Support cstate residency counters
 *
 * Copyright (C) 2015, Intel Corp.
 * Author: Kan Liang ([email protected])
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 */

/*
 * This file export cstate related free running (read-only) counters
 * for perf. These counters may be use simultaneously by other tools,
 * such as turbostat. However, it still make sense to implement them
 * in perf. Because we can conveniently collect them together with
 * other events, and allow to use them from tools without special MSR
 * access code.
 *
 * The events only support system-wide mode counting. There is no
 * sampling support because it is not supported by the hardware.
 *
 * According to counters' scope and category, two PMUs are registered
 * with the perf_event core subsystem.
 *  - 'cstate_core': The counter is available for each physical core.
 *    The counters include CORE_C*_RESIDENCY.
 *  - 'cstate_pkg': The counter is available for each physical package.
 *    The counters include PKG_C*_RESIDENCY.
 *
 * All of these counters are specified in the Intel® 64 and IA-32
 * Architectures Software Developer.s Manual Vol3b.
 *
 * Model specific counters:
 *	MSR_CORE_C1_RES: CORE C1 Residency Counter
 *			 perf code: 0x00
 *			 Available model: SLM,AMT,GLM,CNL,ICX,TNT,ADL,RPL
 *					  MTL,SRF,GRR,ARL,LNL
 *			 Scope: Core (each processor core has a MSR)
 *	MSR_CORE_C3_RESIDENCY: CORE C3 Residency Counter
 *			       perf code: 0x01
 *			       Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,GLM,
 *						CNL,KBL,CML,TNT
 *			       Scope: Core
 *	MSR_CORE_C6_RESIDENCY: CORE C6 Residency Counter
 *			       perf code: 0x02
 *			       Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,
 *						SKL,KNL,GLM,CNL,KBL,CML,ICL,ICX,
 *						TGL,TNT,RKL,ADL,RPL,SPR,MTL,SRF,
 *						GRR,ARL,LNL
 *			       Scope: Core
 *	MSR_CORE_C7_RESIDENCY: CORE C7 Residency Counter
 *			       perf code: 0x03
 *			       Available model: SNB,IVB,HSW,BDW,SKL,CNL,KBL,CML,
 *						ICL,TGL,RKL,ADL,RPL,MTL,ARL,LNL
 *			       Scope: Core
 *	MSR_PKG_C2_RESIDENCY:  Package C2 Residency Counter.
 *			       perf code: 0x00
 *			       Available model: SNB,IVB,HSW,BDW,SKL,KNL,GLM,CNL,
 *						KBL,CML,ICL,ICX,TGL,TNT,RKL,ADL,
 *						RPL,SPR,MTL,ARL,LNL,SRF
 *			       Scope: Package (physical package)
 *	MSR_PKG_C3_RESIDENCY:  Package C3 Residency Counter.
 *			       perf code: 0x01
 *			       Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,KNL,
 *						GLM,CNL,KBL,CML,ICL,TGL,TNT,RKL,
 *						ADL,RPL,MTL,ARL,LNL
 *			       Scope: Package (physical package)
 *	MSR_PKG_C6_RESIDENCY:  Package C6 Residency Counter.
 *			       perf code: 0x02
 *			       Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,
 *						SKL,KNL,GLM,CNL,KBL,CML,ICL,ICX,
 *						TGL,TNT,RKL,ADL,RPL,SPR,MTL,SRF,
 *						ARL,LNL
 *			       Scope: Package (physical package)
 *	MSR_PKG_C7_RESIDENCY:  Package C7 Residency Counter.
 *			       perf code: 0x03
 *			       Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,CNL,
 *						KBL,CML,ICL,TGL,RKL
 *			       Scope: Package (physical package)
 *	MSR_PKG_C8_RESIDENCY:  Package C8 Residency Counter.
 *			       perf code: 0x04
 *			       Available model: HSW ULT,KBL,CNL,CML,ICL,TGL,RKL,
 *						ADL,RPL,MTL,ARL
 *			       Scope: Package (physical package)
 *	MSR_PKG_C9_RESIDENCY:  Package C9 Residency Counter.
 *			       perf code: 0x05
 *			       Available model: HSW ULT,KBL,CNL,CML,ICL,TGL,RKL
 *			       Scope: Package (physical package)
 *	MSR_PKG_C10_RESIDENCY: Package C10 Residency Counter.
 *			       perf code: 0x06
 *			       Available model: HSW ULT,KBL,GLM,CNL,CML,ICL,TGL,
 *						TNT,RKL,ADL,RPL,MTL,ARL,LNL
 *			       Scope: Package (physical package)
 *	MSR_MODULE_C6_RES_MS:  Module C6 Residency Counter.
 *			       perf code: 0x00
 *			       Available model: SRF,GRR
 *			       Scope: A cluster of cores shared L2 cache
 *
 */

#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();

#define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format)

static ssize_t cstate_get_attr_cpumask(struct device *dev,
				       struct device_attribute *attr,
				       char *buf);

/* Model -> events mapping */
struct cstate_model {};

/* Quirk flags */
#define SLM_PKG_C6_USE_C7_MSR
#define KNL_CORE_C6_MSR

/* cstate_core PMU */
static struct pmu cstate_core_pmu;
static bool has_cstate_core;

enum perf_cstate_core_events {};

PMU_EVENT_ATTR_STRING(c1-residency, attr_cstate_core_c1, "event=0x00");
PMU_EVENT_ATTR_STRING(c3-residency, attr_cstate_core_c3, "event=0x01");
PMU_EVENT_ATTR_STRING(c6-residency, attr_cstate_core_c6, "event=0x02");
PMU_EVENT_ATTR_STRING(c7-residency, attr_cstate_core_c7, "event=0x03");

static unsigned long core_msr_mask;

PMU_EVENT_GROUP();
PMU_EVENT_GROUP();
PMU_EVENT_GROUP();
PMU_EVENT_GROUP();

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

static struct perf_msr core_msr[] =;

static struct attribute *attrs_empty[] =;

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

DEFINE_CSTATE_FORMAT_ATTR();
static struct attribute *cstate_format_attrs[] =;

static struct attribute_group cstate_format_attr_group =;

static cpumask_t cstate_core_cpu_mask;
static DEVICE_ATTR(cpumask, S_IRUGO, cstate_get_attr_cpumask, NULL);

static struct attribute *cstate_cpumask_attrs[] =;

static struct attribute_group cpumask_attr_group =;

static const struct attribute_group *cstate_attr_groups[] =;

/* cstate_pkg PMU */
static struct pmu cstate_pkg_pmu;
static bool has_cstate_pkg;

enum perf_cstate_pkg_events {};

PMU_EVENT_ATTR_STRING(c2-residency,  attr_cstate_pkg_c2,  "event=0x00");
PMU_EVENT_ATTR_STRING(c3-residency,  attr_cstate_pkg_c3,  "event=0x01");
PMU_EVENT_ATTR_STRING(c6-residency,  attr_cstate_pkg_c6,  "event=0x02");
PMU_EVENT_ATTR_STRING(c7-residency,  attr_cstate_pkg_c7,  "event=0x03");
PMU_EVENT_ATTR_STRING(c8-residency,  attr_cstate_pkg_c8,  "event=0x04");
PMU_EVENT_ATTR_STRING(c9-residency,  attr_cstate_pkg_c9,  "event=0x05");
PMU_EVENT_ATTR_STRING(c10-residency, attr_cstate_pkg_c10, "event=0x06");

static unsigned long pkg_msr_mask;

PMU_EVENT_GROUP();
PMU_EVENT_GROUP();
PMU_EVENT_GROUP();
PMU_EVENT_GROUP();
PMU_EVENT_GROUP();
PMU_EVENT_GROUP();
PMU_EVENT_GROUP();

static struct perf_msr pkg_msr[] =;

static cpumask_t cstate_pkg_cpu_mask;

/* cstate_module PMU */
static struct pmu cstate_module_pmu;
static bool has_cstate_module;

enum perf_cstate_module_events {};

PMU_EVENT_ATTR_STRING(c6-residency, attr_cstate_module_c6, "event=0x00");

static unsigned long module_msr_mask;

PMU_EVENT_GROUP();

static struct perf_msr module_msr[] =;

static cpumask_t cstate_module_cpu_mask;

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

static int cstate_pmu_event_init(struct perf_event *event)
{}

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

static void cstate_pmu_event_update(struct perf_event *event)
{}

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

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

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

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

/*
 * Check if exiting cpu is the designated reader. If so migrate the
 * events when there is a valid target available
 */
static int cstate_cpu_exit(unsigned int cpu)
{}

static int cstate_cpu_init(unsigned int cpu)
{}

static const struct attribute_group *core_attr_update[] =;

static const struct attribute_group *pkg_attr_update[] =;

static const struct attribute_group *module_attr_update[] =;

static struct pmu cstate_core_pmu =;

static struct pmu cstate_pkg_pmu =;

static struct pmu cstate_module_pmu =;

static const struct cstate_model nhm_cstates __initconst =;

static const struct cstate_model snb_cstates __initconst =;

static const struct cstate_model hswult_cstates __initconst =;

static const struct cstate_model cnl_cstates __initconst =;

static const struct cstate_model icl_cstates __initconst =;

static const struct cstate_model icx_cstates __initconst =;

static const struct cstate_model adl_cstates __initconst =;

static const struct cstate_model lnl_cstates __initconst =;

static const struct cstate_model slm_cstates __initconst =;


static const struct cstate_model knl_cstates __initconst =;


static const struct cstate_model glm_cstates __initconst =;

static const struct cstate_model grr_cstates __initconst =;

static const struct cstate_model srf_cstates __initconst =;


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

static int __init cstate_probe(const struct cstate_model *cm)
{}

static inline void cstate_cleanup(void)
{}

static int __init cstate_init(void)
{}

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

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