anv: Add gem_mmap to kmd backend

Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21255>
This commit is contained in:
José Roberto de Souza 2023-02-09 06:29:28 -08:00 committed by Marge Bot
parent 32a8250b46
commit 0c8d8ae13c
7 changed files with 104 additions and 82 deletions

View file

@ -1503,7 +1503,7 @@ anv_device_alloc_bo(struct anv_device *device,
if (alloc_flags & ANV_BO_ALLOC_MAPPED) {
VkResult result = anv_device_map_bo(device, &new_bo, 0, size,
0 /* gem_flags */, &new_bo.map);
0 /* propertyFlags */, &new_bo.map);
if (unlikely(result != VK_SUCCESS)) {
device->kmd_backend->gem_close(device, new_bo.gem_handle);
return result;
@ -1562,16 +1562,13 @@ anv_device_map_bo(struct anv_device *device,
struct anv_bo *bo,
uint64_t offset,
size_t size,
uint32_t gem_flags,
VkMemoryPropertyFlags property_flags,
void **map_out)
{
assert(!bo->from_host_ptr);
assert(size > 0);
if (bo->map_wc)
gem_flags |= I915_MMAP_WC;
void *map = anv_gem_mmap(device, bo, offset, size, gem_flags);
void *map = anv_gem_mmap(device, bo, offset, size, property_flags);
if (unlikely(map == MAP_FAILED))
return vk_errorf(device, VK_ERROR_MEMORY_MAP_FAILED, "mmap failed: %m");

View file

@ -4255,12 +4255,6 @@ VkResult anv_MapMemory(
"Memory object already mapped.");
}
uint32_t gem_flags = 0;
if (!device->info->has_llc &&
(mem->type->propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
gem_flags |= I915_MMAP_WC;
/* GEM will fail to map if the offset isn't 4k-aligned. Round down. */
uint64_t map_offset;
if (!device->physical->info.has_mmap_offset)
@ -4274,8 +4268,8 @@ VkResult anv_MapMemory(
map_size = align64(map_size, 4096);
void *map;
VkResult result = anv_device_map_bo(device, mem->bo, map_offset,
map_size, gem_flags, &map);
VkResult result = anv_device_map_bo(device, mem->bo, map_offset, map_size,
mem->type->propertyFlags, &map);
if (result != VK_SUCCESS)
return result;

View file

@ -32,64 +32,12 @@
#include "anv_private.h"
#include "common/intel_gem.h"
/**
* Wrapper around DRM_IOCTL_I915_GEM_MMAP. Returns MAP_FAILED on error.
*/
static void*
anv_gem_mmap_offset(struct anv_device *device, uint32_t gem_handle,
uint64_t offset, uint64_t size, uint32_t flags)
void *
anv_gem_mmap(struct anv_device *device, struct anv_bo *bo, uint64_t offset,
uint64_t size, VkMemoryPropertyFlags property_flags)
{
struct drm_i915_gem_mmap_offset gem_mmap = {
.handle = gem_handle,
.flags = device->info->has_local_mem ? I915_MMAP_OFFSET_FIXED :
(flags & I915_MMAP_WC) ? I915_MMAP_OFFSET_WC : I915_MMAP_OFFSET_WB,
};
assert(offset == 0);
/* Get the fake offset back */
int ret = intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_MMAP_OFFSET, &gem_mmap);
if (ret != 0)
return MAP_FAILED;
/* And map it */
void *map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
device->fd, gem_mmap.offset);
return map;
}
static void*
anv_gem_mmap_legacy(struct anv_device *device, uint32_t gem_handle,
uint64_t offset, uint64_t size, uint32_t flags)
{
assert(!device->info->has_local_mem);
struct drm_i915_gem_mmap gem_mmap = {
.handle = gem_handle,
.offset = offset,
.size = size,
.flags = flags,
};
int ret = intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_MMAP, &gem_mmap);
if (ret != 0)
return MAP_FAILED;
return (void *)(uintptr_t) gem_mmap.addr_ptr;
}
/**
* Wrapper around DRM_IOCTL_I915_GEM_MMAP. Returns MAP_FAILED on error.
*/
void*
anv_gem_mmap(struct anv_device *device, struct anv_bo *bo,
uint64_t offset, uint64_t size, uint32_t flags)
{
uint32_t gem_handle = bo->gem_handle;
void *map;
if (device->physical->info.has_mmap_offset)
map = anv_gem_mmap_offset(device, gem_handle, offset, size, flags);
else
map = anv_gem_mmap_legacy(device, gem_handle, offset, size, flags);
void *map = device->kmd_backend->gem_mmap(device, bo, offset, size,
property_flags);
if (map != MAP_FAILED)
VG(VALGRIND_MALLOCLIKE_BLOCK(map, size, 0, 1));
@ -98,7 +46,7 @@ anv_gem_mmap(struct anv_device *device, struct anv_bo *bo,
}
/* This is just a wrapper around munmap, but it also notifies valgrind that
* this map is no longer valid. Pair this with anv_gem_mmap().
* this map is no longer valid. Pair this with gem_mmap().
*/
void
anv_gem_munmap(struct anv_device *device, void *p, uint64_t size)

View file

@ -48,19 +48,29 @@ stub_gem_create(struct anv_device *device,
return fd;
}
void*
anv_gem_mmap(struct anv_device *device, struct anv_bo *bo,
uint64_t offset, uint64_t size, uint32_t flags)
static void *
stub_gem_mmap(struct anv_device *device, struct anv_bo *bo, uint64_t offset,
uint64_t size, VkMemoryPropertyFlags property_flags)
{
/* Ignore flags, as they're specific to I915_GEM_MMAP. */
(void) flags;
return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->gem_handle,
offset);
}
return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
bo->gem_handle, offset);
void *
anv_gem_mmap(struct anv_device *device, struct anv_bo *bo, uint64_t offset,
uint64_t size, VkMemoryPropertyFlags property_flags)
{
void *map = device->kmd_backend->gem_mmap(device, bo, offset, size,
property_flags);
if (map != MAP_FAILED)
VG(VALGRIND_MALLOCLIKE_BLOCK(map, size, 0, 1));
return map;
}
/* This is just a wrapper around munmap, but it also notifies valgrind that
* this map is no longer valid. Pair this with anv_gem_mmap().
* this map is no longer valid. Pair this with gem_mmap().
*/
void
anv_gem_munmap(struct anv_device *device, void *p, uint64_t size)
@ -123,6 +133,7 @@ const struct anv_kmd_backend *anv_stub_kmd_backend_get(void)
static const struct anv_kmd_backend stub_backend = {
.gem_create = stub_gem_create,
.gem_close = stub_gem_close,
.gem_mmap = stub_gem_mmap,
};
return &stub_backend;
}

