xref: /optee_os/core/mm/phys_mem.c (revision de19cacbc6dfb468525d2e57a04a740ff5dabb6f)
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