radv/amdgpu: use host page granularity for GPU VA reservations GEM objects are rounded up to the host page size by the kernel and the VA mappings cover that whole extent, but radv reserves and places VA ranges in 4K units. Where PAGE_SIZE is bigger than AMDGPU_GPU_PAGE_SIZE the ranges overlap and the kernel rejects the map: amdgpu 0000:04:00.0: bo ... va 0x0000100201-0x0000100204 conflict with 0x0000100200-0x0000100204 Traced on ia64 (16K pages) with an Oland, the same BO handle mapped twice: GEM_VA h=7 op=1 fl=0xe va=0x100200000 sz=0x4000 -> 0 GEM_VA h=7 op=1 fl=0xa va=0x100201000 sz=0x4000 -> -1 EINVAL The read-only pad page of RADEON_FLAG_VM_PAD_1PAGE goes to va + align64(size, 4096), only 4K along, while the mapping it must sit behind is a full 16K host page. Same for the reservation in radv_amdgpu_bo_va_size() and the VA range alignment. radv then fails vkAllocateMemory, and vkcube - built with NDEBUG, so its assert(!err) is gone - carries on and dereferences a VK_NULL_HANDLE VkDeviceMemory in radv_MapMemory2(). Nothing changes where PAGE_SIZE is 4K; 64K page arm64 and ppc64 would hit this too. radv_amdgpu_winsys_bo_from_ptr() already aligns with getpagesize() for the same reason. Signed-off-by: René Rebe --- mesa-26.1.6/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c +++ mesa-26.1.6/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c @@ -92,12 +92,12 @@ radv_amdgpu_canonicalize_va(uint64_t va) static uint64_t radv_amdgpu_bo_va_size(uint64_t bo_size, uint32_t flags) { - if (flags & RADEON_FLAG_VM_PAD_1PAGE) { - const uint64_t va_padding = 4096; - return align64(bo_size, 4096) + va_padding; - } + const uint64_t page_size = MAX2(getpagesize(), 4096); + + if (flags & RADEON_FLAG_VM_PAD_1PAGE) + return align64(bo_size, page_size) + page_size; - return bo_size; + return align64(bo_size, page_size); } static void @@ -349,7 +360,7 @@ radv_amdgpu_winsys_virtual_bo_create(str return VK_ERROR_OUT_OF_HOST_MEMORY; } - unsigned virt_alignment = alignment; + unsigned virt_alignment = MAX2(alignment, (unsigned)getpagesize()); if (size >= ws->info.pte_fragment_size) virt_alignment = MAX2(virt_alignment, ws->info.pte_fragment_size); @@ -418,7 +432,7 @@ radv_amdgpu_winsys_bo_create(struct rade return VK_ERROR_OUT_OF_HOST_MEMORY; } - unsigned virt_alignment = alignment; + unsigned virt_alignment = MAX2(alignment, (unsigned)getpagesize()); if (size >= ws->info.pte_fragment_size) virt_alignment = MAX2(virt_alignment, ws->info.pte_fragment_size); @@ -528,8 +545,9 @@ radv_amdgpu_winsys_bo_create(struct rade if (flags & RADEON_FLAG_VM_PAD_1PAGE) { /* Map the first page of the same BO as read-only after the BO itself. */ - r = radv_amdgpu_bo_va_op(ws, kms_handle, 0, 4096, va + align64(size, 4096), flags | RADEON_FLAG_READ_ONLY, 0, - AMDGPU_VA_OP_MAP); + const uint64_t page_size = MAX2(getpagesize(), 4096); + r = radv_amdgpu_bo_va_op(ws, kms_handle, 0, page_size, va + align64(size, page_size), + flags | RADEON_FLAG_READ_ONLY, 0, AMDGPU_VA_OP_MAP); if (r) { result = VK_ERROR_OUT_OF_DEVICE_MEMORY; goto error_va_map;