提交 a71a460c 编写于 作者: H Hanjun Guo 提交者: Yang Yingliang

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: NHanjun Guo <guohanjun@huawei.com>
Reviewed-by: NKefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 4946aa9f
...@@ -787,7 +787,7 @@ static int smmu_pmu_probe(struct platform_device *pdev) ...@@ -787,7 +787,7 @@ static int smmu_pmu_probe(struct platform_device *pdev)
smmu_pmu_get_acpi_options(smmu_pmu); smmu_pmu_get_acpi_options(smmu_pmu);
/* Pick one CPU to be the preferred one to use */ /* 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))); WARN_ON(irq_set_affinity(smmu_pmu->irq, cpumask_of(smmu_pmu->on_cpu)));
err = cpuhp_state_add_instance_nocalls(cpuhp_state_num, err = cpuhp_state_add_instance_nocalls(cpuhp_state_num,
...@@ -805,7 +805,6 @@ static int smmu_pmu_probe(struct platform_device *pdev) ...@@ -805,7 +805,6 @@ static int smmu_pmu_probe(struct platform_device *pdev)
goto out_unregister; goto out_unregister;
} }
put_cpu();
dev_info(dev, "Registered PMU @ %pa using %d counters with %s filter settings\n", dev_info(dev, "Registered PMU @ %pa using %d counters with %s filter settings\n",
&res_0->start, smmu_pmu->num_counters, &res_0->start, smmu_pmu->num_counters,
smmu_pmu->global_filter ? "Global(Counter0)" : smmu_pmu->global_filter ? "Global(Counter0)" :
...@@ -816,7 +815,6 @@ static int smmu_pmu_probe(struct platform_device *pdev) ...@@ -816,7 +815,6 @@ static int smmu_pmu_probe(struct platform_device *pdev)
out_unregister: out_unregister:
cpuhp_state_remove_instance_nocalls(cpuhp_state_num, &smmu_pmu->node); cpuhp_state_remove_instance_nocalls(cpuhp_state_num, &smmu_pmu->node);
out_cpuhp_err: out_cpuhp_err:
put_cpu();
return err; return err;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册