From 15c1247953e8a45232ed5a5540f291d2d0a77665 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 9 Jun 2015 11:40:28 +0200 Subject: [PATCH] Revert "perf/x86/intel/uncore: Move uncore_box_init() out of driver initialization" This reverts commit c05199e5a57a579fea1e8fa65e2b511ceb524ffc. Vince Weaver reported the following crash while perf fuzzing: [ 79.473121] kernel BUG at mm/vmalloc.c:1335! [ 79.694391] Call Trace: [ 79.696997] [ 79.699090] [] get_vm_area_caller+0x40/0x50 [ 79.705505] [] ? snb_uncore_imc_init_box+0x6d/0x90 [ 79.712414] [] __ioremap_caller+0x195/0x350 [ 79.718610] [] ? snb_uncore_imc_init_box+0x6d/0x90 [ 79.725462] [] ? debug_object_activate+0x14b/0x1e0 [ 79.732346] [] ioremap_nocache+0x17/0x20 [ 79.738283] [] snb_uncore_imc_init_box+0x6d/0x90 [ 79.744945] [] snb_uncore_imc_event_start+0xb7/0x110 [ 79.752020] [] snb_uncore_imc_event_add+0x47/0x60 [ 79.758832] [] event_sched_in.isra.85+0xfb/0x330 [ 79.765519] [] group_sched_in+0x6f/0x1e0 [ 79.771481] [] ? native_sched_clock+0x2a/0x90 [ 79.777858] [] __perf_event_enable+0x25c/0x2a0 [ 79.784418] [] ? tick_nohz_irq_exit+0x29/0x30 [ 79.790820] [] ? cpu_clock_event_start+0x40/0x40 [ 79.797546] [] remote_function+0x50/0x60 [ 79.803535] [] flush_smp_call_function_queue+0x81/0x180 [ 79.810840] [] generic_smp_call_function_single_interrupt+0x13/0x60 [ 79.819328] [] smp_trace_call_function_single_interrupt+0x38/0xc0 [ 79.827614] [] trace_call_function_single_interrupt+0x6e/0x80 [ 79.835465] [ 79.837543] [] ? cpuidle_enter_state+0x65/0x160 [ 79.844377] [] ? cpuidle_enter_state+0x51/0x160 [ 79.851015] [] cpuidle_enter+0x17/0x20 [ 79.856791] [] cpu_startup_entry+0x399/0x440 [ 79.863165] [] rest_init+0xbb/0xd0 The offending commit is clearly confused as it moves heavy initialization work into IPI context. Revert it. Reported-by: Vince Weaver Acked-by: Peter Zijlstra (Intel) Cc: Kan Liang Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Cc: Yan, Zheng Cc: linux-kernel@vger.kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event_intel_uncore.c | 9 +++++++-- arch/x86/kernel/cpu/perf_event_intel_uncore.h | 18 ++++++++---------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index dd319e59246b..90b7c501c95b 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -839,6 +839,7 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id box->phys_id = phys_id; box->pci_dev = pdev; box->pmu = pmu; + uncore_box_init(box); pci_set_drvdata(pdev, box); raw_spin_lock(&uncore_box_lock); @@ -1002,8 +1003,10 @@ static int uncore_cpu_starting(int cpu) pmu = &type->pmus[j]; box = *per_cpu_ptr(pmu->box, cpu); /* called by uncore_cpu_init? */ - if (box && box->phys_id >= 0) + if (box && box->phys_id >= 0) { + uncore_box_init(box); continue; + } for_each_online_cpu(k) { exist = *per_cpu_ptr(pmu->box, k); @@ -1019,8 +1022,10 @@ static int uncore_cpu_starting(int cpu) } } - if (box) + if (box) { box->phys_id = phys_id; + uncore_box_init(box); + } } } return 0; diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index f789ec9a0133..ceac8f5dc018 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h @@ -258,14 +258,6 @@ static inline int uncore_num_counters(struct intel_uncore_box *box) return box->pmu->type->num_counters; } -static inline void uncore_box_init(struct intel_uncore_box *box) -{ - if (!test_and_set_bit(UNCORE_BOX_FLAG_INITIATED, &box->flags)) { - if (box->pmu->type->ops->init_box) - box->pmu->type->ops->init_box(box); - } -} - static inline void uncore_disable_box(struct intel_uncore_box *box) { if (box->pmu->type->ops->disable_box) @@ -274,8 +266,6 @@ static inline void uncore_disable_box(struct intel_uncore_box *box) static inline void uncore_enable_box(struct intel_uncore_box *box) { - uncore_box_init(box); - if (box->pmu->type->ops->enable_box) box->pmu->type->ops->enable_box(box); } @@ -298,6 +288,14 @@ static inline u64 uncore_read_counter(struct intel_uncore_box *box, return box->pmu->type->ops->read_counter(box, event); } +static inline void uncore_box_init(struct intel_uncore_box *box) +{ + if (!test_and_set_bit(UNCORE_BOX_FLAG_INITIATED, &box->flags)) { + if (box->pmu->type->ops->init_box) + box->pmu->type->ops->init_box(box); + } +} + static inline bool uncore_box_is_fake(struct intel_uncore_box *box) { return (box->phys_id < 0); -- 2.20.1