Skip to content

Commit 8107d6a

Browse files
keyonjielgirdwood
authored andcommitted
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 <yang.jie@linux.intel.com>
1 parent 6ce3237 commit 8107d6a

File tree

1 file changed

+20
-11
lines changed

1 file changed

+20
-11
lines changed

src/lib/alloc.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,7 @@ static void free_block(void *ptr)
453453
struct block_hdr *hdr;
454454
void *cached_ptr = uncache_to_cache(ptr);
455455
void *uncached_ptr = cache_to_uncache(ptr);
456+
void *free_ptr;
456457
int i;
457458
int block;
458459
int used_blocks;
@@ -465,21 +466,21 @@ static void free_block(void *ptr)
465466
if (!heap) {
466467
heap = get_heap_from_ptr(uncached_ptr);
467468
if (!heap) {
468-
tr_err(&mem_tr, "free_block(): invalid heap = %p, cpu = %d",
469+
tr_err(&mem_tr, "free_block(): invalid heap, ptr = %p, cpu = %d",
469470
ptr, cpu_get_id());
470471
return;
471472
}
472-
ptr = uncached_ptr;
473+
free_ptr = uncached_ptr;
473474
} else {
474-
ptr = cached_ptr;
475+
free_ptr = cached_ptr;
475476
}
476477

477478
/* find block that ptr belongs to */
478479
for (i = 0; i < heap->blocks; i++) {
479480
block_map = &heap->map[i];
480481

481482
/* is ptr in this block */
482-
if ((uint32_t)ptr < (block_map->base +
483+
if ((uint32_t)free_ptr < (block_map->base +
483484
(block_map->block_size * block_map->count)))
484485
break;
485486

@@ -488,13 +489,13 @@ static void free_block(void *ptr)
488489
if (i == heap->blocks) {
489490

490491
/* not found */
491-
tr_err(&mem_tr, "free_block(): invalid ptr = %p cpu = %d",
492-
ptr, cpu_get_id());
492+
tr_err(&mem_tr, "free_block(): invalid free_ptr = %p cpu = %d",
493+
free_ptr, cpu_get_id());
493494
return;
494495
}
495496

496497
/* calculate block header */
497-
block = ((uint32_t)ptr - block_map->base) / block_map->block_size;
498+
block = ((uint32_t)free_ptr - block_map->base) / block_map->block_size;
498499

499500
hdr = &block_map->block[block];
500501

@@ -503,17 +504,25 @@ static void free_block(void *ptr)
503504
* be from different block since we got user pointer here
504505
* or null if header was not set)
505506
*/
506-
if (hdr->unaligned_ptr != ptr && hdr->unaligned_ptr) {
507-
ptr = hdr->unaligned_ptr;
508-
block = ((uint32_t)ptr - block_map->base)
507+
if (hdr->unaligned_ptr != free_ptr && hdr->unaligned_ptr) {
508+
free_ptr = hdr->unaligned_ptr;
509+
block = ((uint32_t)free_ptr - block_map->base)
509510
/ block_map->block_size;
510511
hdr = &block_map->block[block];
511512
}
512513

513514
/* report an error if ptr is not aligned to block */
514-
if (block_map->base + block_map->block_size * block != (uint32_t)ptr)
515+
if (block_map->base + block_map->block_size * block != (uint32_t)free_ptr)
515516
panic(SOF_IPC_PANIC_MEM);
516517

518+
/* There may still be live dirty cache lines in the region
519+
* on the current core. Those must be invalidated, otherwise
520+
* they will be evicted from the cache at some point in the
521+
* future, on top of the memory region now being used for
522+
* different purposes on another core.
523+
*/
524+
dcache_writeback_invalidate_region(ptr, block_map->block_size * hdr->size);
525+
517526
heap_is_full = !block_map->free_count;
518527

519528
/* free block header and continuous blocks */

0 commit comments

Comments
 (0)