View file

@ -25,9 +25,12 @@
#include <stdint.h>
#include "vulkan/vulkan_core.h"
#include "dev/intel_device_info.h"
#include "dev/intel_kmd.h"
struct anv_bo;
enum anv_bo_alloc_flags;
struct anv_device;
@ -41,6 +44,10 @@ struct anv_kmd_backend {
uint16_t num_regions, uint64_t size,
enum anv_bo_alloc_flags alloc_flags);
void (*gem_close)(struct anv_device *device, uint32_t handle);
/* Returns MAP_FAILED on error */
void *(*gem_mmap)(struct anv_device *device, struct anv_bo *bo,
uint64_t offset, uint64_t size,
VkMemoryPropertyFlags property_flags);
};
const struct anv_kmd_backend *anv_kmd_backend_get(enum intel_kmd_type type);

View file

@ -1349,8 +1349,9 @@ VkResult anv_queue_submit(struct vk_queue *queue,
VkResult anv_queue_submit_simple_batch(struct anv_queue *queue,
struct anv_batch *batch);
void* anv_gem_mmap(struct anv_device *device, struct anv_bo *bo,
uint64_t offset, uint64_t size, uint32_t flags);
void *
anv_gem_mmap(struct anv_device *device, struct anv_bo *bo, uint64_t offset,
uint64_t size, VkMemoryPropertyFlags property_flags);
void anv_gem_munmap(struct anv_device *device, void *p, uint64_t size);
uint32_t anv_gem_userptr(struct anv_device *device, void *mem, size_t size);
int anv_gem_wait(struct anv_device *device, uint32_t gem_handle, int64_t *timeout_ns);

View file

@ -21,6 +21,8 @@
* IN THE SOFTWARE.
*/
#include <sys/mman.h>
#include "anv_private.h"
#include "drm-uapi/i915_drm.h"
@ -84,12 +86,74 @@ i915_gem_close(struct anv_device *device, uint32_t handle)
intel_ioctl(device->fd, DRM_IOCTL_GEM_CLOSE, &close);
}
static void *
i915_gem_mmap_offset(struct anv_device *device, struct anv_bo *bo,
uint64_t size, uint32_t flags)
{
struct drm_i915_gem_mmap_offset gem_mmap = {
.handle = bo->gem_handle,
.flags = flags,
};
if (intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_MMAP_OFFSET, &gem_mmap))
return MAP_FAILED;
return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
device->fd, gem_mmap.offset);
}
static void *
i915_gem_mmap_legacy(struct anv_device *device, struct anv_bo *bo, uint64_t offset,
uint64_t size, uint32_t flags)
{
struct drm_i915_gem_mmap gem_mmap = {
.handle = bo->gem_handle,
.offset = offset,
.size = size,
.flags = flags,
};
if (intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_MMAP, &gem_mmap))
return MAP_FAILED;
return (void *)(uintptr_t) gem_mmap.addr_ptr;
}
static uint32_t
mmap_calc_flags(struct anv_device *device, struct anv_bo *bo,
VkMemoryPropertyFlags property_flags)
{
if (device->info->has_local_mem)
return I915_MMAP_OFFSET_FIXED;
uint32_t flags = 0;
if (!device->info->has_llc &&
(property_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
flags |= I915_MMAP_WC;
if (bo->map_wc)
flags |= I915_MMAP_WC;
if (likely(device->physical->info.has_mmap_offset))
flags = (flags & I915_MMAP_WC) ? I915_MMAP_OFFSET_WC : I915_MMAP_OFFSET_WB;
return flags;
}
static void *
i915_gem_mmap(struct anv_device *device, struct anv_bo *bo, uint64_t offset,
uint64_t size, VkMemoryPropertyFlags property_flags)
{
const uint32_t flags = mmap_calc_flags(device, bo, property_flags);
if (likely(device->physical->info.has_mmap_offset))
return i915_gem_mmap_offset(device, bo, size, flags);
return i915_gem_mmap_legacy(device, bo, offset, size, flags);
}
const struct anv_kmd_backend *
anv_i915_kmd_backend_get(void)
{
static const struct anv_kmd_backend i915_backend = {
.gem_create = i915_gem_create,
.gem_close = i915_gem_close,
.gem_mmap = i915_gem_mmap,
};
return &i915_backend;
}