mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-07 07:08:04 +02:00
anv: Fix placed address mmap with slab bo
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:
parent
fddc101070
commit
889cf429ee
3 changed files with 76 additions and 9 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue