r535_bar_bar2_init() warns if the FB zero object cannot be wrapped or
mapped, but then continues and maps bar->flushFBZero through nvkm_kmap().
If the object was not created, nvkm_kmap() dereferences NULL. If
nvkm_kmap() returns NULL, assigning the result to bar->flushBAR2 clears
the existing physical-mode flush mapping and later r535_bar_flush() can
dereference NULL after the generic BAR2 init wrapper marks BAR2 active.
Keep the physical-mode flush mapping unless the BAR2 flush mapping was
successfully acquired. In fini, call nvkm_done() only for an acquired
BAR2 flush mapping, because nvkm_done() is not NULL-safe.
This issue was found by a static analysis checker and confirmed by
manual source review.
Fixes: 5bf0257136a2 ("drm/nouveau/mmu/r535: initial support")
Signed-off-by: Ruoyu Wang <[email protected]>
---
.../gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/bar.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/bar.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/bar.c
index fae08ac3b18c7..eb3a7ddfa3355 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/bar.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/bar.c
@@ -71,8 +71,9 @@ r535_bar_bar2_fini(struct nvkm_bar *bar)
struct nvkm_vmm *vmm = gf100_bar(bar)->bar[0].vmm;
struct nvkm_gsp *gsp = bar->subdev.device->gsp;
+ if (bar->flushFBZero && bar->flushBAR2 != bar->flushBAR2PhysMode)
+ nvkm_done(bar->flushFBZero);
bar->flushBAR2 = bar->flushBAR2PhysMode;
- nvkm_done(bar->flushFBZero);
WARN_ON(r535_bar_bar2_update_pde(gsp, vmm->func->page[0].shift, 0));
}
@@ -86,6 +87,7 @@ r535_bar_bar2_init(struct nvkm_bar *bar)
struct nvkm_memory *pdb = vmm->pd->pt[0]->memory;
u32 pdb_offset = vmm->pd->pt[0]->base;
u32 pdbe_lo, pdbe_hi;
+ void __iomem *flush;
u64 pdbe;
nvkm_kmap(pdb);
@@ -106,12 +108,16 @@ r535_bar_bar2_init(struct nvkm_bar *bar)
ret = nvkm_memory_kmap(fbZero, &bar->flushFBZero);
nvkm_memory_unref(&fbZero);
}
- WARN_ON(ret);
+ if (WARN_ON(ret))
+ return;
}
+ flush = nvkm_kmap(bar->flushFBZero);
+ if (WARN_ON(!flush))
+ return;
+
+ bar->flushBAR2 = flush;
bar->bar2 = true;
- bar->flushBAR2 = nvkm_kmap(bar->flushFBZero);
- WARN_ON(!bar->flushBAR2);
}
static void
--
2.51.0