[1/4] drm/shmem: Do dma_unmap_sg before purging pages
diff mbox series

Message ID 20190819161204.3106-2-robh@kernel.org
State New
Headers show
Series
  • panfrost: Locking fixes
Related show

Commit Message

Rob Herring Aug. 19, 2019, 4:12 p.m. UTC
Calling dma_unmap_sg() in drm_gem_shmem_free_object() is too late if the
backing pages have already been released by the shrinker. The result is
the following abort:

Unable to handle kernel paging request at virtual address ffff8000098ed000
Mem abort info:
  ESR = 0x96000147
  Exception class = DABT (current EL), IL = 32 bits
  SET = 0, FnV = 0
  EA = 0, S1PTW = 0
Data abort info:
  ISV = 0, ISS = 0x00000147
  CM = 1, WnR = 1
swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000002f51000
[ffff8000098ed000] pgd=00000000401f8003, pud=00000000401f7003, pmd=00000000401b1003, pte=00e80000098ed712
Internal error: Oops: 96000147 [#1] SMP
Modules linked in: panfrost gpu_sched
CPU: 5 PID: 902 Comm: gnome-shell Not tainted 5.3.0-rc1+ #95
Hardware name: 96boards Rock960 (DT)
pstate: 40000005 (nZcv daif -PAN -UAO)
pc : __dma_inv_area+0x40/0x58
lr : arch_sync_dma_for_cpu+0x28/0x30
sp : ffff00001321ba30
x29: ffff00001321ba30 x28: ffff00001321bd08
x27: 0000000000000000 x26: 0000000000000009
x25: 0000ffffc1f86170 x24: 0000000000000000
x23: 0000000000000000 x22: 0000000000000000
x21: 0000000000021000 x20: ffff80003bb2d810
x19: 00000000098ed000 x18: 0000000000000000
x17: 0000000000000000 x16: ffff800023fd9480
x15: 0000000000000000 x14: 0000000000000000
x13: 0000000000000000 x12: 0000000000000000
x11: 00000000fffb9fff x10: 0000000000000000
x9 : 0000000000000000 x8 : ffff800023fd9c18
x7 : 0000000000000000 x6 : 00000000ffffffff
x5 : 0000000000000000 x4 : 0000000000021000
Purging 5693440 bytes
x3 : 000000000000003f x2 : 0000000000000040
x1 : ffff80000990e000 x0 : ffff8000098ed000
Call trace:
 __dma_inv_area+0x40/0x58
 dma_direct_sync_single_for_cpu+0x7c/0x80
 dma_direct_unmap_page+0x80/0x88
 dma_direct_unmap_sg+0x54/0x80
 drm_gem_shmem_free_object+0xfc/0x108
 panfrost_gem_free_object+0x118/0x128 [panfrost]
 drm_gem_object_free+0x18/0x90
 drm_gem_object_put_unlocked+0x58/0x80
 drm_gem_object_handle_put_unlocked+0x64/0xb0
 drm_gem_object_release_handle+0x70/0x98
 drm_gem_handle_delete+0x64/0xb0
 drm_gem_close_ioctl+0x28/0x38
 drm_ioctl_kernel+0xb8/0x110
 drm_ioctl+0x244/0x3f0
 do_vfs_ioctl+0xbc/0x910
 ksys_ioctl+0x78/0xa8
 __arm64_sys_ioctl+0x1c/0x28
 el0_svc_common.constprop.0+0x88/0x150
 el0_svc_handler+0x28/0x78
 el0_svc+0x8/0xc
 Code: 8a230000 54000060 d50b7e20 14000002 (d5087620)

Fixes: 17acb9f35ed7 ("drm/shmem: Add madvise state and purge helpers")
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <maxime.ripard@bootlin.com>
Cc: Sean Paul <sean@poorly.run>
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel@ffwll.ch>
Signed-off-by: Rob Herring <robh@kernel.org>
---
 drivers/gpu/drm/drm_gem_shmem_helper.c | 6 ++++++
 1 file changed, 6 insertions(+)

Comments

Steven Price Aug. 22, 2019, 1:27 p.m. UTC | #1
On 19/08/2019 17:12, Rob Herring wrote:
> Calling dma_unmap_sg() in drm_gem_shmem_free_object() is too late if the
> backing pages have already been released by the shrinker. The result is
> the following abort:
> 
> Unable to handle kernel paging request at virtual address ffff8000098ed000
> Mem abort info:
>   ESR = 0x96000147
>   Exception class = DABT (current EL), IL = 32 bits
>   SET = 0, FnV = 0
>   EA = 0, S1PTW = 0
> Data abort info:
>   ISV = 0, ISS = 0x00000147
>   CM = 1, WnR = 1
> swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000002f51000
> [ffff8000098ed000] pgd=00000000401f8003, pud=00000000401f7003, pmd=00000000401b1003, pte=00e80000098ed712
> Internal error: Oops: 96000147 [#1] SMP
> Modules linked in: panfrost gpu_sched
> CPU: 5 PID: 902 Comm: gnome-shell Not tainted 5.3.0-rc1+ #95
> Hardware name: 96boards Rock960 (DT)
> pstate: 40000005 (nZcv daif -PAN -UAO)
> pc : __dma_inv_area+0x40/0x58
> lr : arch_sync_dma_for_cpu+0x28/0x30
> sp : ffff00001321ba30
> x29: ffff00001321ba30 x28: ffff00001321bd08
> x27: 0000000000000000 x26: 0000000000000009
> x25: 0000ffffc1f86170 x24: 0000000000000000
> x23: 0000000000000000 x22: 0000000000000000
> x21: 0000000000021000 x20: ffff80003bb2d810
> x19: 00000000098ed000 x18: 0000000000000000
> x17: 0000000000000000 x16: ffff800023fd9480
> x15: 0000000000000000 x14: 0000000000000000
> x13: 0000000000000000 x12: 0000000000000000
> x11: 00000000fffb9fff x10: 0000000000000000
> x9 : 0000000000000000 x8 : ffff800023fd9c18
> x7 : 0000000000000000 x6 : 00000000ffffffff
> x5 : 0000000000000000 x4 : 0000000000021000
> Purging 5693440 bytes
> x3 : 000000000000003f x2 : 0000000000000040
> x1 : ffff80000990e000 x0 : ffff8000098ed000
> Call trace:
>  __dma_inv_area+0x40/0x58
>  dma_direct_sync_single_for_cpu+0x7c/0x80
>  dma_direct_unmap_page+0x80/0x88
>  dma_direct_unmap_sg+0x54/0x80
>  drm_gem_shmem_free_object+0xfc/0x108
>  panfrost_gem_free_object+0x118/0x128 [panfrost]
>  drm_gem_object_free+0x18/0x90
>  drm_gem_object_put_unlocked+0x58/0x80
>  drm_gem_object_handle_put_unlocked+0x64/0xb0
>  drm_gem_object_release_handle+0x70/0x98
>  drm_gem_handle_delete+0x64/0xb0
>  drm_gem_close_ioctl+0x28/0x38
>  drm_ioctl_kernel+0xb8/0x110
>  drm_ioctl+0x244/0x3f0
>  do_vfs_ioctl+0xbc/0x910
>  ksys_ioctl+0x78/0xa8
>  __arm64_sys_ioctl+0x1c/0x28
>  el0_svc_common.constprop.0+0x88/0x150
>  el0_svc_handler+0x28/0x78
>  el0_svc+0x8/0xc
>  Code: 8a230000 54000060 d50b7e20 14000002 (d5087620)
> 
> Fixes: 17acb9f35ed7 ("drm/shmem: Add madvise state and purge helpers")
> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Cc: Maxime Ripard <maxime.ripard@bootlin.com>
> Cc: Sean Paul <sean@poorly.run>
> Cc: David Airlie <airlied@linux.ie>
> Cc: Daniel Vetter <daniel@ffwll.ch>
> Signed-off-by: Rob Herring <robh@kernel.org>

Looks good to me:

Reviewed-by: Steven Price <steven.price@arm.com>

> ---
>  drivers/gpu/drm/drm_gem_shmem_helper.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
> index df8f2c8adb2b..5423ec56b535 100644
> --- a/drivers/gpu/drm/drm_gem_shmem_helper.c
> +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
> @@ -390,6 +390,12 @@ void drm_gem_shmem_purge_locked(struct drm_gem_object *obj)
>  
>  	WARN_ON(!drm_gem_shmem_is_purgeable(shmem));
>  
> +	dma_unmap_sg(obj->dev->dev, shmem->sgt->sgl,
> +		     shmem->sgt->nents, DMA_BIDIRECTIONAL);
> +	sg_free_table(shmem->sgt);
> +	kfree(shmem->sgt);
> +	shmem->sgt = NULL;
> +
>  	drm_gem_shmem_put_pages_locked(shmem);
>  
>  	shmem->madv = -1;
>

Patch
diff mbox series

diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
index df8f2c8adb2b..5423ec56b535 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -390,6 +390,12 @@  void drm_gem_shmem_purge_locked(struct drm_gem_object *obj)
 
 	WARN_ON(!drm_gem_shmem_is_purgeable(shmem));
 
+	dma_unmap_sg(obj->dev->dev, shmem->sgt->sgl,
+		     shmem->sgt->nents, DMA_BIDIRECTIONAL);
+	sg_free_table(shmem->sgt);
+	kfree(shmem->sgt);
+	shmem->sgt = NULL;
+
 	drm_gem_shmem_put_pages_locked(shmem);
 
 	shmem->madv = -1;