mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 17:36:20 +03:00
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 <ddutta@nvidia.com> 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 <kdutka@nvidia.com> Reviewed-by: Thomas Fleury <tfleury@nvidia.com> Reviewed-by: Amulya Yarlagadda <ayarlagadda@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: Kajetan Dutka <kdutka@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
9e9046f03c
commit
f0fca24ffb
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user