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