xref: /optee_os/core/mm/boot_mem.c (revision bd8bea6f45b004aa153fa8d7922dec6a655f50e3)
1fe85eae5SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2fe85eae5SJens Wiklander /*
3*bd8bea6fSJens Wiklander  * Copyright (c) 2024-2025, Linaro Limited
4fe85eae5SJens Wiklander  */
5fe85eae5SJens Wiklander 
6fe85eae5SJens Wiklander #include <assert.h>
7*bd8bea6fSJens Wiklander #include <kernel/asan.h>
8fe85eae5SJens Wiklander #include <kernel/boot.h>
9fe85eae5SJens Wiklander #include <mm/core_memprot.h>
10fe85eae5SJens Wiklander #include <mm/core_mmu.h>
11fe85eae5SJens Wiklander #include <mm/phys_mem.h>
12fe85eae5SJens Wiklander #include <mm/tee_mm.h>
13fe85eae5SJens Wiklander #include <stdalign.h>
14fe85eae5SJens Wiklander #include <string.h>
15fe85eae5SJens Wiklander #include <util.h>
16fe85eae5SJens Wiklander 
17fe85eae5SJens Wiklander /*
18fe85eae5SJens Wiklander  * struct boot_mem_reloc - Pointers relocated in memory during boot
19fe85eae5SJens Wiklander  * @ptrs: Array of relocation
20fe85eae5SJens Wiklander  * @count: Number of cells used in @ptrs
21fe85eae5SJens Wiklander  * @next: Next relocation array when @ptrs is fully used
22fe85eae5SJens Wiklander  */
23fe85eae5SJens Wiklander struct boot_mem_reloc {
24fe85eae5SJens Wiklander 	void **ptrs[64];
25fe85eae5SJens Wiklander 	size_t count;
26fe85eae5SJens Wiklander 	struct boot_mem_reloc *next;
27fe85eae5SJens Wiklander };
28fe85eae5SJens Wiklander 
29fe85eae5SJens Wiklander /*
30c62a7972SJens Wiklander  * struct boot_mem_padding - unused memory between allocations
31c62a7972SJens Wiklander  * @start: Start of padding
32c62a7972SJens Wiklander  * @len: Length of padding
33c62a7972SJens Wiklander  * @next: Next padding
34c62a7972SJens Wiklander  */
35c62a7972SJens Wiklander struct boot_mem_padding {
36c62a7972SJens Wiklander 	vaddr_t start;
37c62a7972SJens Wiklander 	size_t len;
38c62a7972SJens Wiklander 	struct boot_mem_padding *next;
39c62a7972SJens Wiklander };
40c62a7972SJens Wiklander 
41c62a7972SJens Wiklander /*
42fe85eae5SJens Wiklander  * struct boot_mem_desc - Stack like boot memory allocation pool
43fe85eae5SJens Wiklander  * @orig_mem_start: Boot memory stack base address
44fe85eae5SJens Wiklander  * @orig_mem_end: Boot memory start end address
45fe85eae5SJens Wiklander  * @mem_start: Boot memory free space start address
46fe85eae5SJens Wiklander  * @mem_end: Boot memory free space end address
47fe85eae5SJens Wiklander  * @reloc: Boot memory pointers requiring relocation
48c62a7972SJens Wiklander  * @padding: Linked list of unused memory between allocated blocks
49fe85eae5SJens Wiklander  */
50fe85eae5SJens Wiklander struct boot_mem_desc {
51fe85eae5SJens Wiklander 	vaddr_t orig_mem_start;
52fe85eae5SJens Wiklander 	vaddr_t orig_mem_end;
53fe85eae5SJens Wiklander 	vaddr_t mem_start;
54fe85eae5SJens Wiklander 	vaddr_t mem_end;
55fe85eae5SJens Wiklander 	struct boot_mem_reloc *reloc;
56c62a7972SJens Wiklander 	struct boot_mem_padding *padding;
57fe85eae5SJens Wiklander };
58fe85eae5SJens Wiklander 
59fe85eae5SJens Wiklander static struct boot_mem_desc *boot_mem_desc;
60fe85eae5SJens Wiklander 
mem_alloc_tmp(struct boot_mem_desc * desc,size_t len,size_t align)61fe85eae5SJens Wiklander static void *mem_alloc_tmp(struct boot_mem_desc *desc, size_t len, size_t align)
62fe85eae5SJens Wiklander {
63fe85eae5SJens Wiklander 	vaddr_t va = 0;
64fe85eae5SJens Wiklander 
65*bd8bea6fSJens Wiklander 	if (IS_ENABLED(CFG_CORE_SANITIZE_KADDRESS))
66*bd8bea6fSJens Wiklander 		align = MAX(align, ASAN_BLOCK_SIZE);
67*bd8bea6fSJens Wiklander 
68fe85eae5SJens Wiklander 	assert(desc && desc->mem_start && desc->mem_end);
69fe85eae5SJens Wiklander 	assert(IS_POWER_OF_TWO(align) && !(len % align));
70fe85eae5SJens Wiklander 	if (SUB_OVERFLOW(desc->mem_end, len, &va))
71fe85eae5SJens Wiklander 		panic();
7276d6685eSEtienne Carriere 	va = ROUNDDOWN2(va, align);
73fe85eae5SJens Wiklander 	if (va < desc->mem_start)
74fe85eae5SJens Wiklander 		panic();
75fe85eae5SJens Wiklander 	desc->mem_end = va;
76*bd8bea6fSJens Wiklander 
77*bd8bea6fSJens Wiklander 	asan_tag_access((void *)va, (void *)(va + len));
78*bd8bea6fSJens Wiklander 
79fe85eae5SJens Wiklander 	return (void *)va;
80fe85eae5SJens Wiklander }
81fe85eae5SJens Wiklander 
add_padding(struct boot_mem_desc * desc,vaddr_t va)82c62a7972SJens Wiklander static void add_padding(struct boot_mem_desc *desc, vaddr_t va)
83c62a7972SJens Wiklander {
84c62a7972SJens Wiklander 	struct boot_mem_padding *pad = NULL;
85*bd8bea6fSJens Wiklander 	vaddr_t start = desc->mem_start;
86*bd8bea6fSJens Wiklander 	vaddr_t rounded = 0;
87c62a7972SJens Wiklander 
88*bd8bea6fSJens Wiklander 	if (IS_ENABLED(CFG_CORE_SANITIZE_KADDRESS))
89*bd8bea6fSJens Wiklander 		start = ROUNDUP(start, ASAN_BLOCK_SIZE);
90*bd8bea6fSJens Wiklander 
91*bd8bea6fSJens Wiklander 	rounded = ROUNDUP(start, alignof(*pad));
92c62a7972SJens Wiklander 	if (rounded < va && va - rounded > sizeof(*pad)) {
93c62a7972SJens Wiklander 		pad = (struct boot_mem_padding *)rounded;
94*bd8bea6fSJens Wiklander 		pad->start = start;
95*bd8bea6fSJens Wiklander 		pad->len = va - start;
96c62a7972SJens Wiklander 		DMSG("%#"PRIxVA" len %#zx", pad->start, pad->len);
97c62a7972SJens Wiklander 		pad->next = desc->padding;
98c62a7972SJens Wiklander 		desc->padding = pad;
99c62a7972SJens Wiklander 	}
100c62a7972SJens Wiklander }
101c62a7972SJens Wiklander 
mem_alloc(struct boot_mem_desc * desc,size_t len,size_t align)102fe85eae5SJens Wiklander static void *mem_alloc(struct boot_mem_desc *desc, size_t len, size_t align)
103fe85eae5SJens Wiklander {
104fe85eae5SJens Wiklander 	vaddr_t va = 0;
105fe85eae5SJens Wiklander 	vaddr_t ve = 0;
106fe85eae5SJens Wiklander 
107*bd8bea6fSJens Wiklander 	if (IS_ENABLED(CFG_CORE_SANITIZE_KADDRESS))
108*bd8bea6fSJens Wiklander 		align = MAX(align, ASAN_BLOCK_SIZE);
109*bd8bea6fSJens Wiklander 
110fe85eae5SJens Wiklander 	runtime_assert(!IS_ENABLED(CFG_WITH_PAGER));
111fe85eae5SJens Wiklander 	assert(desc && desc->mem_start && desc->mem_end);
112fe85eae5SJens Wiklander 	assert(IS_POWER_OF_TWO(align) && !(len % align));
11376d6685eSEtienne Carriere 	va = ROUNDUP2(desc->mem_start, align);
114fe85eae5SJens Wiklander 	if (ADD_OVERFLOW(va, len, &ve))
115fe85eae5SJens Wiklander 		panic();
116fe85eae5SJens Wiklander 	if (ve > desc->mem_end)
117fe85eae5SJens Wiklander 		panic();
118c62a7972SJens Wiklander 	add_padding(desc, va);
119fe85eae5SJens Wiklander 	desc->mem_start = ve;
120*bd8bea6fSJens Wiklander 
121*bd8bea6fSJens Wiklander 	asan_tag_access((void *)va, (void *)(va + len));
122*bd8bea6fSJens Wiklander 
123fe85eae5SJens Wiklander 	return (void *)va;
124fe85eae5SJens Wiklander }
125fe85eae5SJens Wiklander 
boot_mem_init(vaddr_t start,vaddr_t end,vaddr_t orig_end)126fe85eae5SJens Wiklander void boot_mem_init(vaddr_t start, vaddr_t end, vaddr_t orig_end)
127fe85eae5SJens Wiklander {
128fe85eae5SJens Wiklander 	struct boot_mem_desc desc = {
129fe85eae5SJens Wiklander 		.orig_mem_start = start,
130fe85eae5SJens Wiklander 		.orig_mem_end = orig_end,
131fe85eae5SJens Wiklander 		.mem_start = start,
132fe85eae5SJens Wiklander 		.mem_end = end,
133fe85eae5SJens Wiklander 	};
134fe85eae5SJens Wiklander 
135fe85eae5SJens Wiklander 	boot_mem_desc = mem_alloc_tmp(&desc, sizeof(desc), alignof(desc));
136fe85eae5SJens Wiklander 	*boot_mem_desc = desc;
137fe85eae5SJens Wiklander 	boot_mem_desc->reloc = mem_alloc_tmp(boot_mem_desc,
138fe85eae5SJens Wiklander 					     sizeof(*boot_mem_desc->reloc),
139fe85eae5SJens Wiklander 					     alignof(*boot_mem_desc->reloc));
140fe85eae5SJens Wiklander 	memset(boot_mem_desc->reloc, 0, sizeof(*boot_mem_desc->reloc));
141fe85eae5SJens Wiklander }
142fe85eae5SJens Wiklander 
tag_padding_no_access(vaddr_t va __unused,size_t len __unused,void * ptr __unused)143*bd8bea6fSJens Wiklander static bool tag_padding_no_access(vaddr_t va __unused, size_t len __unused,
144*bd8bea6fSJens Wiklander 				  void *ptr __unused)
145*bd8bea6fSJens Wiklander {
146*bd8bea6fSJens Wiklander 	/*
147*bd8bea6fSJens Wiklander 	 * No need to do anything since boot_mem_foreach_padding() calls
148*bd8bea6fSJens Wiklander 	 * asan_tag_access() before this function is called and calls
149*bd8bea6fSJens Wiklander 	 * asan_tag_no_access() after this function has returned false.
150*bd8bea6fSJens Wiklander 	 */
151*bd8bea6fSJens Wiklander 	return false;
152*bd8bea6fSJens Wiklander }
153*bd8bea6fSJens Wiklander 
boot_mem_init_asan(void)154*bd8bea6fSJens Wiklander void boot_mem_init_asan(void)
155*bd8bea6fSJens Wiklander {
156*bd8bea6fSJens Wiklander 	asan_tag_access((void *)ROUNDDOWN(boot_mem_desc->orig_mem_start,
157*bd8bea6fSJens Wiklander 					  ASAN_BLOCK_SIZE),
158*bd8bea6fSJens Wiklander 			(void *)boot_mem_desc->mem_start);
159*bd8bea6fSJens Wiklander 	asan_tag_access((void *)ROUNDDOWN(boot_mem_desc->mem_end,
160*bd8bea6fSJens Wiklander 					  ASAN_BLOCK_SIZE),
161*bd8bea6fSJens Wiklander 			(void *)boot_mem_desc->orig_mem_end);
162*bd8bea6fSJens Wiklander 	boot_mem_foreach_padding(tag_padding_no_access, NULL);
163*bd8bea6fSJens Wiklander }
164*bd8bea6fSJens Wiklander 
boot_mem_add_reloc(void * ptr)165fe85eae5SJens Wiklander void boot_mem_add_reloc(void *ptr)
166fe85eae5SJens Wiklander {
167fe85eae5SJens Wiklander 	struct boot_mem_reloc *reloc = NULL;
168fe85eae5SJens Wiklander 
169fe85eae5SJens Wiklander 	assert(boot_mem_desc && boot_mem_desc->reloc);
170fe85eae5SJens Wiklander 	reloc = boot_mem_desc->reloc;
171fe85eae5SJens Wiklander 
172fe85eae5SJens Wiklander 	/* If the reloc struct is full, allocate a new and link it first */
173fe85eae5SJens Wiklander 	if (reloc->count == ARRAY_SIZE(reloc->ptrs)) {
174fe85eae5SJens Wiklander 		reloc = boot_mem_alloc_tmp(sizeof(*reloc), alignof(*reloc));
175fe85eae5SJens Wiklander 		reloc->next = boot_mem_desc->reloc;
176fe85eae5SJens Wiklander 		boot_mem_desc->reloc = reloc;
177fe85eae5SJens Wiklander 	}
178fe85eae5SJens Wiklander 
179fe85eae5SJens Wiklander 	reloc->ptrs[reloc->count] = ptr;
180fe85eae5SJens Wiklander 	reloc->count++;
181fe85eae5SJens Wiklander }
182fe85eae5SJens Wiklander 
add_offs(void * p,size_t offs)183fe85eae5SJens Wiklander static void *add_offs(void *p, size_t offs)
184fe85eae5SJens Wiklander {
185fe85eae5SJens Wiklander 	assert(p);
186fe85eae5SJens Wiklander 	return (uint8_t *)p + offs;
187fe85eae5SJens Wiklander }
188fe85eae5SJens Wiklander 
add_offs_or_null(void * p,size_t offs)1896b61de6cSJens Wiklander static void *add_offs_or_null(void *p, size_t offs)
1906b61de6cSJens Wiklander {
1916b61de6cSJens Wiklander 	if (!p)
1926b61de6cSJens Wiklander 		return NULL;
1936b61de6cSJens Wiklander 	return (uint8_t *)p + offs;
1946b61de6cSJens Wiklander }
1956b61de6cSJens Wiklander 
boot_mem_relocate(size_t offs)196fe85eae5SJens Wiklander void boot_mem_relocate(size_t offs)
197fe85eae5SJens Wiklander {
198fe85eae5SJens Wiklander 	struct boot_mem_reloc *reloc = NULL;
199c62a7972SJens Wiklander 	struct boot_mem_padding *pad = NULL;
200fe85eae5SJens Wiklander 	size_t n = 0;
201fe85eae5SJens Wiklander 
202fe85eae5SJens Wiklander 	boot_mem_desc = add_offs(boot_mem_desc, offs);
203fe85eae5SJens Wiklander 
204fe85eae5SJens Wiklander 	boot_mem_desc->orig_mem_start += offs;
205fe85eae5SJens Wiklander 	boot_mem_desc->orig_mem_end += offs;
206fe85eae5SJens Wiklander 	boot_mem_desc->mem_start += offs;
207fe85eae5SJens Wiklander 	boot_mem_desc->mem_end += offs;
208fe85eae5SJens Wiklander 	boot_mem_desc->reloc = add_offs(boot_mem_desc->reloc, offs);
209fe85eae5SJens Wiklander 
210fe85eae5SJens Wiklander 	for (reloc = boot_mem_desc->reloc;; reloc = reloc->next) {
211fe85eae5SJens Wiklander 		for (n = 0; n < reloc->count; n++) {
212fe85eae5SJens Wiklander 			reloc->ptrs[n] = add_offs(reloc->ptrs[n], offs);
2136b61de6cSJens Wiklander 			*reloc->ptrs[n] = add_offs_or_null(*reloc->ptrs[n],
2146b61de6cSJens Wiklander 							   offs);
215fe85eae5SJens Wiklander 		}
216fe85eae5SJens Wiklander 		if (!reloc->next)
217fe85eae5SJens Wiklander 			break;
218fe85eae5SJens Wiklander 		reloc->next = add_offs(reloc->next, offs);
219fe85eae5SJens Wiklander 	}
220c62a7972SJens Wiklander 
221c62a7972SJens Wiklander 	if (boot_mem_desc->padding) {
222c62a7972SJens Wiklander 		boot_mem_desc->padding = add_offs(boot_mem_desc->padding, offs);
223c62a7972SJens Wiklander 		pad = boot_mem_desc->padding;
224c62a7972SJens Wiklander 		while (true) {
225c62a7972SJens Wiklander 			pad->start += offs;
226c62a7972SJens Wiklander 			if (!pad->next)
227c62a7972SJens Wiklander 				break;
228c62a7972SJens Wiklander 			pad->next = add_offs(pad->next, offs);
229c62a7972SJens Wiklander 			pad = pad->next;
230c62a7972SJens Wiklander 		}
231c62a7972SJens Wiklander 	}
232fe85eae5SJens Wiklander }
233fe85eae5SJens Wiklander 
boot_mem_alloc(size_t len,size_t align)234fe85eae5SJens Wiklander void *boot_mem_alloc(size_t len, size_t align)
235fe85eae5SJens Wiklander {
236fe85eae5SJens Wiklander 	return mem_alloc(boot_mem_desc, len, align);
237fe85eae5SJens Wiklander }
238fe85eae5SJens Wiklander 
boot_mem_alloc_tmp(size_t len,size_t align)239fe85eae5SJens Wiklander void *boot_mem_alloc_tmp(size_t len, size_t align)
240fe85eae5SJens Wiklander {
241fe85eae5SJens Wiklander 	return mem_alloc_tmp(boot_mem_desc, len, align);
242fe85eae5SJens Wiklander }
243fe85eae5SJens Wiklander 
244c62a7972SJens Wiklander /*
245c62a7972SJens Wiklander  * Calls the supplied @func() for each padding and removes the paddings
246c62a7972SJens Wiklander  * where @func() returns true.
247c62a7972SJens Wiklander  */
boot_mem_foreach_padding(bool (* func)(vaddr_t va,size_t len,void * ptr),void * ptr)248c62a7972SJens Wiklander void boot_mem_foreach_padding(bool (*func)(vaddr_t va, size_t len, void *ptr),
249c62a7972SJens Wiklander 			      void *ptr)
250c62a7972SJens Wiklander {
251c62a7972SJens Wiklander 	struct boot_mem_padding **prev = NULL;
252c62a7972SJens Wiklander 	struct boot_mem_padding *next = NULL;
253c62a7972SJens Wiklander 	struct boot_mem_padding *pad = NULL;
254c62a7972SJens Wiklander 
255c62a7972SJens Wiklander 	assert(boot_mem_desc);
256c62a7972SJens Wiklander 
257c62a7972SJens Wiklander 	prev = &boot_mem_desc->padding;
258c62a7972SJens Wiklander 	for (pad = boot_mem_desc->padding; pad; pad = next) {
259*bd8bea6fSJens Wiklander 		vaddr_t start = 0;
260*bd8bea6fSJens Wiklander 		size_t len = 0;
261c62a7972SJens Wiklander 
262*bd8bea6fSJens Wiklander 		asan_tag_access(pad, (uint8_t *)pad + sizeof(*pad));
263*bd8bea6fSJens Wiklander 		start = pad->start;
264*bd8bea6fSJens Wiklander 		len = pad->len;
265*bd8bea6fSJens Wiklander 		asan_tag_access((void *)start, (void *)(start + len));
266c62a7972SJens Wiklander 		next = pad->next;
267c62a7972SJens Wiklander 		if (func(start, len, ptr)) {
268c62a7972SJens Wiklander 			DMSG("consumed %p %#"PRIxVA" len %#zx",
269c62a7972SJens Wiklander 			     pad, start, len);
270c62a7972SJens Wiklander 			*prev = next;
271c62a7972SJens Wiklander 		} else {
272c62a7972SJens Wiklander 			DMSG("keeping %p %#"PRIxVA" len %#zx",
273c62a7972SJens Wiklander 			     pad, start, len);
274c62a7972SJens Wiklander 			prev = &pad->next;
275*bd8bea6fSJens Wiklander 			asan_tag_no_access((void *)start,
276*bd8bea6fSJens Wiklander 					   (void *)(start + len));
277c62a7972SJens Wiklander 		}
278c62a7972SJens Wiklander 	}
279c62a7972SJens Wiklander }
280c62a7972SJens Wiklander 
boot_mem_release_unused(void)281fe85eae5SJens Wiklander vaddr_t boot_mem_release_unused(void)
282fe85eae5SJens Wiklander {
283fe85eae5SJens Wiklander 	tee_mm_entry_t *mm = NULL;
284fe85eae5SJens Wiklander 	paddr_t pa = 0;
285fe85eae5SJens Wiklander 	vaddr_t va = 0;
286fe85eae5SJens Wiklander 	size_t n = 0;
287fe85eae5SJens Wiklander 	vaddr_t tmp_va = 0;
288fe85eae5SJens Wiklander 	paddr_t tmp_pa = 0;
289fe85eae5SJens Wiklander 	size_t tmp_n = 0;
290fe85eae5SJens Wiklander 
291fe85eae5SJens Wiklander 	assert(boot_mem_desc);
292fe85eae5SJens Wiklander 
293fe85eae5SJens Wiklander 	n = boot_mem_desc->mem_start - boot_mem_desc->orig_mem_start;
294fe85eae5SJens Wiklander 	DMSG("Allocated %zu bytes at va %#"PRIxVA" pa %#"PRIxPA,
295fe85eae5SJens Wiklander 	     n, boot_mem_desc->orig_mem_start,
296fe85eae5SJens Wiklander 	     vaddr_to_phys(boot_mem_desc->orig_mem_start));
297fe85eae5SJens Wiklander 
298fe85eae5SJens Wiklander 	DMSG("Tempalloc %zu bytes at va %#"PRIxVA,
299fe85eae5SJens Wiklander 	     (size_t)(boot_mem_desc->orig_mem_end - boot_mem_desc->mem_end),
300fe85eae5SJens Wiklander 	     boot_mem_desc->mem_end);
301fe85eae5SJens Wiklander 
302fe85eae5SJens Wiklander 	if (IS_ENABLED(CFG_WITH_PAGER))
303fe85eae5SJens Wiklander 		goto out;
304fe85eae5SJens Wiklander 
305fe85eae5SJens Wiklander 	pa = vaddr_to_phys(ROUNDUP(boot_mem_desc->orig_mem_start,
306fe85eae5SJens Wiklander 				   SMALL_PAGE_SIZE));
307fe85eae5SJens Wiklander 	mm = nex_phys_mem_mm_find(pa);
308fe85eae5SJens Wiklander 	if (!mm)
309fe85eae5SJens Wiklander 		panic();
310fe85eae5SJens Wiklander 
311fe85eae5SJens Wiklander 	va = ROUNDUP(boot_mem_desc->mem_start, SMALL_PAGE_SIZE);
312fe85eae5SJens Wiklander 
313fe85eae5SJens Wiklander 	tmp_va = ROUNDDOWN(boot_mem_desc->mem_end, SMALL_PAGE_SIZE);
314fe85eae5SJens Wiklander 	tmp_n = boot_mem_desc->orig_mem_end - tmp_va;
315fe85eae5SJens Wiklander 	tmp_pa = vaddr_to_phys(tmp_va);
316fe85eae5SJens Wiklander 
317fe85eae5SJens Wiklander 	pa = tee_mm_get_smem(mm);
318fe85eae5SJens Wiklander 	n = vaddr_to_phys(boot_mem_desc->mem_start) - pa;
319fe85eae5SJens Wiklander 	tee_mm_free(mm);
320fe85eae5SJens Wiklander 	DMSG("Carving out %#"PRIxPA"..%#"PRIxPA, pa, pa + n - 1);
321fe85eae5SJens Wiklander 	mm = nex_phys_mem_alloc2(pa, n);
322fe85eae5SJens Wiklander 	if (!mm)
323fe85eae5SJens Wiklander 		panic();
324fe85eae5SJens Wiklander 	mm = nex_phys_mem_alloc2(tmp_pa, tmp_n);
325fe85eae5SJens Wiklander 	if (!mm)
326fe85eae5SJens Wiklander 		panic();
327fe85eae5SJens Wiklander 
328fe85eae5SJens Wiklander 	n = tmp_va - boot_mem_desc->mem_start;
329fe85eae5SJens Wiklander 	DMSG("Releasing %zu bytes from va %#"PRIxVA, n, va);
330fe85eae5SJens Wiklander 
331fe85eae5SJens Wiklander 	/* Unmap the now unused pages */
332fe85eae5SJens Wiklander 	core_mmu_unmap_pages(va, n / SMALL_PAGE_SIZE);
333fe85eae5SJens Wiklander 
334fe85eae5SJens Wiklander out:
335fe85eae5SJens Wiklander 	/* Stop further allocations. */
336fe85eae5SJens Wiklander 	boot_mem_desc->mem_start = boot_mem_desc->mem_end;
337fe85eae5SJens Wiklander 	return va;
338fe85eae5SJens Wiklander }
339fe85eae5SJens Wiklander 
boot_mem_release_tmp_alloc(void)340fe85eae5SJens Wiklander void boot_mem_release_tmp_alloc(void)
341fe85eae5SJens Wiklander {
342fe85eae5SJens Wiklander 	tee_mm_entry_t *mm = NULL;
343fe85eae5SJens Wiklander 	vaddr_t va = 0;
344fe85eae5SJens Wiklander 	paddr_t pa = 0;
345fe85eae5SJens Wiklander 	size_t n = 0;
346fe85eae5SJens Wiklander 
347fe85eae5SJens Wiklander 	assert(boot_mem_desc &&
348fe85eae5SJens Wiklander 	       boot_mem_desc->mem_start == boot_mem_desc->mem_end);
349fe85eae5SJens Wiklander 
350fe85eae5SJens Wiklander 	if (IS_ENABLED(CFG_WITH_PAGER)) {
351fe85eae5SJens Wiklander 		n = boot_mem_desc->orig_mem_end - boot_mem_desc->mem_end;
352fe85eae5SJens Wiklander 		va = boot_mem_desc->mem_end;
353fe85eae5SJens Wiklander 		boot_mem_desc = NULL;
354fe85eae5SJens Wiklander 		DMSG("Releasing %zu bytes from va %#"PRIxVA, n, va);
355fe85eae5SJens Wiklander 		return;
356fe85eae5SJens Wiklander 	}
357fe85eae5SJens Wiklander 
358fe85eae5SJens Wiklander 	va = ROUNDDOWN(boot_mem_desc->mem_end, SMALL_PAGE_SIZE);
359fe85eae5SJens Wiklander 	pa = vaddr_to_phys(va);
360fe85eae5SJens Wiklander 
361fe85eae5SJens Wiklander 	mm = nex_phys_mem_mm_find(pa);
362fe85eae5SJens Wiklander 	if (!mm)
363fe85eae5SJens Wiklander 		panic();
364fe85eae5SJens Wiklander 	assert(pa == tee_mm_get_smem(mm));
365fe85eae5SJens Wiklander 	n = tee_mm_get_bytes(mm);
366fe85eae5SJens Wiklander 
367fe85eae5SJens Wiklander 	/* Boot memory allocation is now done */
368fe85eae5SJens Wiklander 	boot_mem_desc = NULL;
369fe85eae5SJens Wiklander 
370fe85eae5SJens Wiklander 	DMSG("Releasing %zu bytes from va %#"PRIxVA, n, va);
371fe85eae5SJens Wiklander 
372fe85eae5SJens Wiklander 	/* Unmap the now unused pages */
373fe85eae5SJens Wiklander 	core_mmu_unmap_pages(va, n / SMALL_PAGE_SIZE);
374fe85eae5SJens Wiklander }
375