Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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.com


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent e633c65a
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -8,4 +8,12 @@ config PERF_EVENTS_INTEL_UNCORE
	Include support for Intel uncore performance events. These are
	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
+2 −1
Original line number Diff line number Diff line
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)		+= 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
intel-uncore-objs			:= uncore.o uncore_nhmex.o uncore_snb.o uncore_snbep.o
+82 −39
Original line number Diff line number Diff line
@@ -53,6 +53,8 @@
#include <asm/cpu_device_id.h>
#include "../perf_event.h"

MODULE_LICENSE("GPL");

/*
 * RAPL energy status counters
 */
@@ -592,6 +594,11 @@ static int rapl_cpu_notifier(struct notifier_block *self,
	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)
{
	u64 msr_rapl_power_unit_bits;
@@ -660,7 +667,7 @@ static int __init rapl_prepare_cpus(void)
	return 0;
}

static void __init cleanup_rapl_pmus(void)
static void cleanup_rapl_pmus(void)
{
	int i;

@@ -691,51 +698,77 @@ static int __init init_rapl_pmus(void)
	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 = {
	[0] = { .vendor = X86_VENDOR_INTEL, .family = 6 },
	[1] = {},
	X86_RAPL_MODEL_MATCH(42, snb_rapl_init),	/* Sandy Bridge */
	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)
{
	bool apply_quirk = false;
	const struct x86_cpu_id *id;
	struct intel_rapl_init_fun *rapl_init;
	bool apply_quirk;
	int ret;

	if (!x86_match_cpu(rapl_cpu_match))
	id = x86_match_cpu(rapl_cpu_match);
	if (!id)
		return -ENODEV;

	switch (boot_cpu_data.x86_model) {
	case 42: /* Sandy Bridge */
	case 58: /* Ivy Bridge */
		rapl_cntr_mask = RAPL_IDX_CLN;
		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;
	}
	rapl_init = (struct intel_rapl_init_fun *)id->driver_data;
	apply_quirk = rapl_init->apply_quirk;
	rapl_cntr_mask = rapl_init->cntr_mask;
	rapl_pmu_events_group.attrs = rapl_init->attrs;

	ret = rapl_check_hw_unit(apply_quirk);
	if (ret)
@@ -755,7 +788,7 @@ static int __init rapl_pmu_init(void)
	if (ret)
		goto out;

	__perf_cpu_notifier(rapl_cpu_notifier);
	__register_cpu_notifier(&rapl_cpu_nb);
	cpu_notifier_register_done();
	rapl_advertise();
	return 0;
@@ -766,4 +799,14 @@ static int __init rapl_pmu_init(void)
	cpu_notifier_register_done();
	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);