From 79f47249e8ccc1cd8c7cbe2fd8022173df961563 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 11 Aug 2022 01:04:31 +0300 Subject: [PATCH] llvmpipe: Align persistent mappings to page size KVM requires memory mapping to be aligned to page size, otherwise it refuses to do the mapping. In particular this causes KVM mapping errors when llvmpipe is used by virtio-gpu on host and guest tries to map buffer that has a persistent mapping, i.e. it tries to map the llvmpipe's host blob/buffer. Mesa virgl driver uses host blobs only for the buffers with persistent mapping, hence let's align buffer allocations to the page size when the persistence flag is set to fix the KVM fault. Reviewed-by: Dave Airlie Acked-by: Antonio Caggiano Signed-off-by: Dmitry Osipenko Part-of: --- src/gallium/drivers/llvmpipe/lp_texture.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index c68f175db72..615df6341b0 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -90,7 +90,16 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen, * of a block for all formats) though this should not be strictly necessary * neither. In any case it can only affect compressed or 1d textures. */ - unsigned mip_align = MAX2(64, util_get_cpu_caps()->cacheline); + uint64_t mip_align = MAX2(64, util_get_cpu_caps()->cacheline); + + /* KVM on Linux requires memory mapping to be aligned to the page size, + * otherwise Linux kernel errors out on trying to map host GPU mapping + * to guest (ARB_map_buffer_range). The improper alignment creates trouble + * for the virgl driver when host uses llvmpipe, causing Qemu and crosvm to + * bail out on the KVM error. + */ + if (lpr->base.flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT) + os_get_page_size(&mip_align); assert(LP_MAX_TEXTURE_2D_LEVELS <= LP_MAX_TEXTURE_LEVELS); assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS); @@ -280,7 +289,12 @@ llvmpipe_resource_create_all(struct pipe_screen *_screen, lpr->size_required += (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float); if (alloc_backing) { - lpr->data = align_malloc(lpr->size_required, 64); + uint64_t alignment = 64; + + if (templat->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT) + os_get_page_size(&alignment); + + lpr->data = align_malloc(lpr->size_required, alignment); if (!lpr->data) goto fail;