Commit 4b6e2571 authored by Kan Liang's avatar Kan Liang Committed by Ingo Molnar

x86/perf/intel/rapl: Make the Intel RAPL PMU driver modular

By default, the RAPL driver will be built into the kernel. If it is
configured as a module, the supported CPU model can be auto loaded.

Also clean up the code of rapl_pmu_init().
Based-on-a-patch-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarKan Liang <kan.liang@intel.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Reviewed-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Link: http://lkml.kernel.org/r/1458372050-2420-2-git-send-email-kan.liang@intel.comSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent e633c65a
...@@ -8,4 +8,12 @@ config PERF_EVENTS_INTEL_UNCORE ...@@ -8,4 +8,12 @@ config PERF_EVENTS_INTEL_UNCORE
Include support for Intel uncore performance events. These are Include support for Intel uncore performance events. These are
available on NehalemEX and more modern processors. available on NehalemEX and more modern processors.
config PERF_EVENTS_INTEL_RAPL
tristate "Intel rapl performance events"
depends on PERF_EVENTS && CPU_SUP_INTEL && PCI
default y
---help---
Include support for Intel rapl performance events for power
monitoring on modern processors.
endmenu endmenu
obj-$(CONFIG_CPU_SUP_INTEL) += core.o bts.o cqm.o obj-$(CONFIG_CPU_SUP_INTEL) += core.o bts.o cqm.o
obj-$(CONFIG_CPU_SUP_INTEL) += cstate.o ds.o knc.o obj-$(CONFIG_CPU_SUP_INTEL) += cstate.o ds.o knc.o
obj-$(CONFIG_CPU_SUP_INTEL) += lbr.o p4.o p6.o pt.o obj-$(CONFIG_CPU_SUP_INTEL) += lbr.o p4.o p6.o pt.o
obj-$(CONFIG_CPU_SUP_INTEL) += rapl.o obj-$(CONFIG_PERF_EVENTS_INTEL_RAPL) += intel-rapl.o
intel-rapl-objs := rapl.o
obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel-uncore.o obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel-uncore.o
intel-uncore-objs := uncore.o uncore_nhmex.o uncore_snb.o uncore_snbep.o intel-uncore-objs := uncore.o uncore_nhmex.o uncore_snb.o uncore_snbep.o
...@@ -53,6 +53,8 @@ ...@@ -53,6 +53,8 @@
#include <asm/cpu_device_id.h> #include <asm/cpu_device_id.h>
#include "../perf_event.h" #include "../perf_event.h"
MODULE_LICENSE("GPL");
/* /*
* RAPL energy status counters * RAPL energy status counters
*/ */
...@@ -592,6 +594,11 @@ static int rapl_cpu_notifier(struct notifier_block *self, ...@@ -592,6 +594,11 @@ static int rapl_cpu_notifier(struct notifier_block *self,
return NOTIFY_OK; return NOTIFY_OK;
} }
static struct notifier_block rapl_cpu_nb = {
.notifier_call = rapl_cpu_notifier,
.priority = CPU_PRI_PERF + 1,
};
static int rapl_check_hw_unit(bool apply_quirk) static int rapl_check_hw_unit(bool apply_quirk)
{ {
u64 msr_rapl_power_unit_bits; u64 msr_rapl_power_unit_bits;
...@@ -660,7 +667,7 @@ static int __init rapl_prepare_cpus(void) ...@@ -660,7 +667,7 @@ static int __init rapl_prepare_cpus(void)
return 0; return 0;
} }
static void __init cleanup_rapl_pmus(void) static void cleanup_rapl_pmus(void)
{ {
int i; int i;
...@@ -691,51 +698,77 @@ static int __init init_rapl_pmus(void) ...@@ -691,51 +698,77 @@ static int __init init_rapl_pmus(void)
return 0; return 0;
} }
#define X86_RAPL_MODEL_MATCH(model, init) \
{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&init }
struct intel_rapl_init_fun {
bool apply_quirk;
int cntr_mask;
struct attribute **attrs;
};
static const struct intel_rapl_init_fun snb_rapl_init __initconst = {
.apply_quirk = false,
.cntr_mask = RAPL_IDX_CLN,
.attrs = rapl_events_cln_attr,
};
static const struct intel_rapl_init_fun hsx_rapl_init __initconst = {
.apply_quirk = true,
.cntr_mask = RAPL_IDX_SRV,
.attrs = rapl_events_srv_attr,
};
static const struct intel_rapl_init_fun hsw_rapl_init __initconst = {
.apply_quirk = false,
.cntr_mask = RAPL_IDX_HSW,
.attrs = rapl_events_hsw_attr,
};
static const struct intel_rapl_init_fun snbep_rapl_init __initconst = {
.apply_quirk = false,
.cntr_mask = RAPL_IDX_SRV,
.attrs = rapl_events_srv_attr,
};
static const struct intel_rapl_init_fun knl_rapl_init __initconst = {
.apply_quirk = true,
.cntr_mask = RAPL_IDX_KNL,
.attrs = rapl_events_knl_attr,
};
static const struct x86_cpu_id rapl_cpu_match[] __initconst = { static const struct x86_cpu_id rapl_cpu_match[] __initconst = {
[0] = { .vendor = X86_VENDOR_INTEL, .family = 6 }, X86_RAPL_MODEL_MATCH(42, snb_rapl_init), /* Sandy Bridge */
[1] = {}, X86_RAPL_MODEL_MATCH(58, snb_rapl_init), /* Ivy Bridge */
X86_RAPL_MODEL_MATCH(63, hsx_rapl_init), /* Haswell-Server */
X86_RAPL_MODEL_MATCH(79, hsx_rapl_init), /* Broadwell-Server */
X86_RAPL_MODEL_MATCH(60, hsw_rapl_init), /* Haswell */
X86_RAPL_MODEL_MATCH(69, hsw_rapl_init), /* Haswell-Celeron */
X86_RAPL_MODEL_MATCH(61, hsw_rapl_init), /* Broadwell */
X86_RAPL_MODEL_MATCH(71, hsw_rapl_init), /* Broadwell-H */
X86_RAPL_MODEL_MATCH(45, snbep_rapl_init), /* Sandy Bridge-EP */
X86_RAPL_MODEL_MATCH(62, snbep_rapl_init), /* IvyTown */
X86_RAPL_MODEL_MATCH(87, knl_rapl_init), /* Knights Landing */
{},
}; };
MODULE_DEVICE_TABLE(x86cpu, rapl_cpu_match);
static int __init rapl_pmu_init(void) static int __init rapl_pmu_init(void)
{ {
bool apply_quirk = false; const struct x86_cpu_id *id;
struct intel_rapl_init_fun *rapl_init;
bool apply_quirk;
int ret; int ret;
if (!x86_match_cpu(rapl_cpu_match)) id = x86_match_cpu(rapl_cpu_match);
if (!id)
return -ENODEV; return -ENODEV;
switch (boot_cpu_data.x86_model) { rapl_init = (struct intel_rapl_init_fun *)id->driver_data;
case 42: /* Sandy Bridge */ apply_quirk = rapl_init->apply_quirk;
case 58: /* Ivy Bridge */ rapl_cntr_mask = rapl_init->cntr_mask;
rapl_cntr_mask = RAPL_IDX_CLN; rapl_pmu_events_group.attrs = rapl_init->attrs;
rapl_pmu_events_group.attrs = rapl_events_cln_attr;
break;
case 63: /* Haswell-Server */
case 79: /* Broadwell-Server */
apply_quirk = true;
rapl_cntr_mask = RAPL_IDX_SRV;
rapl_pmu_events_group.attrs = rapl_events_srv_attr;
break;
case 60: /* Haswell */
case 69: /* Haswell-Celeron */
case 61: /* Broadwell */
case 71: /* Broadwell-H */
rapl_cntr_mask = RAPL_IDX_HSW;
rapl_pmu_events_group.attrs = rapl_events_hsw_attr;
break;
case 45: /* Sandy Bridge-EP */
case 62: /* IvyTown */
rapl_cntr_mask = RAPL_IDX_SRV;
rapl_pmu_events_group.attrs = rapl_events_srv_attr;
break;
case 87: /* Knights Landing */
apply_quirk = true;
rapl_cntr_mask = RAPL_IDX_KNL;
rapl_pmu_events_group.attrs = rapl_events_knl_attr;
break;
default:
return -ENODEV;
}
ret = rapl_check_hw_unit(apply_quirk); ret = rapl_check_hw_unit(apply_quirk);
if (ret) if (ret)
...@@ -755,7 +788,7 @@ static int __init rapl_pmu_init(void) ...@@ -755,7 +788,7 @@ static int __init rapl_pmu_init(void)
if (ret) if (ret)
goto out; goto out;
__perf_cpu_notifier(rapl_cpu_notifier); __register_cpu_notifier(&rapl_cpu_nb);
cpu_notifier_register_done(); cpu_notifier_register_done();
rapl_advertise(); rapl_advertise();
return 0; return 0;
...@@ -766,4 +799,14 @@ static int __init rapl_pmu_init(void) ...@@ -766,4 +799,14 @@ static int __init rapl_pmu_init(void)
cpu_notifier_register_done(); cpu_notifier_register_done();
return ret; return ret;
} }
device_initcall(rapl_pmu_init); module_init(rapl_pmu_init);
static void __exit intel_rapl_exit(void)
{
cpu_notifier_register_begin();
__unregister_cpu_notifier(&rapl_cpu_nb);
perf_pmu_unregister(&rapl_pmus->pmu);
cleanup_rapl_pmus();
cpu_notifier_register_done();
}
module_exit(intel_rapl_exit);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment