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