Mesa (master): winsys/radeon: Unmap GPU VM address range when destroying BO

Michel Dänzer daenzer at kemper.freedesktop.org
Wed Jun 24 06:25:18 UTC 2015


Module: Mesa
Branch: master
Commit: 7796e8889a9a2cc1b454dc32d8da3d756404339a
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=7796e8889a9a2cc1b454dc32d8da3d756404339a

Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu May 21 10:49:05 2015 +0900

winsys/radeon: Unmap GPU VM address range when destroying BO

But only when doing so is safe according to the
RADEON_INFO_VA_UNMAP_WORKING kernel query.

This avoids kernel GPU VM address range conflicts when the BO has other
references than the GEM handle being closed, e.g. when the BO is shared.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90537
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90873

Cc: "10.5 10.6" <mesa-stable at lists.freedesktop.org>
Reviewed-by: Christian König <christian.koenig at amd.com>

---

 src/gallium/winsys/radeon/drm/radeon_drm_bo.c     |   28 ++++++++++++++++++---
 src/gallium/winsys/radeon/drm/radeon_drm_winsys.c |    4 +++
 src/gallium/winsys/radeon/drm/radeon_drm_winsys.h |    1 +
 3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
index fe98870..78c95b1 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
@@ -305,14 +305,34 @@ static void radeon_bo_destroy(struct pb_buffer *_buf)
     if (bo->ptr)
         os_munmap(bo->ptr, bo->base.size);
 
+    if (mgr->va) {
+        if (bo->rws->va_unmap_working) {
+            struct drm_radeon_gem_va va;
+
+            va.handle = bo->handle;
+            va.vm_id = 0;
+            va.operation = RADEON_VA_UNMAP;
+            va.flags = RADEON_VM_PAGE_READABLE |
+                       RADEON_VM_PAGE_WRITEABLE |
+                       RADEON_VM_PAGE_SNOOPED;
+            va.offset = bo->va;
+
+            if (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_VA, &va,
+				    sizeof(va)) != 0 &&
+		va.operation == RADEON_VA_RESULT_ERROR) {
+                fprintf(stderr, "radeon: Failed to deallocate virtual address for buffer:\n");
+                fprintf(stderr, "radeon:    size      : %d bytes\n", bo->base.size);
+                fprintf(stderr, "radeon:    va        : 0x%016llx\n", (unsigned long long)bo->va);
+            }
+	}
+
+	radeon_bomgr_free_va(mgr, bo->va, bo->base.size);
+    }
+
     /* Close object. */
     args.handle = bo->handle;
     drmIoctl(bo->rws->fd, DRM_IOCTL_GEM_CLOSE, &args);
 
-    if (mgr->va) {
-        radeon_bomgr_free_va(mgr, bo->va, bo->base.size);
-    }
-
     pipe_mutex_destroy(bo->map_mutex);
 
     if (bo->initial_domain & RADEON_DOMAIN_VRAM)
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
index ba8d143..d457f8a 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
@@ -57,6 +57,8 @@
 #define RADEON_INFO_READ_REG		0x24
 #endif
 
+#define RADEON_INFO_VA_UNMAP_WORKING	0x25
+
 static struct util_hash_table *fd_tab = NULL;
 pipe_static_mutex(fd_tab_mutex);
 
@@ -399,6 +401,8 @@ static boolean do_winsys_init(struct radeon_drm_winsys *ws)
             if (!radeon_get_drm_value(ws->fd, RADEON_INFO_IB_VM_MAX_SIZE, NULL,
                                       &ib_vm_max_size))
                 ws->info.r600_virtual_address = FALSE;
+            radeon_get_drm_value(ws->fd, RADEON_INFO_VA_UNMAP_WORKING, NULL,
+                                 &ws->va_unmap_working);
         }
 	if (ws->gen == DRV_R600 && !debug_get_bool_option("RADEON_VA", FALSE))
 		ws->info.r600_virtual_address = FALSE;
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h
index 166b6b9..99c8b8a 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h
@@ -74,6 +74,7 @@ struct radeon_drm_winsys {
     enum radeon_generation gen;
     struct radeon_info info;
     uint32_t va_start;
+    uint32_t va_unmap_working;
     uint32_t accel_working2;
 
     struct pb_manager *kman;




More information about the mesa-commit mailing list