Skip to contentSkip to conversation

perf/x86: set pmu->module in Intel PMU modules

PATCH In review David Carrillo-Cisneros 4 participants 5 messages Dec 23, 2016 – Jan 5, 2017

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 perf/x86: set pmu->module in Intel PMU modules

The conversion of Intel PMU drivers into modules did not include reference counting. The machine will crash when attempting to access deleted code if an event from a module PMU is started and the module removed before the event is destroyed.

i.e. this crashes the machine:

	$ insmod intel-rapl-perf.ko
	$ perf stat -e power/energy-cores/ -C 0 &
	$ rmmod intel-rapl-perf.ko

Set THIS_MODULE to pmu->module in Intel module PMUs so that generic code can handle reference counting and deny rmmod while an event still exists.

---
 arch/x86/events/intel/cstate.c | 2 ++
 arch/x86/events/intel/rapl.c   | 1 +
 arch/x86/events/intel/uncore.c | 1 +
 3 files changed, 4 insertions(+)
arch/x86/events/intel/cstate.c +2 -0
index da51e5a..5c08fc7 100644
@@ -434,6 +434,7 @@ static struct pmu cstate_core_pmu = {
 	.stop		= cstate_pmu_event_stop,
 	.read		= cstate_pmu_event_update,
 	.capabilities	= PERF_PMU_CAP_NO_INTERRUPT,
+	.module		= THIS_MODULE,
 };
 
 static struct pmu cstate_pkg_pmu = {
@@ -447,6 +448,7 @@ static struct pmu cstate_pkg_pmu = {
 	.stop		= cstate_pmu_event_stop,
 	.read		= cstate_pmu_event_update,
 	.capabilities	= PERF_PMU_CAP_NO_INTERRUPT,
+	.module		= THIS_MODULE,
 };
 
 static const struct cstate_model nhm_cstates __initconst = {
arch/x86/events/intel/rapl.c +1 -0
index 0a535ce..6f2cbd5 100644
@@ -697,6 +697,7 @@ static int __init init_rapl_pmus(void)
 	rapl_pmus->pmu.start		= rapl_pmu_event_start;
 	rapl_pmus->pmu.stop		= rapl_pmu_event_stop;
 	rapl_pmus->pmu.read		= rapl_pmu_event_read;
+	rapl_pmus->pmu.module		= THIS_MODULE;
 	return 0;
 }
 
arch/x86/events/intel/uncore.c +1 -0
index dbaaf7dc..2fe525b 100644
@@ -733,6 +733,7 @@ static int uncore_pmu_register(struct intel_uncore_pmu *pmu)
 			.start		= uncore_pmu_event_start,
 			.stop		= uncore_pmu_event_stop,
 			.read		= uncore_pmu_event_read,
+			.module		= THIS_MODULE,
 		};
 	} else {
 		pmu->pmu = *pmu->type->pmu;
Signature · 1 line
2.8.0.rc3.226.g39d4020
#1 lore raw

[tip:perf/urgent] perf/x86: Set pmu->module in Intel PMU modules

perf/x86: Set pmu->module in Intel PMU modules
Commit-ID:  74545f63890e38520eb4d1dbedcadaa9c0dbc824
Gitweb:     http://git.kernel.org/tip/74545f63890e38520eb4d1dbedcadaa9c0dbc824
Author:     David Carrillo-Cisneros <[email protected]>
AuthorDate: Thu, 22 Dec 2016 17:17:40 -0800
Committer:  Ingo Molnar <[email protected]>
CommitDate: Thu, 5 Jan 2017 09:13:55 +0100

perf/x86: Set pmu->module in Intel PMU modules

The conversion of Intel PMU drivers into modules did not include reference counting. The machine will crash when attempting to access deleted code if an event from a module PMU is started and the module removed before the event is destroyed.

i.e. this crashes the machine:

	$ insmod intel-rapl-perf.ko
	$ perf stat -e power/energy-cores/ -C 0 &
	$ rmmod intel-rapl-perf.ko

Set THIS_MODULE to pmu->module in Intel module PMUs so that generic code can handle reference counting and deny rmmod while an event still exists.

Cc Alexander Shishkin <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Kan Liang <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Paul Turner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Srinivas Pandruvada <[email protected]>
Cc Stephane Eranian <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/events/intel/cstate.c | 2 ++
 arch/x86/events/intel/rapl.c   | 1 +
 arch/x86/events/intel/uncore.c | 1 +
 3 files changed, 4 insertions(+)
arch/x86/events/intel/cstate.c +2 -0
index fec8a46..1076c9a 100644
@@ -434,6 +434,7 @@ static struct pmu cstate_core_pmu = {
 	.stop		= cstate_pmu_event_stop,
 	.read		= cstate_pmu_event_update,
 	.capabilities	= PERF_PMU_CAP_NO_INTERRUPT,
+	.module		= THIS_MODULE,
 };
 
 static struct pmu cstate_pkg_pmu = {
@@ -447,6 +448,7 @@ static struct pmu cstate_pkg_pmu = {
 	.stop		= cstate_pmu_event_stop,
 	.read		= cstate_pmu_event_update,
 	.capabilities	= PERF_PMU_CAP_NO_INTERRUPT,
+	.module		= THIS_MODULE,
 };
 
 static const struct cstate_model nhm_cstates __initconst = {
arch/x86/events/intel/rapl.c +1 -0
index bd34124..17c3564 100644
@@ -697,6 +697,7 @@ static int __init init_rapl_pmus(void)
 	rapl_pmus->pmu.start		= rapl_pmu_event_start;
 	rapl_pmus->pmu.stop		= rapl_pmu_event_stop;
 	rapl_pmus->pmu.read		= rapl_pmu_event_read;
+	rapl_pmus->pmu.module		= THIS_MODULE;
 	return 0;
 }
 
arch/x86/events/intel/uncore.c +1 -0
index 97c246f..8c4ccdc 100644
@@ -733,6 +733,7 @@ static int uncore_pmu_register(struct intel_uncore_pmu *pmu)
 			.start		= uncore_pmu_event_start,
 			.stop		= uncore_pmu_event_stop,
 			.read		= uncore_pmu_event_read,
+			.module		= THIS_MODULE,
 		};
 	} else {
 		pmu->pmu = *pmu->type->pmu;
maintainer
#2 lore raw

Re: [tip:perf/urgent] perf/x86: Set pmu->module in Intel PMU modules

Quoted 35 lines · tip-bot for David Carrillo-Cisneros
arch/x86/events/intel/cstate.c +2 -0
@@ -434,6 +434,7 @@ static struct pmu cstate_core_pmu = {
 	.stop		= cstate_pmu_event_stop,
 	.read		= cstate_pmu_event_update,
 	.capabilities	= PERF_PMU_CAP_NO_INTERRUPT,
+	.module		= THIS_MODULE,
 };
 
 static struct pmu cstate_pkg_pmu = {
@@ -447,6 +448,7 @@ static struct pmu cstate_pkg_pmu = {
 	.stop		= cstate_pmu_event_stop,
 	.read		= cstate_pmu_event_update,
 	.capabilities	= PERF_PMU_CAP_NO_INTERRUPT,
+	.module		= THIS_MODULE,
 };
 
 static const struct cstate_model nhm_cstates __initconst = {
arch/x86/events/intel/rapl.c +1 -0
index bd34124..17c3564 100644
@@ -697,6 +697,7 @@ static int __init init_rapl_pmus(void)
 	rapl_pmus->pmu.start		= rapl_pmu_event_start;
 	rapl_pmus->pmu.stop		= rapl_pmu_event_stop;
 	rapl_pmus->pmu.read		= rapl_pmu_event_read;
+	rapl_pmus->pmu.module		= THIS_MODULE;
 	return 0;
 }
 
arch/x86/events/intel/uncore.c +0 -0
index 97c246f..8c4ccdc 100644

arch/x86/events/intel/uncore.c static int uncore_pmu_register(struct intel_uncore_pmu *pmu) · line 739

Quoted 7 lines
arch/x86/events/intel/uncore.c +1 -0
@@ -733,6 +733,7 @@ static int uncore_pmu_register(struct intel_uncore_pmu *pmu)
 			.start		= uncore_pmu_event_start,
 			.stop		= uncore_pmu_event_stop,
 			.read		= uncore_pmu_event_read,
+			.module		= THIS_MODULE,
 		};
 	} else {
 		pmu->pmu = *pmu->type->pmu;

Ah, forgot about this, thanks for picking it up.

The first time I saw this I thought about doing something like the below, but never got around to testing if that works and subsequently forgot about things again.

Does this make sense and or work?

---

include/linux/perf_event.h +8 -1
index 4741ecdb9817..70f8a5a2e224 100644
@@ -852,7 +852,14 @@ extern int perf_aux_output_skip(struct perf_output_handle *handle,
 				unsigned long size);
 extern void *perf_get_aux(struct perf_output_handle *handle);
 
-extern int perf_pmu_register(struct pmu *pmu, const char *name, int type);
+extern int __perf_pmu_register(struct pmu *pmu, const char *name, int type);
+
+#define perf_pmu_register(_pmu, _name, _type)			\
+({								\
+ 	(_pmu)->module = THIS_MODULE;				\
+ 	__perf_pmu_register((_pmu), (_name), (_type));		\
+})
+
 extern void perf_pmu_unregister(struct pmu *pmu);
 
 extern int perf_num_counters(void);
kernel/events/core.c +1 -1
index faf073d0287f..cde2004d932d 100644
@@ -8752,7 +8767,7 @@ static int pmu_dev_alloc(struct pmu *pmu)
 static struct lock_class_key cpuctx_mutex;
 static struct lock_class_key cpuctx_lock;
 
-int perf_pmu_register(struct pmu *pmu, const char *name, int type)
+int __perf_pmu_register(struct pmu *pmu, const char *name, int type)
 {
 	int cpu, ret;
 
#3 lore raw

Re: [tip:perf/urgent] perf/x86: Set pmu->module in Intel PMU modules

Quoted 6 lines · Peter Zijlstra

The first time I saw this I thought about doing something like the below, but never got around to testing if that works and subsequently forgot about things again.

Does this make sense and or work?

I'd argue against it.

It will "work", but it's fragile. In particular, if something ever ends up using perf_pmu_register() through some indirect helper function, it will do the wrong thing, because

include/linux/perf_event.h extern int perf_aux_output_skip(struct perf_output_handle *handle, · line 861

Quoted 5 lines
include/linux/perf_event.h +5 -0
+#define perf_pmu_register(_pmu, _name, _type)                  \
+({                                                             \
+       (_pmu)->module = THIS_MODULE;                           \
+       __perf_pmu_register((_pmu), (_name), (_type));          \
+})

.. at that point "THIS_MODULE" could be the module that contains the helper function that may not actually be the actual end-point module.

Looking at the situation right now, that never happens and all the users seem to be "leaf" modules. But it would worry me a bit.

Linus

maintainer
#4 lore raw

Re: [tip:perf/urgent] perf/x86: Set pmu->module in Intel PMU modules

Quoted 9 lines · Linus Torvalds
Quoted 6 lines · Peter Zijlstra

The first time I saw this I thought about doing something like the below, but never got around to testing if that works and subsequently forgot about things again.

Does this make sense and or work?

I'd argue against it.

Fair enough; /me files it in the bit-bucket.