anv: Fix placed address mmap with slab bo
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

The current implmentation adjust the mmap() parameters to make it work, but that
causes us to map more addresses than application asked what could cause us to
overwrite other application mmaps().

So here we export the slab parent as a dma-buf, then do the mmap with almost no
adjustment, the only change is the offset that needs to include the difference
between bo address and slab bo parent address.

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40441>
This commit is contained in:
José Roberto de Souza 2026-03-09 10:17:03 -07:00 committed by Marge Bot
parent fddc101070
commit 889cf429ee
3 changed files with 76 additions and 9 deletions

View file

@ -33,6 +33,7 @@
#include "common/intel_aux_map.h"
#include "util/anon_file.h"
#include "util/futex.h"
#include "util/os_mman.h"
#ifdef HAVE_VALGRIND
#define VG_NOACCESS_READ(__ptr) ({ \
@ -1763,6 +1764,46 @@ anv_device_alloc_bo(struct anv_device *device,
return VK_SUCCESS;
}
static VkResult
map_placed_addr_slab(struct anv_device *device,
struct anv_bo *bo,
uint64_t offset,
size_t size,
void *placed_addr,
void **map_out)
{
int prime_handle = anv_gem_handle_to_fd(device, bo->gem_handle);
VkResult result = VK_SUCCESS;
if (prime_handle < 0) {
return vk_errorf(device, VK_ERROR_MEMORY_MAP_FAILED,
"anv_gem_handle_to_fd() before mmap failed: %m");
}
offset += (bo->offset - bo->slab_parent->offset);
void *map = os_mmap(placed_addr,
size,
PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_SHARED,
prime_handle,
offset);
if (map == MAP_FAILED) {
result = vk_errorf(device, VK_ERROR_MEMORY_MAP_FAILED, "mmap failed: %m");
goto end;
}
assert(placed_addr == NULL || map == placed_addr);
assert(map != NULL);
VG(VALGRIND_MALLOCLIKE_BLOCK(map, size, 0, 1));
if (map_out)
*map_out = map;
end:
close(prime_handle);
return result;
}
VkResult
anv_device_map_bo(struct anv_device *device,
struct anv_bo *bo,
@ -1777,6 +1818,9 @@ anv_device_map_bo(struct anv_device *device,
struct anv_bo *real = anv_bo_get_real(bo);
uint64_t offset_adjustment = 0;
if (real != bo) {
if (placed_addr)
return map_placed_addr_slab(device, bo, offset, size, placed_addr, map_out);
offset += (bo->offset - real->offset);
const uint64_t page_size = device->physical->page_size;
@ -1786,9 +1830,6 @@ anv_device_map_bo(struct anv_device *device,
offset_adjustment = offset - munmap_offset;
size += offset_adjustment;
offset = munmap_offset;
if (placed_addr)
placed_addr -= offset_adjustment;
}
assert((offset & (page_size - 1)) == 0);

View file

@ -91,7 +91,7 @@ anv_gem_handle_to_fd(struct anv_device *device, uint32_t gem_handle)
int ret = intel_ioctl(device->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
if (ret == -1)
return -1;
return -errno;
return args.fd;
}

View file

@ -32,6 +32,27 @@
#include "drm-uapi/gpu_scheduler.h"
#include "drm-uapi/xe_drm.h"
static bool
is_slab_parent_memory_mapped_placeable(struct anv_device *device,
enum anv_bo_alloc_flags alloc_flags)
{
if ((alloc_flags & ANV_BO_ALLOC_SLAB_PARENT) == false)
return false;
if (device->physical->instance->debug & ANV_DEBUG_NO_SLAB)
return false;
if (!device->vk.enabled_features.memoryMapPlaced)
return false;
/* Not subject to vkMapMemory*() */
enum anv_bo_alloc_flags no_vk_map_memory = ANV_BO_ALLOC_COMPRESSED |
ANV_BO_ALLOC_INTERNAL |
ANV_BO_ALLOC_DESCRIPTOR_POOL;
if (alloc_flags & no_vk_map_memory)
return false;
return true;
}
static uint32_t
xe_gem_create(struct anv_device *device,
const struct intel_memory_class_instance **regions,
@ -70,12 +91,17 @@ xe_gem_create(struct anv_device *device,
device->info->xe2_has_no_compression_hint)
flags |= DRM_XE_GEM_CREATE_FLAG_NO_COMPRESSION;
/* From xe_drm.h: If a VM is specified, this BO must:
* 1. Only ever be bound to that VM.
* 2. Cannot be exported as a PRIME fd.
*/
uint32_t vm_id = device->vm_id;
if ((alloc_flags & ANV_BO_ALLOC_EXTERNAL) ||
is_slab_parent_memory_mapped_placeable(device, alloc_flags))
vm_id = 0;
struct drm_xe_gem_create gem_create = {
/* From xe_drm.h: If a VM is specified, this BO must:
* 1. Only ever be bound to that VM.
* 2. Cannot be exported as a PRIME fd.
*/
.vm_id = alloc_flags & ANV_BO_ALLOC_EXTERNAL ? 0 : device->vm_id,
.vm_id = vm_id,
.size = align64(size, device->info->mem_alignment),
.flags = flags,
};