intel: Export raw GEM mmap interfaces

Export a set of interfaces to allow the caller to have precise control
over mapping the buffer - but still provide caching of the mmaps between
callers.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
main
Chris Wilson 2015-05-01 13:39:55 +01:00
parent 2d8c01f256
commit 455e9b4917
2 changed files with 158 additions and 0 deletions

View File

@ -184,6 +184,10 @@ int drm_intel_gem_bo_map_unsynchronized(drm_intel_bo *bo);
int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo);
int drm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo);
void *drm_intel_gem_bo_map__cpu(drm_intel_bo *bo);
void *drm_intel_gem_bo_map__gtt(drm_intel_bo *bo);
void *drm_intel_gem_bo_map__wc(drm_intel_bo *bo);
int drm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo);
void drm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start);
void drm_intel_gem_bo_start_gtt_access(drm_intel_bo *bo, int write_enable);

View File

@ -211,6 +211,8 @@ struct _drm_intel_bo_gem {
void *mem_virtual;
/** GTT virtual address for the buffer, saved across map/unmap cycles */
void *gtt_virtual;
/** WC CPU address for the buffer, saved across map/unmap cycles */
void *wc_virtual;
/**
* Virtual address of the buffer allocated by user, used for userptr
* objects only.
@ -1188,6 +1190,11 @@ drm_intel_gem_bo_free(drm_intel_bo *bo)
drm_munmap(bo_gem->mem_virtual, bo_gem->bo.size);
bufmgr_gem->vma_count--;
}
if (bo_gem->wc_virtual) {
VG(VALGRIND_FREELIKE_BLOCK(bo_gem->wc_virtual, 0));
drm_munmap(bo_gem->wc_virtual, bo_gem->bo.size);
bufmgr_gem->vma_count--;
}
if (bo_gem->gtt_virtual) {
drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size);
bufmgr_gem->vma_count--;
@ -1213,6 +1220,9 @@ drm_intel_gem_bo_mark_mmaps_incoherent(drm_intel_bo *bo)
if (bo_gem->mem_virtual)
VALGRIND_MAKE_MEM_NOACCESS(bo_gem->mem_virtual, bo->size);
if (bo_gem->wc_virtual)
VALGRIND_MAKE_MEM_NOACCESS(bo_gem->wc_virtual, bo->size);
if (bo_gem->gtt_virtual)
VALGRIND_MAKE_MEM_NOACCESS(bo_gem->gtt_virtual, bo->size);
#endif
@ -1277,6 +1287,11 @@ static void drm_intel_gem_bo_purge_vma_cache(drm_intel_bufmgr_gem *bufmgr_gem)
bo_gem->mem_virtual = NULL;
bufmgr_gem->vma_count--;
}
if (bo_gem->wc_virtual) {
drm_munmap(bo_gem->wc_virtual, bo_gem->bo.size);
bo_gem->wc_virtual = NULL;
bufmgr_gem->vma_count--;
}
if (bo_gem->gtt_virtual) {
drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size);
bo_gem->gtt_virtual = NULL;
@ -1292,6 +1307,8 @@ static void drm_intel_gem_bo_close_vma(drm_intel_bufmgr_gem *bufmgr_gem,
DRMLISTADDTAIL(&bo_gem->vma_list, &bufmgr_gem->vma_cache);
if (bo_gem->mem_virtual)
bufmgr_gem->vma_count++;
if (bo_gem->wc_virtual)
bufmgr_gem->vma_count++;
if (bo_gem->gtt_virtual)
bufmgr_gem->vma_count++;
drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
@ -1304,6 +1321,8 @@ static void drm_intel_gem_bo_open_vma(drm_intel_bufmgr_gem *bufmgr_gem,
DRMLISTDEL(&bo_gem->vma_list);
if (bo_gem->mem_virtual)
bufmgr_gem->vma_count--;
if (bo_gem->wc_virtual)
bufmgr_gem->vma_count--;
if (bo_gem->gtt_virtual)
bufmgr_gem->vma_count--;
drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
@ -3330,6 +3349,141 @@ drm_intel_bufmgr_gem_unref(drm_intel_bufmgr *bufmgr)
}
}
void *drm_intel_gem_bo_map__gtt(drm_intel_bo *bo)
{
drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
if (bo_gem->gtt_virtual)
return bo_gem->gtt_virtual;
if (bo_gem->is_userptr)
return NULL;
pthread_mutex_lock(&bufmgr_gem->lock);
if (bo_gem->gtt_virtual == NULL) {
struct drm_i915_gem_mmap_gtt mmap_arg;
void *ptr;
DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n",
bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
if (bo_gem->map_count++ == 0)
drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
memclear(mmap_arg);
mmap_arg.handle = bo_gem->gem_handle;
/* Get the fake offset back... */
ptr = MAP_FAILED;
if (drmIoctl(bufmgr_gem->fd,
DRM_IOCTL_I915_GEM_MMAP_GTT,
&mmap_arg) == 0) {
/* and mmap it */
ptr = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE,
MAP_SHARED, bufmgr_gem->fd,
mmap_arg.offset);
}
if (ptr == MAP_FAILED) {
if (--bo_gem->map_count == 0)
drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
ptr = NULL;
}
bo_gem->gtt_virtual = ptr;
}
pthread_mutex_unlock(&bufmgr_gem->lock);
return bo_gem->gtt_virtual;
}
void *drm_intel_gem_bo_map__cpu(drm_intel_bo *bo)
{
drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
if (bo_gem->mem_virtual)
return bo_gem->mem_virtual;
if (bo_gem->is_userptr) {
/* Return the same user ptr */
return bo_gem->user_virtual;
}
pthread_mutex_lock(&bufmgr_gem->lock);
if (!bo_gem->mem_virtual) {
struct drm_i915_gem_mmap mmap_arg;
if (bo_gem->map_count++ == 0)
drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
DBG("bo_map: %d (%s), map_count=%d\n",
bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
memclear(mmap_arg);
mmap_arg.handle = bo_gem->gem_handle;
mmap_arg.size = bo->size;
if (drmIoctl(bufmgr_gem->fd,
DRM_IOCTL_I915_GEM_MMAP,
&mmap_arg)) {
DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
__FILE__, __LINE__, bo_gem->gem_handle,
bo_gem->name, strerror(errno));
if (--bo_gem->map_count == 0)
drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
} else {
VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1));
bo_gem->mem_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr;
}
}
pthread_mutex_unlock(&bufmgr_gem->lock);
return bo_gem->mem_virtual;
}
void *drm_intel_gem_bo_map__wc(drm_intel_bo *bo)
{
drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
if (bo_gem->wc_virtual)
return bo_gem->wc_virtual;
if (bo_gem->is_userptr)
return NULL;
pthread_mutex_lock(&bufmgr_gem->lock);
if (!bo_gem->wc_virtual) {
struct drm_i915_gem_mmap mmap_arg;
if (bo_gem->map_count++ == 0)
drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
DBG("bo_map: %d (%s), map_count=%d\n",
bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
memclear(mmap_arg);
mmap_arg.handle = bo_gem->gem_handle;
mmap_arg.size = bo->size;
mmap_arg.flags = I915_MMAP_WC;
if (drmIoctl(bufmgr_gem->fd,
DRM_IOCTL_I915_GEM_MMAP,
&mmap_arg)) {
DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
__FILE__, __LINE__, bo_gem->gem_handle,
bo_gem->name, strerror(errno));
if (--bo_gem->map_count == 0)
drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
} else {
VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1));
bo_gem->wc_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr;
}
}
pthread_mutex_unlock(&bufmgr_gem->lock);
return bo_gem->wc_virtual;
}
/**
* Initializes the GEM buffer manager, which uses the kernel to allocate, map,
* and manage map buffer objections.