1c596d835SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 2c596d835SJens Wiklander /* 3c596d835SJens Wiklander * Copyright (c) 2024, Linaro Limited 4c596d835SJens Wiklander */ 5c596d835SJens Wiklander 6c596d835SJens Wiklander #include <kernel/panic.h> 7c596d835SJens Wiklander #include <kernel/tee_misc.h> 8c596d835SJens Wiklander #include <mm/core_mmu.h> 9c596d835SJens Wiklander #include <mm/phys_mem.h> 10c596d835SJens Wiklander #include <mm/tee_mm.h> 11c596d835SJens Wiklander #include <string.h> 12c596d835SJens Wiklander #include <types_ext.h> 13c596d835SJens Wiklander 14c596d835SJens Wiklander static tee_mm_pool_t *nex_core_pool __nex_bss; 15c596d835SJens Wiklander static tee_mm_pool_t *nex_ta_pool __nex_bss; 16c596d835SJens Wiklander 17c596d835SJens Wiklander static tee_mm_pool_t *init_pool(paddr_t b, paddr_size_t sz, uint32_t flags) 18c596d835SJens Wiklander { 19c596d835SJens Wiklander tee_mm_pool_t *pool = NULL; 20c596d835SJens Wiklander 21c596d835SJens Wiklander if (!b && !sz) 22c596d835SJens Wiklander return NULL; 23c596d835SJens Wiklander 24c596d835SJens Wiklander if (!b || (b & CORE_MMU_USER_CODE_MASK) || 25c596d835SJens Wiklander !sz || (sz & CORE_MMU_USER_CODE_MASK)) 26c596d835SJens Wiklander panic("invalid phys mem"); 27c596d835SJens Wiklander 28c596d835SJens Wiklander if (flags & TEE_MM_POOL_NEX_MALLOC) 29c596d835SJens Wiklander pool = nex_malloc(sizeof(*pool)); 30c596d835SJens Wiklander else 31c596d835SJens Wiklander pool = malloc(sizeof(*pool)); 32c596d835SJens Wiklander if (!pool) 33c596d835SJens Wiklander panic(); 34c596d835SJens Wiklander 35*0ccf6468SSahil Malhotra if (!tee_mm_init(pool, b, sz, CORE_MMU_USER_CODE_SHIFT, flags)) 36*0ccf6468SSahil Malhotra panic(); 37*0ccf6468SSahil Malhotra 38c596d835SJens Wiklander return pool; 39c596d835SJens Wiklander } 40c596d835SJens Wiklander 41c596d835SJens Wiklander void nex_phys_mem_init(paddr_t core_base, paddr_size_t core_size, 42c596d835SJens Wiklander paddr_t ta_base, paddr_size_t ta_size) 43c596d835SJens Wiklander { 44c596d835SJens Wiklander uint32_t flags = TEE_MM_POOL_NEX_MALLOC; 45c596d835SJens Wiklander 46de19cacbSJens Wiklander assert(!nex_core_pool && !nex_ta_pool); 47de19cacbSJens Wiklander 48c596d835SJens Wiklander nex_core_pool = init_pool(core_base, core_size, flags); 49c596d835SJens Wiklander nex_ta_pool = init_pool(ta_base, ta_size, flags); 50c596d835SJens Wiklander } 51c596d835SJens Wiklander 52c596d835SJens Wiklander paddr_size_t nex_phys_mem_get_ta_size(void) 53c596d835SJens Wiklander { 54c596d835SJens Wiklander if (nex_ta_pool) 55c596d835SJens Wiklander return nex_ta_pool->size; 56c596d835SJens Wiklander assert(nex_core_pool); 57c596d835SJens Wiklander return nex_core_pool->size - TEE_RAM_VA_SIZE; 58c596d835SJens Wiklander } 59c596d835SJens Wiklander 60c596d835SJens Wiklander paddr_t nex_phys_mem_get_ta_base(void) 61c596d835SJens Wiklander { 62c596d835SJens Wiklander if (nex_ta_pool) 63c596d835SJens Wiklander return nex_ta_pool->lo; 64c596d835SJens Wiklander assert(nex_core_pool); 65c596d835SJens Wiklander return nex_core_pool->lo; 66c596d835SJens Wiklander } 67c596d835SJens Wiklander 68c596d835SJens Wiklander static bool is_in_pool_range(tee_mm_pool_t *pool, paddr_t addr) 69c596d835SJens Wiklander { 70c596d835SJens Wiklander return pool && core_is_buffer_inside(addr, 1, pool->lo, pool->size); 71c596d835SJens Wiklander } 72c596d835SJens Wiklander 73c596d835SJens Wiklander static tee_mm_entry_t *mm_find(tee_mm_pool_t *p0, tee_mm_pool_t *p1, 74c596d835SJens Wiklander paddr_t addr) 75c596d835SJens Wiklander { 76c596d835SJens Wiklander if (is_in_pool_range(p0, addr)) 77c596d835SJens Wiklander return tee_mm_find(p0, addr); 78c596d835SJens Wiklander if (is_in_pool_range(p1, addr)) 79c596d835SJens Wiklander return tee_mm_find(p1, addr); 80c596d835SJens Wiklander return NULL; 81c596d835SJens Wiklander } 82c596d835SJens Wiklander 83c596d835SJens Wiklander tee_mm_entry_t *nex_phys_mem_mm_find(paddr_t addr) 84c596d835SJens Wiklander { 85c596d835SJens Wiklander return mm_find(nex_core_pool, nex_ta_pool, addr); 86c596d835SJens Wiklander } 87c596d835SJens Wiklander 88c596d835SJens Wiklander static tee_mm_entry_t *mm_alloc(tee_mm_pool_t *p0, tee_mm_pool_t *p1, 89c596d835SJens Wiklander size_t size) 90c596d835SJens Wiklander { 91c596d835SJens Wiklander tee_mm_entry_t *mm = NULL; 92c596d835SJens Wiklander 93c596d835SJens Wiklander if (p0) 94c596d835SJens Wiklander mm = tee_mm_alloc(p0, size); 95c596d835SJens Wiklander if (!mm && p1) 96c596d835SJens Wiklander mm = tee_mm_alloc(p1, size); 97c596d835SJens Wiklander 98c596d835SJens Wiklander return mm; 99c596d835SJens Wiklander } 100c596d835SJens Wiklander 101c596d835SJens Wiklander tee_mm_entry_t *nex_phys_mem_core_alloc(size_t size) 102c596d835SJens Wiklander { 103c596d835SJens Wiklander return mm_alloc(nex_core_pool, NULL, size); 104c596d835SJens Wiklander } 105c596d835SJens Wiklander 106c596d835SJens Wiklander tee_mm_entry_t *nex_phys_mem_ta_alloc(size_t size) 107c596d835SJens Wiklander { 108c596d835SJens Wiklander return mm_alloc(nex_ta_pool, nex_core_pool, size); 109c596d835SJens Wiklander } 110c596d835SJens Wiklander 111c596d835SJens Wiklander static tee_mm_entry_t *mm_alloc2(tee_mm_pool_t *p0, tee_mm_pool_t *p1, 112c596d835SJens Wiklander paddr_t base, size_t size) 113c596d835SJens Wiklander { 114c596d835SJens Wiklander if (is_in_pool_range(p0, base)) 115c596d835SJens Wiklander return tee_mm_alloc2(p0, base, size); 116c596d835SJens Wiklander if (is_in_pool_range(p1, base)) 117c596d835SJens Wiklander return tee_mm_alloc2(p1, base, size); 118c596d835SJens Wiklander return NULL; 119c596d835SJens Wiklander } 120c596d835SJens Wiklander 121c596d835SJens Wiklander tee_mm_entry_t *nex_phys_mem_alloc2(paddr_t base, size_t size) 122c596d835SJens Wiklander { 123c596d835SJens Wiklander return mm_alloc2(nex_core_pool, nex_ta_pool, base, size); 124c596d835SJens Wiklander } 125c596d835SJens Wiklander 126c596d835SJens Wiklander static void partial_carve_out(tee_mm_pool_t *pool, paddr_t base, size_t size) 127c596d835SJens Wiklander { 128c596d835SJens Wiklander if (pool && 129c596d835SJens Wiklander core_is_buffer_intersect(base, size, pool->lo, pool->size)) { 130c596d835SJens Wiklander tee_mm_entry_t *mm __maybe_unused = NULL; 131c596d835SJens Wiklander paddr_t end_pa = 0; 132c596d835SJens Wiklander paddr_t pa = 0; 133c596d835SJens Wiklander size_t sz = 0; 134c596d835SJens Wiklander 135c596d835SJens Wiklander pa = MAX(base, pool->lo); 136c596d835SJens Wiklander end_pa = MIN(base + size - 1, pool->lo + pool->size - 1); 137c596d835SJens Wiklander sz = end_pa - pa + 1; 138c596d835SJens Wiklander 139c596d835SJens Wiklander mm = tee_mm_alloc2(pool, pa, sz); 140c596d835SJens Wiklander assert(mm); 141c596d835SJens Wiklander } 142c596d835SJens Wiklander } 143c596d835SJens Wiklander 144c596d835SJens Wiklander void nex_phys_mem_partial_carve_out(paddr_t base, size_t size) 145c596d835SJens Wiklander { 146c596d835SJens Wiklander partial_carve_out(nex_core_pool, base, size); 147c596d835SJens Wiklander partial_carve_out(nex_ta_pool, base, size); 148c596d835SJens Wiklander } 149c596d835SJens Wiklander 150c596d835SJens Wiklander #ifdef CFG_WITH_STATS 151c596d835SJens Wiklander static void add_pool_stats(tee_mm_pool_t *pool, struct pta_stats_alloc *stats, 152c596d835SJens Wiklander bool reset) 153c596d835SJens Wiklander { 154c596d835SJens Wiklander if (pool) { 155c596d835SJens Wiklander struct pta_stats_alloc s = { }; 156c596d835SJens Wiklander 157c596d835SJens Wiklander tee_mm_get_pool_stats(pool, &s, reset); 158c596d835SJens Wiklander stats->size += s.size; 159c596d835SJens Wiklander if (s.max_allocated > stats->max_allocated) 160c596d835SJens Wiklander stats->max_allocated = s.max_allocated; 161c596d835SJens Wiklander stats->allocated += s.allocated; 162c596d835SJens Wiklander } 163c596d835SJens Wiklander } 164c596d835SJens Wiklander 165c596d835SJens Wiklander void nex_phys_mem_stats(struct pta_stats_alloc *stats, bool reset) 166c596d835SJens Wiklander { 167c596d835SJens Wiklander memset(stats, 0, sizeof(*stats)); 168c596d835SJens Wiklander 169c596d835SJens Wiklander add_pool_stats(nex_core_pool, stats, reset); 170c596d835SJens Wiklander add_pool_stats(nex_ta_pool, stats, reset); 171c596d835SJens Wiklander } 172c596d835SJens Wiklander #endif /*CFG_WITH_STATS*/ 173c596d835SJens Wiklander 174c596d835SJens Wiklander #if defined(CFG_NS_VIRTUALIZATION) 175c596d835SJens Wiklander 176c596d835SJens Wiklander static tee_mm_pool_t *core_pool; 177c596d835SJens Wiklander static tee_mm_pool_t *ta_pool; 178c596d835SJens Wiklander 179c596d835SJens Wiklander void phys_mem_init(paddr_t core_base, paddr_size_t core_size, 180c596d835SJens Wiklander paddr_t ta_base, paddr_size_t ta_size) 181c596d835SJens Wiklander { 182c596d835SJens Wiklander uint32_t flags = TEE_MM_POOL_NO_FLAGS; 183c596d835SJens Wiklander 184de19cacbSJens Wiklander assert(!core_pool && !ta_pool); 185de19cacbSJens Wiklander 186c596d835SJens Wiklander core_pool = init_pool(core_base, core_size, flags); 187c596d835SJens Wiklander ta_pool = init_pool(ta_base, ta_size, flags); 188c596d835SJens Wiklander } 189c596d835SJens Wiklander 190c596d835SJens Wiklander tee_mm_entry_t *phys_mem_mm_find(paddr_t addr) 191c596d835SJens Wiklander { 192c596d835SJens Wiklander return mm_find(core_pool, ta_pool, addr); 193c596d835SJens Wiklander } 194c596d835SJens Wiklander 195c596d835SJens Wiklander tee_mm_entry_t *phys_mem_core_alloc(size_t size) 196c596d835SJens Wiklander { 197c596d835SJens Wiklander return mm_alloc(core_pool, NULL, size); 198c596d835SJens Wiklander } 199c596d835SJens Wiklander 200c596d835SJens Wiklander tee_mm_entry_t *phys_mem_ta_alloc(size_t size) 201c596d835SJens Wiklander { 202c596d835SJens Wiklander return mm_alloc(ta_pool, core_pool, size); 203c596d835SJens Wiklander } 204c596d835SJens Wiklander 205c596d835SJens Wiklander tee_mm_entry_t *phys_mem_alloc2(paddr_t base, size_t size) 206c596d835SJens Wiklander { 207c596d835SJens Wiklander return mm_alloc2(core_pool, ta_pool, base, size); 208c596d835SJens Wiklander } 209c596d835SJens Wiklander 210c596d835SJens Wiklander #ifdef CFG_WITH_STATS 211c596d835SJens Wiklander void phys_mem_stats(struct pta_stats_alloc *stats, bool reset) 212c596d835SJens Wiklander { 213c596d835SJens Wiklander memset(stats, 0, sizeof(*stats)); 214c596d835SJens Wiklander 215c596d835SJens Wiklander add_pool_stats(core_pool, stats, reset); 216c596d835SJens Wiklander add_pool_stats(ta_pool, stats, reset); 217c596d835SJens Wiklander } 218c596d835SJens Wiklander #endif /*CFG_WITH_STATS*/ 219c596d835SJens Wiklander #endif /*CFG_NS_VIRTUALIZATION*/ 220