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