From 434462a93ebe462cbd334cbf3431ff9c5b5a1aae Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 11 Jul 2025 13:50:41 +0100 Subject: [PATCH] [riscv] Ensure coherent DMA allocations do not cross cacheline boundaries Signed-off-by: Michael Brown --- src/arch/riscv/core/riscv_dma.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/arch/riscv/core/riscv_dma.c b/src/arch/riscv/core/riscv_dma.c index 0a0107bd1..7b48b1bdd 100644 --- a/src/arch/riscv/core/riscv_dma.c +++ b/src/arch/riscv/core/riscv_dma.c @@ -34,6 +34,13 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * */ +/** Minimum alignment for coherent DMA allocations + * + * We set this sufficiently high to ensure that we do not end up with + * both cached and uncached uses in the same cacheline. + */ +#define RISCV_DMA_ALIGN 256 + /** * Map buffer for DMA * @@ -111,6 +118,11 @@ static void * riscv_dma_alloc ( struct dma_device *dma, void *addr; void *caddr; + /* Round up length and alignment */ + len = ( ( len + RISCV_DMA_ALIGN - 1 ) & ~( RISCV_DMA_ALIGN - 1 ) ); + if ( align < RISCV_DMA_ALIGN ) + align = RISCV_DMA_ALIGN; + /* Allocate from heap */ addr = malloc_phys ( len, align ); if ( ! addr ) @@ -153,6 +165,9 @@ static void riscv_dma_free ( struct dma_mapping *map, /* Sanity check */ assert ( virt_to_phys ( addr ) == virt_to_phys ( map->token ) ); + /* Round up length to match allocation */ + len = ( ( len + RISCV_DMA_ALIGN - 1 ) & ~( RISCV_DMA_ALIGN - 1 ) ); + /* Free original allocation */ free_phys ( map->token, len ); -- 2.39.5