From bd0ff1e19f97494825ce02931deaf584f3798788 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Sat, 9 Oct 2021 10:35:16 +0800 Subject: [PATCH] alloc: free_block: perform wb/inv for the blocks When freeing blocks, we need to perform writeback and invalidate to the dirty cache lines, otherwise, they will be evicted from the cache at some point in the future, which will break the usage of the same memory region from another DSP core. Introduce a free_ptr to make sure the original 'ptr' is not changed, so we can use it for this wb/inv operation. Signed-off-by: Keyon Jie --- src/lib/alloc.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/lib/alloc.c b/src/lib/alloc.c index 15ed8dc352c6..782e2e170ad6 100644 --- a/src/lib/alloc.c +++ b/src/lib/alloc.c @@ -453,6 +453,7 @@ static void free_block(void *ptr) struct block_hdr *hdr; void *cached_ptr = uncache_to_cache(ptr); void *uncached_ptr = cache_to_uncache(ptr); + void *free_ptr; int i; int block; int used_blocks; @@ -465,13 +466,13 @@ static void free_block(void *ptr) if (!heap) { heap = get_heap_from_ptr(uncached_ptr); if (!heap) { - tr_err(&mem_tr, "free_block(): invalid heap = %p, cpu = %d", + tr_err(&mem_tr, "free_block(): invalid heap, ptr = %p, cpu = %d", ptr, cpu_get_id()); return; } - ptr = uncached_ptr; + free_ptr = uncached_ptr; } else { - ptr = cached_ptr; + free_ptr = cached_ptr; } /* find block that ptr belongs to */ @@ -479,7 +480,7 @@ static void free_block(void *ptr) block_map = &heap->map[i]; /* is ptr in this block */ - if ((uint32_t)ptr < (block_map->base + + if ((uint32_t)free_ptr < (block_map->base + (block_map->block_size * block_map->count))) break; @@ -488,13 +489,13 @@ static void free_block(void *ptr) if (i == heap->blocks) { /* not found */ - tr_err(&mem_tr, "free_block(): invalid ptr = %p cpu = %d", - ptr, cpu_get_id()); + tr_err(&mem_tr, "free_block(): invalid free_ptr = %p cpu = %d", + free_ptr, cpu_get_id()); return; } /* calculate block header */ - block = ((uint32_t)ptr - block_map->base) / block_map->block_size; + block = ((uint32_t)free_ptr - block_map->base) / block_map->block_size; hdr = &block_map->block[block]; @@ -503,17 +504,25 @@ static void free_block(void *ptr) * be from different block since we got user pointer here * or null if header was not set) */ - if (hdr->unaligned_ptr != ptr && hdr->unaligned_ptr) { - ptr = hdr->unaligned_ptr; - block = ((uint32_t)ptr - block_map->base) + if (hdr->unaligned_ptr != free_ptr && hdr->unaligned_ptr) { + free_ptr = hdr->unaligned_ptr; + block = ((uint32_t)free_ptr - block_map->base) / block_map->block_size; hdr = &block_map->block[block]; } /* report an error if ptr is not aligned to block */ - if (block_map->base + block_map->block_size * block != (uint32_t)ptr) + if (block_map->base + block_map->block_size * block != (uint32_t)free_ptr) panic(SOF_IPC_PANIC_MEM); + /* There may still be live dirty cache lines in the region + * on the current core. Those must be invalidated, otherwise + * they will be evicted from the cache at some point in the + * future, on top of the memory region now being used for + * different purposes on another core. + */ + dcache_writeback_invalidate_region(ptr, block_map->block_size * hdr->size); + heap_is_full = !block_map->free_count; /* free block header and continuous blocks */