nvk/nvkmd: Fix alignments

Previously, there was some mixing up of alignments between the alignment
provided by the caller, and the minimum alignment we have (4KiB). Additionally,
there was some redundant aligning being done to data already passed in aligned.
This didn't matter because we were always using 4K pages anyways due to kernel
limitations. However, this now needs fixing to allow for larger page support.

Reviewed-by: Mel Henning <mhenning@darkrefraction.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38702>
This commit is contained in:
Mohamed Ahmed 2025-07-22 21:01:01 +03:00 committed by Marge Bot
parent 88b92dc3d3
commit 9bd51ce508
2 changed files with 23 additions and 10 deletions

View file

@ -41,8 +41,16 @@ create_mem_or_close_bo(struct nvkmd_nouveau_dev *dev,
goto fail_bo;
}
/* It should be the caller's responsibility to ensure proper alignment and
* this function should be kept pretty simple. However, because dma_buf
* imports call this with 0 alignment, we need a minimum alignment for the
* memory object initialization. For other cases, we just pass in the given
* alignment along the chain. There's no need to re-align here because the
* VA allocation at the end aligns the data to va_align_B.
*/
va_align_B = MAX2(dev->base.pdev->bind_align_B, va_align_B);
nvkmd_mem_init(&dev->base, &mem->base, &nvkmd_nouveau_mem_ops,
mem_flags, size_B, dev->base.pdev->bind_align_B);
mem_flags, size_B, va_align_B);
mem->bo = bo;
result = nvkmd_dev_alloc_va(&dev->base, log_obj,
@ -123,11 +131,13 @@ nvkmd_nouveau_alloc_tiled_mem(struct nvkmd_dev *_dev,
if (force_mem_to_gart(dev->base.pdev, flags))
domains = NOUVEAU_WS_BO_GART;
const uint32_t mem_align_B = _dev->pdev->bind_align_B;
size_B = align64(size_B, mem_align_B);
/* Since not all callers care about the alignment and pass in zero to signal
* that, we enforce a minimum alignment equal to the system page size here,
* which is guaranteed to work.
*/
assert(util_is_power_of_two_or_zero64(align_B));
const uint64_t va_align_B = MAX2(mem_align_B, align_B);
align_B = MAX2(align_B, dev->base.pdev->bind_align_B);
size_B = align64(size_B, align_B);
enum nouveau_ws_bo_flags nouveau_flags = domains;
if (flags & NVKMD_MEM_CAN_MAP)
@ -152,7 +162,7 @@ nvkmd_nouveau_alloc_tiled_mem(struct nvkmd_dev *_dev,
}
struct nouveau_ws_bo *bo = nouveau_ws_bo_new_tiled(dev->ws_dev,
size_B, mem_align_B,
size_B, align_B,
pte_kind, tile_mode,
nouveau_flags);
if (bo == NULL)
@ -163,7 +173,7 @@ nvkmd_nouveau_alloc_tiled_mem(struct nvkmd_dev *_dev,
va_flags |= NVKMD_VA_GART;
return create_mem_or_close_bo(dev, log_obj, flags, bo,
va_flags, va_align_B, mem_out);
va_flags, align_B, mem_out);
}
VkResult

View file

@ -125,11 +125,14 @@ nvkmd_nouveau_alloc_va(struct nvkmd_dev *_dev,
if (va == NULL)
return vk_error(log_obj, VK_ERROR_OUT_OF_HOST_MEMORY);
/* Not all callers care about alignment and call this function with zero
* for align_B, so enforce a minimum alignment of 4K here, and then align
* the given range to the given alignment (or the minimum if none is given).
*/
const uint32_t min_align_B = _dev->pdev->bind_align_B;
size_B = align64(size_B, min_align_B);
assert(util_is_power_of_two_or_zero64(align_B));
align_B = MAX2(align_B, min_align_B);
size_B = align64(size_B, align_B);
assert((fixed_addr == 0) == !(flags & NVKMD_VA_ALLOC_FIXED));