From f0fca24ffb03c14647e03d611b901bf02426c37a Mon Sep 17 00:00:00 2001 From: Debarshi Dutta Date: Thu, 31 Oct 2019 16:03:33 +0530 Subject: gpu: nvgpu: avoid double mapping of usermode mmap region gk20a_pm_runtime_suspend can fail and invoke gk20a_pm_finalize_poweron that can cause double mapping of the usermode mmap region via io_remap_pfn_range(). Avoid this by using a boolean variable to track whether the region is already mapped. Bug 2707416 Bug 200582208 Change-Id: I4d8cbe427400a5b986348a19af145367cc08ffc6 Signed-off-by: Debarshi Dutta Reviewed-on: https://git-master.nvidia.com/r/2229312 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2283801 Reviewed-by: Kajetan Dutka Reviewed-by: Thomas Fleury Reviewed-by: Amulya Yarlagadda Reviewed-by: mobile promotions Tested-by: Kajetan Dutka Tested-by: mobile promotions --- drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/nvgpu') diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c index 9b4f50a5..dfa9edf3 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c @@ -60,6 +60,7 @@ struct gk20a_ctrl_priv { struct { struct vm_area_struct *vma; unsigned long flags; + bool vma_mapped; } usermode_vma; }; @@ -1925,6 +1926,7 @@ static void usermode_vma_close(struct vm_area_struct *vma) nvgpu_mutex_acquire(&l->ctrl.privs_lock); priv->usermode_vma.vma = NULL; + priv->usermode_vma.vma_mapped = false; nvgpu_mutex_release(&l->ctrl.privs_lock); } @@ -1974,6 +1976,7 @@ int gk20a_ctrl_dev_mmap(struct file *filp, struct vm_area_struct *vma) priv->usermode_vma.vma = vma; priv->usermode_vma.flags = vma->vm_flags; vma->vm_private_data = priv; + priv->usermode_vma.vma_mapped = true; } nvgpu_mutex_release(&l->ctrl.privs_lock); @@ -1988,6 +1991,7 @@ static void alter_usermode_mapping(struct gk20a *g, { struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); struct vm_area_struct *vma = priv->usermode_vma.vma; + bool vma_mapped = priv->usermode_vma.vma_mapped; u64 addr; int err; @@ -2000,14 +2004,20 @@ static void alter_usermode_mapping(struct gk20a *g, down_write(&vma->vm_mm->mmap_sem); - if (poweroff) { + /* + * This is a no-op for the below cases + * a) poweroff and !vma_mapped - > do nothing as no map exists + * b) !poweroff and vmap_mapped -> do nothing as already mapped + */ + if (poweroff && vma_mapped) { err = zap_vma_ptes(vma, vma->vm_start, SZ_4K); if (err == 0) { vma->vm_flags = VM_NONE; + priv->usermode_vma.vma_mapped = false; } else { nvgpu_err(g, "can't remove usermode mapping"); } - } else { + } else if (!poweroff && !vma_mapped) { vma->vm_flags = priv->usermode_vma.flags; err = io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT, @@ -2015,6 +2025,8 @@ static void alter_usermode_mapping(struct gk20a *g, if (err != 0) { nvgpu_err(g, "can't restore usermode mapping"); vma->vm_flags = VM_NONE; + } else { + priv->usermode_vma.vma_mapped = true; } } -- cgit v1.2.2