From 30c7da73585eb1ae494c5fe257d2dba8741b5161 Mon Sep 17 00:00:00 2001 From: Tomasz Lauda Date: Thu, 23 Aug 2018 12:36:53 +0200 Subject: [PATCH] alloc: access to the memory map through uncached addresses Changes access to the platform memory map to go through uncached address range. This will make alloc functions truly shared between cores and also save us many invalidate operations. Memory map needs to be statically defined, so cannot be allocated itself in ucached zone. Signed-off-by: Tomasz Lauda --- src/include/sof/alloc.h | 8 ++++ src/lib/alloc.c | 101 +++++++++++++++++++--------------------- 2 files changed, 57 insertions(+), 52 deletions(-) diff --git a/src/include/sof/alloc.h b/src/include/sof/alloc.h index 623450c56558..1df84d0a7067 100644 --- a/src/include/sof/alloc.h +++ b/src/include/sof/alloc.h @@ -131,4 +131,12 @@ int mm_pm_context_restore(struct dma_copy *dc, struct dma_sg_config *sg); /* heap initialisation */ void init_heap(struct sof *sof); + +/* flush block map from cache to sram */ +static inline void flush_block_map(struct block_map *map) +{ + dcache_writeback_invalidate_region(map->block, + sizeof(*map->block) * map->count); + dcache_writeback_invalidate_region(map, sizeof(*map)); +} #endif diff --git a/src/lib/alloc.c b/src/lib/alloc.c index b5edeff75b3a..82c0b3f93aa2 100644 --- a/src/lib/alloc.c +++ b/src/lib/alloc.c @@ -85,7 +85,7 @@ static inline uint32_t heap_get_size(struct mm_heap *heap) int i; for (i = 0; i < heap->blocks; i++) { - size += block_get_size(&heap->map[i]); + size += block_get_size(cache_to_uncache(&heap->map[i])); } return size; @@ -141,8 +141,8 @@ static void *rmalloc_sys(int zone, size_t bytes) static void *alloc_block(struct mm_heap *heap, int level, uint32_t caps) { - struct block_map *map = &heap->map[level]; - struct block_hdr *hdr = &map->block[map->first_free]; + struct block_map *map = cache_to_uncache(&heap->map[level]); + struct block_hdr *hdr = cache_to_uncache(&map->block[map->first_free]); void *ptr; int i; @@ -152,12 +152,11 @@ static void *alloc_block(struct mm_heap *heap, int level, hdr->used = 1; heap->info.used += map->block_size; heap->info.free -= map->block_size; - dcache_writeback_invalidate_region(hdr, sizeof(*hdr)); /* find next free */ for (i = map->first_free; i < map->count; ++i) { - hdr = &map->block[i]; + hdr = cache_to_uncache(&map->block[i]); if (hdr->used == 0) { map->first_free = i; @@ -169,9 +168,6 @@ static void *alloc_block(struct mm_heap *heap, int level, alloc_memset_region(ptr, map->block_size, DEBUG_BLOCK_ALLOC_VALUE); #endif - dcache_writeback_invalidate_region(map, sizeof(*map)); - dcache_writeback_invalidate_region(heap, sizeof(*heap)); - return ptr; } @@ -179,8 +175,8 @@ static void *alloc_block(struct mm_heap *heap, int level, static void *alloc_cont_blocks(struct mm_heap *heap, int level, uint32_t caps, size_t bytes) { - struct block_map *map = &heap->map[level]; - struct block_hdr *hdr = &map->block[map->first_free]; + struct block_map *map = cache_to_uncache(&heap->map[level]); + struct block_hdr *hdr; void *ptr; unsigned int start; unsigned int current; @@ -198,7 +194,7 @@ static void *alloc_cont_blocks(struct mm_heap *heap, int level, /* check that we have enough free blocks from start pos */ end = start + count; for (current = start; current < end; current++) { - hdr = &map->block[current]; + hdr = cache_to_uncache(&map->block[current]); /* is block used */ if (hdr->used) @@ -218,17 +214,15 @@ static void *alloc_cont_blocks(struct mm_heap *heap, int level, /* found some free blocks */ map->free_count -= count; ptr = (void *)(map->base + start * map->block_size); - hdr = &map->block[start]; + hdr = cache_to_uncache(&map->block[start]); hdr->size = count; heap->info.used += count * map->block_size; heap->info.free -= count * map->block_size; - dcache_writeback_invalidate_region(hdr, sizeof(*hdr)); /* allocate each block */ for (current = start; current < end; current++) { - hdr = &map->block[current]; + hdr = cache_to_uncache(&map->block[current]); hdr->used = 1; - dcache_writeback_invalidate_region(hdr, sizeof(*hdr)); } /* do we need to find a new first free block ? */ @@ -237,7 +231,7 @@ static void *alloc_cont_blocks(struct mm_heap *heap, int level, /* find next free */ for (i = map->first_free + count; i < map->count; ++i) { - hdr = &map->block[i]; + hdr = cache_to_uncache(&map->block[i]); if (hdr->used == 0) { map->first_free = i; @@ -250,9 +244,6 @@ static void *alloc_cont_blocks(struct mm_heap *heap, int level, alloc_memset_region(ptr, bytes, DEBUG_BLOCK_ALLOC_VALUE); #endif - dcache_writeback_invalidate_region(map, sizeof(*map)); - dcache_writeback_invalidate_region(heap, sizeof(*heap)); - return ptr; } @@ -263,7 +254,7 @@ static struct mm_heap *get_heap_from_ptr(void *ptr) /* find mm_heap that ptr belongs to */ for (i = 0; i < PLATFORM_HEAP_RUNTIME; i++) { - heap = &memmap.runtime[i]; + heap = cache_to_uncache(&memmap.runtime[i]); if ((uint32_t)ptr >= heap->heap && (uint32_t)ptr < heap->heap + heap->size) @@ -271,7 +262,7 @@ static struct mm_heap *get_heap_from_ptr(void *ptr) } for (i = 0; i < PLATFORM_HEAP_BUFFER; i++) { - heap = &memmap.buffer[i]; + heap = cache_to_uncache(&memmap.buffer[i]); if ((uint32_t)ptr >= heap->heap && (uint32_t)ptr < heap->heap + heap->size) @@ -289,7 +280,7 @@ static struct mm_heap *get_runtime_heap_from_caps(uint32_t caps) /* find first heap that support type */ for (i = 0; i < PLATFORM_HEAP_RUNTIME; i++) { - heap = &memmap.runtime[i]; + heap = cache_to_uncache(&memmap.runtime[i]); mask = heap->caps & caps; if (mask == caps) return heap; @@ -306,7 +297,7 @@ static struct mm_heap *get_buffer_heap_from_caps(uint32_t caps) /* find first heap that support type */ for (i = 0; i < PLATFORM_HEAP_BUFFER; i++) { - heap = &memmap.buffer[i]; + heap = cache_to_uncache(&memmap.buffer[i]); mask = heap->caps & caps; if (mask == caps) return heap; @@ -334,9 +325,10 @@ static void free_block(void *ptr) /* find block that ptr belongs to */ for (i = 0; i < heap->blocks - 1; i++) { + block_map = cache_to_uncache(&heap->map[i + 1]); /* is ptr in this block */ - if ((uint32_t)ptr < heap->map[i + 1].base) + if ((uint32_t)ptr < block_map->base) goto found; } @@ -346,21 +338,20 @@ static void free_block(void *ptr) found: /* the block i is it */ - block_map = &heap->map[i]; + block_map = cache_to_uncache(&heap->map[i]); /* calculate block header */ block = ((uint32_t)ptr - block_map->base) / block_map->block_size; - hdr = &block_map->block[block]; + hdr = cache_to_uncache(&block_map->block[block]); /* free block header and continuous blocks */ for (i = block; i < block + hdr->size; i++) { - hdr = &block_map->block[i]; + hdr = cache_to_uncache(&block_map->block[i]); hdr->size = 0; hdr->used = 0; block_map->free_count++; heap->info.used -= block_map->block_size; heap->info.free += block_map->block_size; - dcache_writeback_invalidate_region(hdr, sizeof(*hdr)); } /* set first free block */ @@ -370,15 +361,13 @@ static void free_block(void *ptr) #if DEBUG_BLOCK_FREE alloc_memset_region(ptr, block_map->block_size * (i - 1), DEBUG_BLOCK_FREE_VALUE); #endif - - dcache_writeback_invalidate_region(block_map, sizeof(*block_map)); - dcache_writeback_invalidate_region(heap, sizeof(*heap)); } /* allocate single block for runtime */ static void *rmalloc_runtime(int zone, uint32_t caps, size_t bytes) { struct mm_heap *heap; + struct block_map *map; int i; void *ptr = NULL; @@ -394,13 +383,14 @@ static void *rmalloc_runtime(int zone, uint32_t caps, size_t bytes) find: for (i = 0; i < heap->blocks; i++) { + map = cache_to_uncache(&heap->map[i]); /* is block big enough */ - if (heap->map[i].block_size < bytes) + if (map->block_size < bytes) continue; /* does block have free space */ - if (heap->map[i].free_count == 0) + if (map->free_count == 0) continue; /* free block space exists */ @@ -460,6 +450,7 @@ void *rzalloc(int zone, uint32_t caps, size_t bytes) void *rballoc(int zone, uint32_t caps, size_t bytes) { struct mm_heap *heap; + struct block_map *map; int i; uint32_t flags; void *ptr = NULL; @@ -472,13 +463,14 @@ void *rballoc(int zone, uint32_t caps, size_t bytes) /* will request fit in single block */ for (i = 0; i < heap->blocks; i++) { + map = cache_to_uncache(&heap->map[i]); /* is block big enough */ - if (heap->map[i].block_size < bytes) + if (map->block_size < bytes) continue; /* does block have free space */ - if (heap->map[i].free_count == 0) + if (map->free_count == 0) continue; /* allocate block */ @@ -496,9 +488,10 @@ void *rballoc(int zone, uint32_t caps, size_t bytes) /* find best block size for request */ for (i = 0; i < heap->blocks; i++) { + map = cache_to_uncache(&heap->map[i]); /* allocate is block size smaller than request */ - if (heap->map[i].block_size < bytes) + if (map->block_size < bytes) alloc_cont_blocks(heap, i, caps, bytes); } } @@ -529,16 +522,16 @@ uint32_t mm_pm_context_size(void) /* calc context size for each area */ for (i = 0; i < PLATFORM_HEAP_BUFFER; i++) - size += memmap.buffer[i].info.used; + size += cache_to_uncache(&memmap.buffer[i])->info.used; for (i = 0; i < PLATFORM_HEAP_RUNTIME; i++) - size += memmap.runtime[i].info.used; + size += cache_to_uncache(&memmap.runtime[i])->info.used; size += memmap.system.info.used; /* add memory maps */ for (i = 0; i < PLATFORM_HEAP_BUFFER; i++) - size += heap_get_size(&memmap.buffer[i]); + size += heap_get_size(cache_to_uncache(&memmap.buffer[i])); for (i = 0; i < PLATFORM_HEAP_RUNTIME; i++) - size += heap_get_size(&memmap.runtime[i]); + size += heap_get_size(cache_to_uncache(&memmap.runtime[i])); size += heap_get_size(&memmap.system); /* recalc totals */ @@ -546,13 +539,17 @@ uint32_t mm_pm_context_size(void) memmap.total.used = memmap.system.info.used; for (i = 0; i < PLATFORM_HEAP_BUFFER; i++) { - memmap.total.free += memmap.buffer[i].info.free; - memmap.total.used += memmap.buffer[i].info.used; + memmap.total.free += + cache_to_uncache(&memmap.buffer[i])->info.free; + memmap.total.used += + cache_to_uncache(&memmap.buffer[i])->info.used; } for (i = 0; i < PLATFORM_HEAP_RUNTIME; i++) { - memmap.total.free = memmap.runtime[i].info.free; - memmap.total.used = memmap.runtime[i].info.used; + memmap.total.free = + cache_to_uncache(&memmap.runtime[i])->info.free; + memmap.total.used = + cache_to_uncache(&memmap.runtime[i])->info.used; } return size; @@ -653,8 +650,7 @@ void init_heap(struct sof *sof) current_map = &heap->map[j]; current_map->base = heap->heap; - dcache_writeback_region(current_map, - sizeof(*current_map)); + flush_block_map(current_map); for (k = 1; k < heap->blocks; k++) { next_map = &heap->map[k]; @@ -662,10 +658,11 @@ void init_heap(struct sof *sof) current_map->block_size * current_map->count; current_map = &heap->map[k]; - dcache_writeback_region(current_map, - sizeof(*current_map)); + flush_block_map(current_map); } } + + dcache_writeback_invalidate_region(heap, sizeof(*heap)); } /* initialise runtime map */ @@ -676,8 +673,7 @@ void init_heap(struct sof *sof) current_map = &heap->map[j]; current_map->base = heap->heap; - dcache_writeback_region(current_map, - sizeof(*current_map)); + flush_block_map(current_map); for (k = 1; k < heap->blocks; k++) { next_map = &heap->map[k]; @@ -685,9 +681,10 @@ void init_heap(struct sof *sof) current_map->block_size * current_map->count; current_map = &heap->map[k]; - dcache_writeback_region(current_map, - sizeof(*current_map)); + flush_block_map(current_map); } } + + dcache_writeback_invalidate_region(heap, sizeof(*heap)); } }