Re: [PATCH v3 1/2] iommu: Disable preemption around use of this_cpu_ptr()

From: Joonas Lahtinen
Date: Wed Jun 01 2016 - 08:26:09 EST


On ke, 2016-06-01 at 12:10 +0100, Chris Wilson wrote:
> Between acquiring the this_cpu_ptr() and using it, ideally we don't want
> to be preempted and work on another CPU's private data. this_cpu_ptr()
> checks whether or not preemption is disable, and get_cpu_ptr() provides
> a convenient wrapper for operating on the cpu ptr inside a preemption
> disabled critical section (which currently is provided by the
> spinlock). Indeed if we disable preemption around this_cpu_ptr,
> we do not need the CPU local spinlock - so long as take care that no other
> CPU is running that code as do perform the cross-CPU cache flushing and
> teardown, but that is a subject for another patch.
>
> [ÂÂ167.997877] BUG: using smp_processor_id() in preemptible [00000000] code: usb-storage/216
> [ÂÂ167.997940] caller is debug_smp_processor_id+0x17/0x20
> [ÂÂ167.997945] CPU: 7 PID: 216 Comm: usb-storage Tainted: GÂÂÂÂÂUÂÂÂÂÂÂÂÂÂÂ4.7.0-rc1-gfxbench-RO_Patchwork_1057+ #1
> [ÂÂ167.997948] Hardware name: Hewlett-Packard HP Pro 3500 Series/2ABF, BIOS 8.11 10/24/2012
> [ÂÂ167.997951]ÂÂ0000000000000000 ffff880118b7f9c8 ffffffff8140dca5 0000000000000007
> [ÂÂ167.997958]ÂÂffffffff81a3a7e9 ffff880118b7f9f8 ffffffff8142a927 0000000000000000
> [ÂÂ167.997965]ÂÂffff8800d499ed58 0000000000000001 00000000000fffff ffff880118b7fa08
> [ÂÂ167.997971] Call Trace:
> [ÂÂ167.997977]ÂÂ[] dump_stack+0x67/0x92
> [ÂÂ167.997981]ÂÂ[] check_preemption_disabled+0xd7/0xe0
> [ÂÂ167.997985]ÂÂ[] debug_smp_processor_id+0x17/0x20
> [ÂÂ167.997990]ÂÂ[] alloc_iova_fast+0xb7/0x210
> [ÂÂ167.997994]ÂÂ[] intel_alloc_iova+0x7f/0xd0
> [ÂÂ167.997998]ÂÂ[] intel_map_sg+0xbd/0x240
> [ÂÂ167.998002]ÂÂ[] ? debug_lockdep_rcu_enabled+0x1d/0x20
> [ÂÂ167.998009]ÂÂ[] usb_hcd_map_urb_for_dma+0x4b9/0x5a0
> [ÂÂ167.998013]ÂÂ[] usb_hcd_submit_urb+0xe9/0xaa0
> [ÂÂ167.998017]ÂÂ[] ? mark_held_locks+0x6f/0xa0
> [ÂÂ167.998022]ÂÂ[] ? __raw_spin_lock_init+0x1c/0x50
> [ÂÂ167.998025]ÂÂ[] ? debug_lockdep_rcu_enabled+0x1d/0x20
> [ÂÂ167.998028]ÂÂ[] usb_submit_urb+0x3f3/0x5a0
> [ÂÂ167.998032]ÂÂ[] ? trace_hardirqs_on_caller+0x122/0x1b0
> [ÂÂ167.998035]ÂÂ[] usb_sg_wait+0x67/0x150
> [ÂÂ167.998039]ÂÂ[] usb_stor_bulk_transfer_sglist.part.3+0x82/0xd0
> [ÂÂ167.998042]ÂÂ[] usb_stor_bulk_srb+0x4c/0x60
> [ÂÂ167.998045]ÂÂ[] usb_stor_Bulk_transport+0x17e/0x420
> [ÂÂ167.998049]ÂÂ[] usb_stor_invoke_transport+0x242/0x540
> [ÂÂ167.998052]ÂÂ[] ? debug_lockdep_rcu_enabled+0x1d/0x20
> [ÂÂ167.998058]ÂÂ[] usb_stor_transparent_scsi_command+0x9/0x10
> [ÂÂ167.998061]ÂÂ[] usb_stor_control_thread+0x158/0x260
> [ÂÂ167.998064]ÂÂ[] ? fill_inquiry_response+0x20/0x20
> [ÂÂ167.998067]ÂÂ[] ? fill_inquiry_response+0x20/0x20
> [ÂÂ167.998071]ÂÂ[] kthread+0xea/0x100
> [ÂÂ167.998078]ÂÂ[] ret_from_fork+0x1f/0x40
> [ÂÂ167.998081]ÂÂ[] ? kthread_create_on_node+0x1f0/0x1f0
>
> v2: convert preempt_disable(); var = this_cpu_ptr() to var = get_cpu_ptr()
> v3: Actually use get_cpu_ptr (not get_cpu_var). Drop the spinlock
> removal, concentrate on the immediate bug fix.
>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96293
> Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
> Cc: Joonas Lahtinen <joonas.lahtinen@xxxxxxxxxxxxxxx>

