From a71a460c576624850907ed0009df082457160ef3 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Tue, 10 Dec 2019 14:54:57 +0800 Subject: [PATCH] perf/smmuv3: fix possible sleep in preempt context hulk inclusion category: bugfix bugzilla: 5384 CVE: NA -------------------------------------- When booting with SMMUv3 PMU enabled, we got: 17.130943] arm-smmu-v3-pmcg arm-smmu-v3-pmcg.8.auto: option mask 0x1 [ 17.137376] BUG: sleeping function called from invalid context at ./include/linux/percpu-rwsem.h:34 [ 17.146389] in_atomic(): 1, irqs_disabled(): 0, pid: 1, name: swapper/0 [ 17.152984] 1 lock held by swapper/0/1: [ 17.156812] #0: (____ptrval____) (&dev->mutex){....}, at: __driver_attach+0x70/0x150 [ 17.164634] CPU: 16 PID: 1 Comm: swapper/0 Not tainted 4.19.36-cph920-32bitc-vmalloc-binder-debugon.aarch64 #6 [ 17.174589] Hardware name: Huawei TaiShan 2280 V2/BC82AMDD, BIOS 1.12t 11/28/2019 [ 17.177903] usb 5-1: new high-speed USB device number 2 using xhci_hcd [ 17.182037] Call trace: [ 17.182041] dump_backtrace+0x0/0x198 [ 17.182042] show_stack+0x24/0x30 [ 17.182046] dump_stack+0xd0/0x11c [ 17.182048] ___might_sleep+0x1ac/0x288 [ 17.182050] __might_sleep+0x58/0x90 [ 17.182052] cpus_read_lock+0x34/0xd8 [ 17.182054] __cpuhp_state_add_instance+0x28/0x58 [ 17.182058] smmu_pmu_probe+0x2fc/0x500 [ 17.220846] platform_drv_probe+0x58/0xa8 [ 17.224839] really_probe+0x258/0x3c8 [ 17.228488] driver_probe_device+0x12c/0x148 [ 17.232741] __driver_attach+0x124/0x150 [ 17.236649] bus_for_each_dev+0x84/0xd8 [ 17.240470] driver_attach+0x30/0x40 [ 17.244033] bus_add_driver+0x178/0x2b0 [ 17.247854] driver_register+0x64/0x118 [ 17.251675] __platform_driver_register+0x54/0x60 [ 17.256361] arm_smmu_pmu_init+0x50/0x58 [ 17.260268] do_one_initcall+0x90/0x3c8 [ 17.264090] kernel_init_freeable+0x450/0x500 [ 17.265902] usb 1-1.1: new full-speed USB device number 3 using ehci-pci [ 17.268430] kernel_init+0x18/0x118 [ 17.268432] ret_from_fork+0x10/0x18 This is because get_cpu()/put_cpu() will call preempt_disable/enable(), and __cpuhp_state_add_instance() may sleep, so fix it by replacing get_cpu()/put_cpu() with raw_smp_processor_id(). Signed-off-by: Hanjun Guo Reviewed-by: Kefeng Wang Signed-off-by: Yang Yingliang --- drivers/perf/arm_smmuv3_pmu.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c index 7d4be22dc721..b60b447dde94 100644 --- a/drivers/perf/arm_smmuv3_pmu.c +++ b/drivers/perf/arm_smmuv3_pmu.c @@ -787,7 +787,7 @@ static int smmu_pmu_probe(struct platform_device *pdev) smmu_pmu_get_acpi_options(smmu_pmu); /* Pick one CPU to be the preferred one to use */ - smmu_pmu->on_cpu = get_cpu(); + smmu_pmu->on_cpu = raw_smp_processor_id(); WARN_ON(irq_set_affinity(smmu_pmu->irq, cpumask_of(smmu_pmu->on_cpu))); err = cpuhp_state_add_instance_nocalls(cpuhp_state_num, @@ -805,7 +805,6 @@ static int smmu_pmu_probe(struct platform_device *pdev) goto out_unregister; } - put_cpu(); dev_info(dev, "Registered PMU @ %pa using %d counters with %s filter settings\n", &res_0->start, smmu_pmu->num_counters, smmu_pmu->global_filter ? "Global(Counter0)" : @@ -816,7 +815,6 @@ static int smmu_pmu_probe(struct platform_device *pdev) out_unregister: cpuhp_state_remove_instance_nocalls(cpuhp_state_num, &smmu_pmu->node); out_cpuhp_err: - put_cpu(); return err; } -- GitLab