From 298e247776309b4444b4c3ac26872fc1f694568c Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 22 Apr 2020 15:03:15 +0200 Subject: [PATCH] winsys/svga: Optionally avoid caching buffer maps Mapping of graphics kernel buffers is quite costly. Therefore the svga drm winsys caches all kernel buffer maps. However, that may lead to less testing coverage of the unmap paths and (possibly) processes running out of virtual memory space. Introduce a possibility to avoid that caching by setting the environment variable SVGA_FORCE_KERNEL_UNMAPS to 1. Signed-off-by: Thomas Hellstrom Reviewed-by: Roland Scheidegger Reviewed-by: Matthew McClure Part-of: --- src/gallium/winsys/svga/drm/vmw_buffer.c | 17 ++++++++++++++--- src/gallium/winsys/svga/drm/vmw_screen.c | 3 +++ src/gallium/winsys/svga/drm/vmw_screen.h | 1 + src/gallium/winsys/svga/drm/vmw_screen_ioctl.c | 13 ++++--------- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/gallium/winsys/svga/drm/vmw_buffer.c b/src/gallium/winsys/svga/drm/vmw_buffer.c index e2ddf78ed2e..03db92a6481 100644 --- a/src/gallium/winsys/svga/drm/vmw_buffer.c +++ b/src/gallium/winsys/svga/drm/vmw_buffer.c @@ -63,6 +63,7 @@ struct vmw_gmr_buffer struct vmw_region *region; void *map; unsigned map_flags; + unsigned map_count; }; @@ -104,8 +105,12 @@ vmw_gmr_buffer_destroy(struct pb_buffer *_buf) { struct vmw_gmr_buffer *buf = vmw_gmr_buffer(_buf); - vmw_ioctl_region_unmap(buf->region); - + assert(buf->map_count == 0); + if (buf->map) { + assert(buf->mgr->vws->cache_maps); + vmw_ioctl_region_unmap(buf->region); + } + vmw_ioctl_region_destroy(buf->region); FREE(buf); @@ -126,7 +131,6 @@ vmw_gmr_buffer_map(struct pb_buffer *_buf, if (!buf->map) return NULL; - if ((_buf->usage & VMW_BUFFER_USAGE_SYNC) && !(flags & PB_USAGE_UNSYNCHRONIZED)) { ret = vmw_ioctl_syncforcpu(buf->region, @@ -137,6 +141,7 @@ vmw_gmr_buffer_map(struct pb_buffer *_buf, return NULL; } + buf->map_count++; return buf->map; } @@ -153,6 +158,12 @@ vmw_gmr_buffer_unmap(struct pb_buffer *_buf) !(flags & PB_USAGE_CPU_WRITE), FALSE); } + + assert(buf->map_count > 0); + if (!--buf->map_count && !buf->mgr->vws->cache_maps) { + vmw_ioctl_region_unmap(buf->region); + buf->map = NULL; + } } diff --git a/src/gallium/winsys/svga/drm/vmw_screen.c b/src/gallium/winsys/svga/drm/vmw_screen.c index 8b4b89981b2..2f70212de61 100644 --- a/src/gallium/winsys/svga/drm/vmw_screen.c +++ b/src/gallium/winsys/svga/drm/vmw_screen.c @@ -67,6 +67,7 @@ vmw_winsys_create( int fd ) { struct vmw_winsys_screen *vws; struct stat stat_buf; + const char *getenv_val; if (dev_hash == NULL) { dev_hash = _mesa_hash_table_create(NULL, vmw_dev_hash, vmw_dev_compare); @@ -97,6 +98,8 @@ vmw_winsys_create( int fd ) vws->base.have_gb_dma = !vws->force_coherent; vws->base.need_to_rebind_resources = FALSE; vws->base.have_transfer_from_buffer_cmd = vws->base.have_vgpu10; + getenv_val = getenv("SVGA_FORCE_KERNEL_UNMAPS"); + vws->cache_maps = !getenv_val || strcmp(getenv_val, "0") == 0; vws->fence_ops = vmw_fence_ops_create(vws); if (!vws->fence_ops) goto out_no_fence_ops; diff --git a/src/gallium/winsys/svga/drm/vmw_screen.h b/src/gallium/winsys/svga/drm/vmw_screen.h index c55de4a2b6f..4cf6b3fd895 100644 --- a/src/gallium/winsys/svga/drm/vmw_screen.h +++ b/src/gallium/winsys/svga/drm/vmw_screen.h @@ -108,6 +108,7 @@ struct vmw_winsys_screen mtx_t cs_mutex; boolean force_coherent; + boolean cache_maps; }; diff --git a/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c b/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c index 9696f884e4f..bb3a1adedc1 100644 --- a/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c +++ b/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c @@ -64,7 +64,6 @@ struct vmw_region uint32_t handle; uint64_t map_handle; void *data; - uint32_t map_count; int drm_fd; uint32_t size; }; @@ -637,7 +636,6 @@ vmw_ioctl_region_create(struct vmw_winsys_screen *vws, uint32_t size) region->data = NULL; region->handle = rep->handle; region->map_handle = rep->map_handle; - region->map_count = 0; region->size = size; region->drm_fd = vws->ioctl.drm_fd; @@ -659,10 +657,7 @@ vmw_ioctl_region_destroy(struct vmw_region *region) vmw_printf("%s: gmrId = %u, offset = %u\n", __FUNCTION__, region->ptr.gmrId, region->ptr.offset); - if (region->data) { - os_munmap(region->data, region->size); - region->data = NULL; - } + assert(region->data == NULL); memset(&arg, 0, sizeof(arg)); arg.handle = region->handle; @@ -701,8 +696,6 @@ vmw_ioctl_region_map(struct vmw_region *region) region->data = map; } - ++region->map_count; - return region->data; } @@ -711,7 +704,9 @@ vmw_ioctl_region_unmap(struct vmw_region *region) { vmw_printf("%s: gmrId = %u, offset = %u\n", __FUNCTION__, region->ptr.gmrId, region->ptr.offset); - --region->map_count; + + os_munmap(region->data, region->size); + region->data = NULL; } /** -- 2.30.2