Reviewed-by: Joonas Lahtinen <joonas.lahtinen@xxxxxxxxxxxxxxx>

> Cc: Joerg Roedel <joro@xxxxxxxxxx>
> Cc: iommu@xxxxxxxxxxxxxxxxxxxxxxxxxx
> Cc: linux-kernel@xxxxxxxxxxxxxxx
> ---
> Âdrivers/iommu/iova.c | 8 ++++++--
> Â1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
> index ba764a0835d3..e23001bfcfee 100644
> --- a/drivers/iommu/iova.c
> +++ b/drivers/iommu/iova.c
> @@ -420,8 +420,10 @@ retry:
> Â
> Â /* Try replenishing IOVAs by flushing rcache. */
> Â flushed_rcache = true;
> + preempt_disable();
> Â for_each_online_cpu(cpu)
> Â free_cpu_cached_iovas(cpu, iovad);
> + preempt_enable();
> Â goto retry;
> Â }
> Â
> @@ -749,7 +751,7 @@ static bool __iova_rcache_insert(struct iova_domain *iovad,
> Â bool can_insert = false;
> Â unsigned long flags;
> Â
> - cpu_rcache = this_cpu_ptr(rcache->cpu_rcaches);
> + cpu_rcache = get_cpu_ptr(rcache->cpu_rcaches);
> Â spin_lock_irqsave(&cpu_rcache->lock, flags);
> Â
> Â if (!iova_magazine_full(cpu_rcache->loaded)) {
> @@ -779,6 +781,7 @@ static bool __iova_rcache_insert(struct iova_domain *iovad,
> Â iova_magazine_push(cpu_rcache->loaded, iova_pfn);
> Â
> Â spin_unlock_irqrestore(&cpu_rcache->lock, flags);
> + put_cpu_ptr(rcache->cpu_rcaches);
> Â
> Â if (mag_to_free) {
> Â iova_magazine_free_pfns(mag_to_free, iovad);
> @@ -812,7 +815,7 @@ static unsigned long __iova_rcache_get(struct iova_rcache *rcache,
> Â bool has_pfn = false;
> Â unsigned long flags;
> Â
> - cpu_rcache = this_cpu_ptr(rcache->cpu_rcaches);
> + cpu_rcache = get_cpu_ptr(rcache->cpu_rcaches);
> Â spin_lock_irqsave(&cpu_rcache->lock, flags);
> Â
> Â if (!iova_magazine_empty(cpu_rcache->loaded)) {
> @@ -834,6 +837,7 @@ static unsigned long __iova_rcache_get(struct iova_rcache *rcache,
> Â iova_pfn = iova_magazine_pop(cpu_rcache->loaded, limit_pfn);
> Â
> Â spin_unlock_irqrestore(&cpu_rcache->lock, flags);
> + put_cpu_ptr(rcache->cpu_rcaches);
> Â
> Â return iova_pfn;
> Â}
--
Joonas Lahtinen
Open Source Technology Center
Intel Corporation