Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1552036 > unrolled thread

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

Started bytip-bot for David Carrillo-Cisneros <tipbot@zytor.com>
First post2017-01-05 16:10 +0100
Last post2017-01-05 22:00 +0100
Articles 4 — 3 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [tip:perf/urgent] perf/x86: Set pmu->module in Intel PMU modules tip-bot for David Carrillo-Cisneros <tipbot@zytor.com> - 2017-01-05 16:10 +0100
    Re: [tip:perf/urgent] perf/x86: Set pmu->module in Intel PMU modules Peter Zijlstra <peterz@infradead.org> - 2017-01-05 17:00 +0100
      Re: [tip:perf/urgent] perf/x86: Set pmu->module in Intel PMU modules Linus Torvalds <torvalds@linux-foundation.org> - 2017-01-05 19:50 +0100
        Re: [tip:perf/urgent] perf/x86: Set pmu->module in Intel PMU modules Peter Zijlstra <peterz@infradead.org> - 2017-01-05 22:00 +0100

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

Fromtip-bot for David Carrillo-Cisneros <tipbot@zytor.com>
Date2017-01-05 16:10 +0100
Subject[tip:perf/urgent] perf/x86: Set pmu->module in Intel PMU modules
Message-ID<sWhPY-4HN-13@gated-at.bofh.it>
Commit-ID:  74545f63890e38520eb4d1dbedcadaa9c0dbc824
Gitweb:     http://git.kernel.org/tip/74545f63890e38520eb4d1dbedcadaa9c0dbc824
Author:     David Carrillo-Cisneros <davidcc@google.com>
AuthorDate: Thu, 22 Dec 2016 17:17:40 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
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.

Signed-off-by: David Carrillo-Cisneros <davidcc@google.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Paul Turner <pjt@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1482455860-116269-1-git-send-email-davidcc@google.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 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(+)

diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c
index fec8a46..1076c9a 100644
--- a/arch/x86/events/intel/cstate.c
+++ b/arch/x86/events/intel/cstate.c
@@ -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 = {
diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c
index bd34124..17c3564 100644
--- a/arch/x86/events/intel/rapl.c
+++ b/arch/x86/events/intel/rapl.c
@@ -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;
 }
 
diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c
index 97c246f..8c4ccdc 100644
--- a/arch/x86/events/intel/uncore.c
+++ b/arch/x86/events/intel/uncore.c
@@ -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;

[toc] | [next] | [standalone]


#1552078

FromPeter Zijlstra <peterz@infradead.org>
Date2017-01-05 17:00 +0100
Message-ID<sWiCl-50p-17@gated-at.bofh.it>
In reply to#1552036
On Thu, Jan 05, 2017 at 07:07:05AM -0800, tip-bot for David Carrillo-Cisneros wrote:
> --- a/arch/x86/events/intel/cstate.c
> +++ b/arch/x86/events/intel/cstate.c
> @@ -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 = {
> diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c
> index bd34124..17c3564 100644
> --- a/arch/x86/events/intel/rapl.c
> +++ b/arch/x86/events/intel/rapl.c
> @@ -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;
>  }
>  
> diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c
> index 97c246f..8c4ccdc 100644
> --- a/arch/x86/events/intel/uncore.c
> +++ b/arch/x86/events/intel/uncore.c
> @@ -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?

---

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 4741ecdb9817..70f8a5a2e224 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -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);
diff --git a/kernel/events/core.c b/kernel/events/core.c
index faf073d0287f..cde2004d932d 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -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;
 

[toc] | [prev] | [next] | [standalone]


#1552221

FromLinus Torvalds <torvalds@linux-foundation.org>
Date2017-01-05 19:50 +0100
Message-ID<sWlgS-6MA-23@gated-at.bofh.it>
In reply to#1552078
On Thu, Jan 5, 2017 at 7:52 AM, Peter Zijlstra <peterz@infradead.org> wrote:
>
> 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

> +#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

[toc] | [prev] | [next] | [standalone]


#1552327

FromPeter Zijlstra <peterz@infradead.org>
Date2017-01-05 22:00 +0100
Message-ID<sWniF-88U-13@gated-at.bofh.it>
In reply to#1552221
On Thu, Jan 05, 2017 at 10:46:30AM -0800, Linus Torvalds wrote:
> On Thu, Jan 5, 2017 at 7:52 AM, Peter Zijlstra <peterz@infradead.org> wrote:
> >
> > 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.

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web