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
init_pool(paddr_t b,paddr_size_t sz,uint32_t flags)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
350ccf6468SSahil Malhotra if (!tee_mm_init(pool, b, sz, CORE_MMU_USER_CODE_SHIFT, flags))
360ccf6468SSahil Malhotra panic();
370ccf6468SSahil Malhotra
38c596d835SJens Wiklander return pool;
39c596d835SJens Wiklander }
40c596d835SJens Wiklander
nex_phys_mem_init(paddr_t core_base,paddr_size_t core_size,paddr_t ta_base,paddr_size_t ta_size)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
nex_phys_mem_get_ta_size(void)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
nex_phys_mem_get_ta_base(void)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
is_in_pool_range(tee_mm_pool_t * pool,paddr_t addr)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
mm_find(tee_mm_pool_t * p0,tee_mm_pool_t * p1,paddr_t addr)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
nex_phys_mem_mm_find(paddr_t addr)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
mm_alloc(tee_mm_pool_t * p0,tee_mm_pool_t * p1,size_t size,uint32_t flags)88c596d835SJens Wiklander static tee_mm_entry_t *mm_alloc(tee_mm_pool_t *p0, tee_mm_pool_t *p1,
89*1baf19deSJens Wiklander size_t size, uint32_t flags)
90c596d835SJens Wiklander {
91c596d835SJens Wiklander tee_mm_entry_t *mm = NULL;
92c596d835SJens Wiklander
93c596d835SJens Wiklander if (p0)
94*1baf19deSJens Wiklander mm = tee_mm_alloc_flags(p0, size, flags);
95c596d835SJens Wiklander if (!mm && p1)
96*1baf19deSJens Wiklander mm = tee_mm_alloc_flags(p1, size, flags);
97c596d835SJens Wiklander
98c596d835SJens Wiklander return mm;
99c596d835SJens Wiklander }
100c596d835SJens Wiklander
nex_phys_mem_core_alloc(size_t size)101c596d835SJens Wiklander tee_mm_entry_t *nex_phys_mem_core_alloc(size_t size)
102c596d835SJens Wiklander {
103*1baf19deSJens Wiklander return mm_alloc(nex_core_pool, NULL, size, MAF_NULL);
104c596d835SJens Wiklander }
105c596d835SJens Wiklander
nex_phys_mem_ta_alloc(size_t size)106c596d835SJens Wiklander tee_mm_entry_t *nex_phys_mem_ta_alloc(size_t size)
107c596d835SJens Wiklander {
108*1baf19deSJens Wiklander return mm_alloc(nex_ta_pool, nex_core_pool, size, MAF_NULL);
109c596d835SJens Wiklander }
110c596d835SJens Wiklander
mm_alloc2(tee_mm_pool_t * p0,tee_mm_pool_t * p1,paddr_t base,size_t size)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
nex_phys_mem_alloc2(paddr_t base,size_t size)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
partial_carve_out(tee_mm_pool_t * pool,paddr_t base,size_t size)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
nex_phys_mem_partial_carve_out(paddr_t base,size_t size)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
add_pool_stats(tee_mm_pool_t * pool,struct pta_stats_alloc * stats,bool reset)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
nex_phys_mem_stats(struct pta_stats_alloc * stats,bool reset)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
phys_mem_init(paddr_t core_base,paddr_size_t core_size,paddr_t ta_base,paddr_size_t ta_size)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
phys_mem_mm_find(paddr_t addr)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
phys_mem_core_alloc(size_t size)195c596d835SJens Wiklander tee_mm_entry_t *phys_mem_core_alloc(size_t size)
196c596d835SJens Wiklander {
197177b77f7SJens Wiklander /*
198177b77f7SJens Wiklander * With CFG_NS_VIRTUALIZATION all memory is equally secure so we
199177b77f7SJens Wiklander * should normally be able to use one pool only, but if we have two
200177b77f7SJens Wiklander * make sure to use both even for core allocations.
201177b77f7SJens Wiklander */
202*1baf19deSJens Wiklander return mm_alloc(core_pool, ta_pool, size, MAF_NULL);
203c596d835SJens Wiklander }
204c596d835SJens Wiklander
phys_mem_ta_alloc(size_t size)205c596d835SJens Wiklander tee_mm_entry_t *phys_mem_ta_alloc(size_t size)
206c596d835SJens Wiklander {
207*1baf19deSJens Wiklander return mm_alloc(ta_pool, core_pool, size, MAF_NULL);
208c596d835SJens Wiklander }
209c596d835SJens Wiklander
phys_mem_alloc2(paddr_t base,size_t size)210c596d835SJens Wiklander tee_mm_entry_t *phys_mem_alloc2(paddr_t base, size_t size)
211c596d835SJens Wiklander {
212c596d835SJens Wiklander return mm_alloc2(core_pool, ta_pool, base, size);
213c596d835SJens Wiklander }
214c596d835SJens Wiklander
215c596d835SJens Wiklander #ifdef CFG_WITH_STATS
phys_mem_stats(struct pta_stats_alloc * stats,bool reset)216c596d835SJens Wiklander void phys_mem_stats(struct pta_stats_alloc *stats, bool reset)
217c596d835SJens Wiklander {
218c596d835SJens Wiklander memset(stats, 0, sizeof(*stats));
219c596d835SJens Wiklander
220c596d835SJens Wiklander add_pool_stats(core_pool, stats, reset);
221c596d835SJens Wiklander add_pool_stats(ta_pool, stats, reset);
222c596d835SJens Wiklander }
223c596d835SJens Wiklander #endif /*CFG_WITH_STATS*/
224c596d835SJens Wiklander #endif /*CFG_NS_VIRTUALIZATION*/
225*1baf19deSJens Wiklander
phys_mem_alloc_flags(size_t size,uint32_t flags)226*1baf19deSJens Wiklander tee_mm_entry_t *phys_mem_alloc_flags(size_t size, uint32_t flags)
227*1baf19deSJens Wiklander {
228*1baf19deSJens Wiklander tee_mm_pool_t *core = nex_core_pool;
229*1baf19deSJens Wiklander tee_mm_pool_t *ta = nex_ta_pool;
230*1baf19deSJens Wiklander
231*1baf19deSJens Wiklander #if defined(CFG_NS_VIRTUALIZATION)
232*1baf19deSJens Wiklander if (!(flags & MAF_NEX)) {
233*1baf19deSJens Wiklander core = core_pool;
234*1baf19deSJens Wiklander ta = ta_pool;
235*1baf19deSJens Wiklander }
236*1baf19deSJens Wiklander #endif
237*1baf19deSJens Wiklander
238*1baf19deSJens Wiklander if (flags & MAF_CORE_MEM)
239*1baf19deSJens Wiklander return mm_alloc(core, NULL, size, flags);
240*1baf19deSJens Wiklander else
241*1baf19deSJens Wiklander return mm_alloc(ta, core, size, flags);
242*1baf19deSJens Wiklander }
243