xref: /optee_os/core/arch/arm/mm/tee_pager.c (revision 5acb1bc6e8ece254ffe7dbdc41605ad5613b6ab7)
1 /*
2  * Copyright (c) 2016, Linaro Limited
3  * Copyright (c) 2014, STMicroelectronics International N.V.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <arm.h>
30 #include <assert.h>
31 #include <keep.h>
32 #include <sys/queue.h>
33 #include <kernel/abort.h>
34 #include <kernel/panic.h>
35 #include <kernel/spinlock.h>
36 #include <kernel/tee_misc.h>
37 #include <kernel/tee_ta_manager.h>
38 #include <kernel/thread.h>
39 #include <mm/core_memprot.h>
40 #include <mm/tee_mm.h>
41 #include <mm/tee_pager.h>
42 #include <types_ext.h>
43 #include <stdlib.h>
44 #include <tee_api_defines.h>
45 #include <tee/tee_cryp_provider.h>
46 #include <trace.h>
47 #include <utee_defines.h>
48 #include <util.h>
49 
50 #include "pager_private.h"
51 
52 #define PAGER_AE_KEY_BITS	256
53 
54 struct pager_rw_pstate {
55 	uint64_t iv;
56 	uint8_t tag[PAGER_AES_GCM_TAG_LEN];
57 };
58 
59 enum area_type {
60 	AREA_TYPE_RO,
61 	AREA_TYPE_RW,
62 	AREA_TYPE_LOCK,
63 };
64 
65 struct tee_pager_area {
66 	union {
67 		const uint8_t *hashes;
68 		struct pager_rw_pstate *rwp;
69 	} u;
70 	uint8_t *store;
71 	enum area_type type;
72 	uint32_t flags;
73 	vaddr_t base;
74 	size_t size;
75 	struct pgt *pgt;
76 	TAILQ_ENTRY(tee_pager_area) link;
77 };
78 
79 TAILQ_HEAD(tee_pager_area_head, tee_pager_area);
80 
81 static struct tee_pager_area_head tee_pager_area_head =
82 	TAILQ_HEAD_INITIALIZER(tee_pager_area_head);
83 
84 #define INVALID_PGIDX	UINT_MAX
85 
86 /*
87  * struct tee_pager_pmem - Represents a physical page used for paging.
88  *
89  * @pgidx	an index of the entry in area->ti.
90  * @va_alias	Virtual address where the physical page always is aliased.
91  *		Used during remapping of the page when the content need to
92  *		be updated before it's available at the new location.
93  * @area	a pointer to the pager area
94  */
95 struct tee_pager_pmem {
96 	unsigned pgidx;
97 	void *va_alias;
98 	struct tee_pager_area *area;
99 	TAILQ_ENTRY(tee_pager_pmem) link;
100 };
101 
102 /* The list of physical pages. The first page in the list is the oldest */
103 TAILQ_HEAD(tee_pager_pmem_head, tee_pager_pmem);
104 
105 static struct tee_pager_pmem_head tee_pager_pmem_head =
106 	TAILQ_HEAD_INITIALIZER(tee_pager_pmem_head);
107 
108 static struct tee_pager_pmem_head tee_pager_lock_pmem_head =
109 	TAILQ_HEAD_INITIALIZER(tee_pager_lock_pmem_head);
110 
111 static uint8_t pager_ae_key[PAGER_AE_KEY_BITS / 8];
112 
113 /* number of pages hidden */
114 #define TEE_PAGER_NHIDE (tee_pager_npages / 3)
115 
116 /* Number of registered physical pages, used hiding pages. */
117 static size_t tee_pager_npages;
118 
119 #ifdef CFG_WITH_STATS
120 static struct tee_pager_stats pager_stats;
121 
122 static inline void incr_ro_hits(void)
123 {
124 	pager_stats.ro_hits++;
125 }
126 
127 static inline void incr_rw_hits(void)
128 {
129 	pager_stats.rw_hits++;
130 }
131 
132 static inline void incr_hidden_hits(void)
133 {
134 	pager_stats.hidden_hits++;
135 }
136 
137 static inline void incr_zi_released(void)
138 {
139 	pager_stats.zi_released++;
140 }
141 
142 static inline void incr_npages_all(void)
143 {
144 	pager_stats.npages_all++;
145 }
146 
147 static inline void set_npages(void)
148 {
149 	pager_stats.npages = tee_pager_npages;
150 }
151 
152 void tee_pager_get_stats(struct tee_pager_stats *stats)
153 {
154 	*stats = pager_stats;
155 
156 	pager_stats.hidden_hits = 0;
157 	pager_stats.ro_hits = 0;
158 	pager_stats.rw_hits = 0;
159 	pager_stats.zi_released = 0;
160 }
161 
162 #else /* CFG_WITH_STATS */
163 static inline void incr_ro_hits(void) { }
164 static inline void incr_rw_hits(void) { }
165 static inline void incr_hidden_hits(void) { }
166 static inline void incr_zi_released(void) { }
167 static inline void incr_npages_all(void) { }
168 static inline void set_npages(void) { }
169 
170 void tee_pager_get_stats(struct tee_pager_stats *stats)
171 {
172 	memset(stats, 0, sizeof(struct tee_pager_stats));
173 }
174 #endif /* CFG_WITH_STATS */
175 
176 static struct pgt pager_core_pgt;
177 struct core_mmu_table_info tee_pager_tbl_info;
178 static struct core_mmu_table_info pager_alias_tbl_info;
179 
180 static unsigned pager_spinlock = SPINLOCK_UNLOCK;
181 
182 /* Defines the range of the alias area */
183 static tee_mm_entry_t *pager_alias_area;
184 /*
185  * Physical pages are added in a stack like fashion to the alias area,
186  * @pager_alias_next_free gives the address of next free entry if
187  * @pager_alias_next_free is != 0
188  */
189 static uintptr_t pager_alias_next_free;
190 
191 static uint32_t pager_lock(void)
192 {
193 	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
194 
195 	cpu_spin_lock(&pager_spinlock);
196 	return exceptions;
197 }
198 
199 static void pager_unlock(uint32_t exceptions)
200 {
201 	cpu_spin_unlock(&pager_spinlock);
202 	thread_set_exceptions(exceptions);
203 }
204 
205 static void set_alias_area(tee_mm_entry_t *mm)
206 {
207 	struct core_mmu_table_info *ti = &pager_alias_tbl_info;
208 	size_t tbl_va_size;
209 	unsigned idx;
210 	unsigned last_idx;
211 	vaddr_t smem = tee_mm_get_smem(mm);
212 	size_t nbytes = tee_mm_get_bytes(mm);
213 
214 	DMSG("0x%" PRIxVA " - 0x%" PRIxVA, smem, smem + nbytes);
215 
216 	if (pager_alias_area)
217 		panic("null pager_alias_area");
218 
219 	if (!ti->num_entries && !core_mmu_find_table(smem, UINT_MAX, ti))
220 		panic("Can't find translation table");
221 
222 	if ((1 << ti->shift) != SMALL_PAGE_SIZE)
223 		panic("Unsupported page size in translation table");
224 
225 	tbl_va_size = (1 << ti->shift) * ti->num_entries;
226 	if (!core_is_buffer_inside(smem, nbytes,
227 				   ti->va_base, tbl_va_size)) {
228 		EMSG("area 0x%" PRIxVA " len 0x%zx doesn't fit it translation table 0x%" PRIxVA " len 0x%zx",
229 		     smem, nbytes, ti->va_base, tbl_va_size);
230 		panic();
231 	}
232 
233 	if (smem & SMALL_PAGE_MASK || nbytes & SMALL_PAGE_MASK)
234 		panic("invalid area alignment");
235 
236 	pager_alias_area = mm;
237 	pager_alias_next_free = smem;
238 
239 	/* Clear all mapping in the alias area */
240 	idx = core_mmu_va2idx(ti, smem);
241 	last_idx = core_mmu_va2idx(ti, smem + nbytes);
242 	for (; idx < last_idx; idx++)
243 		core_mmu_set_entry(ti, idx, 0, 0);
244 
245 	/* TODO only invalidate entries touched above */
246 	core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0);
247 }
248 
249 static void generate_ae_key(void)
250 {
251 	if (rng_generate(pager_ae_key, sizeof(pager_ae_key)) != TEE_SUCCESS)
252 		panic("failed to generate random");
253 }
254 
255 void tee_pager_init(tee_mm_entry_t *mm_alias)
256 {
257 	set_alias_area(mm_alias);
258 	generate_ae_key();
259 }
260 
261 static void *pager_add_alias_page(paddr_t pa)
262 {
263 	unsigned idx;
264 	struct core_mmu_table_info *ti = &pager_alias_tbl_info;
265 	uint32_t attr = TEE_MATTR_VALID_BLOCK | TEE_MATTR_GLOBAL |
266 			(TEE_MATTR_CACHE_CACHED << TEE_MATTR_CACHE_SHIFT) |
267 			TEE_MATTR_SECURE | TEE_MATTR_PRW;
268 
269 	DMSG("0x%" PRIxPA, pa);
270 
271 	if (!pager_alias_next_free || !ti->num_entries)
272 		panic("invalid alias entry");
273 
274 	idx = core_mmu_va2idx(ti, pager_alias_next_free);
275 	core_mmu_set_entry(ti, idx, pa, attr);
276 	pgt_inc_used_entries(&pager_core_pgt);
277 	pager_alias_next_free += SMALL_PAGE_SIZE;
278 	if (pager_alias_next_free >= (tee_mm_get_smem(pager_alias_area) +
279 				      tee_mm_get_bytes(pager_alias_area)))
280 		pager_alias_next_free = 0;
281 	return (void *)core_mmu_idx2va(ti, idx);
282 }
283 
284 static struct tee_pager_area *alloc_area(struct pgt *pgt,
285 					 vaddr_t base, size_t size,
286 					 uint32_t flags, const void *store,
287 					 const void *hashes)
288 {
289 	struct tee_pager_area *area = calloc(1, sizeof(*area));
290 	enum area_type at;
291 	tee_mm_entry_t *mm_store = NULL;
292 
293 	if (!area)
294 		return NULL;
295 
296 	if (flags & (TEE_MATTR_PW | TEE_MATTR_UW)) {
297 		if (flags & TEE_MATTR_LOCKED) {
298 			at = AREA_TYPE_LOCK;
299 			goto out;
300 		}
301 		mm_store = tee_mm_alloc(&tee_mm_sec_ddr, size);
302 		if (!mm_store)
303 			goto bad;
304 		area->store = phys_to_virt(tee_mm_get_smem(mm_store),
305 					   MEM_AREA_TA_RAM);
306 		if (!area->store)
307 			goto bad;
308 		area->u.rwp = calloc(size / SMALL_PAGE_SIZE,
309 				     sizeof(struct pager_rw_pstate));
310 		if (!area->u.rwp)
311 			goto bad;
312 		at = AREA_TYPE_RW;
313 	} else {
314 		area->store = (void *)store;
315 		area->u.hashes = hashes;
316 		at = AREA_TYPE_RO;
317 	}
318 out:
319 	area->pgt = pgt;
320 	area->base = base;
321 	area->size = size;
322 	area->flags = flags;
323 	area->type = at;
324 	return area;
325 bad:
326 	tee_mm_free(mm_store);
327 	free(area->u.rwp);
328 	free(area);
329 	return NULL;
330 }
331 
332 static void area_insert_tail(struct tee_pager_area *area)
333 {
334 	uint32_t exceptions = pager_lock();
335 
336 	TAILQ_INSERT_TAIL(&tee_pager_area_head, area, link);
337 
338 	pager_unlock(exceptions);
339 }
340 KEEP_PAGER(area_insert_tail);
341 
342 static size_t tbl_usage_count(struct pgt *pgt)
343 {
344 	size_t n;
345 	paddr_t pa;
346 	size_t usage = 0;
347 
348 	for (n = 0; n < tee_pager_tbl_info.num_entries; n++) {
349 		core_mmu_get_entry_primitive(pgt->tbl, tee_pager_tbl_info.level,
350 					     n, &pa, NULL);
351 		if (pa)
352 			usage++;
353 	}
354 	return usage;
355 }
356 
357 bool tee_pager_add_core_area(vaddr_t base, size_t size, uint32_t flags,
358 			const void *store, const void *hashes)
359 {
360 	struct tee_pager_area *area;
361 	size_t tbl_va_size;
362 	struct core_mmu_table_info *ti = &tee_pager_tbl_info;
363 
364 	DMSG("0x%" PRIxPTR " - 0x%" PRIxPTR " : flags 0x%x, store %p, hashes %p",
365 		base, base + size, flags, store, hashes);
366 
367 	if (base & SMALL_PAGE_MASK || size & SMALL_PAGE_MASK || !size) {
368 		EMSG("invalid pager area [%" PRIxVA " +0x%zx]", base, size);
369 		panic();
370 	}
371 
372 	if (!(flags & TEE_MATTR_PW) && (!store || !hashes))
373 		panic("write pages cannot provide store or hashes");
374 
375 	if ((flags & TEE_MATTR_PW) && (store || hashes))
376 		panic("non-write pages must provide store and hashes");
377 
378 	if (!pager_core_pgt.tbl) {
379 		pager_core_pgt.tbl = ti->table;
380 		pgt_set_used_entries(&pager_core_pgt,
381 				     tbl_usage_count(&pager_core_pgt));
382 	}
383 
384 	tbl_va_size = (1 << ti->shift) * ti->num_entries;
385 	if (!core_is_buffer_inside(base, size, ti->va_base, tbl_va_size)) {
386 		DMSG("area 0x%" PRIxPTR " len 0x%zx doesn't fit it translation table 0x%" PRIxVA " len 0x%zx",
387 			base, size, ti->va_base, tbl_va_size);
388 		return false;
389 	}
390 
391 	area = alloc_area(&pager_core_pgt, base, size, flags, store, hashes);
392 	if (!area)
393 		return false;
394 
395 	area_insert_tail(area);
396 	return true;
397 }
398 
399 static struct tee_pager_area *find_area(struct tee_pager_area_head *areas,
400 					vaddr_t va)
401 {
402 	struct tee_pager_area *area;
403 
404 	if (!areas)
405 		return NULL;
406 
407 	TAILQ_FOREACH(area, areas, link) {
408 		if (core_is_buffer_inside(va, 1, area->base, area->size))
409 			return area;
410 	}
411 	return NULL;
412 }
413 
414 #ifdef CFG_PAGED_USER_TA
415 static struct tee_pager_area *find_uta_area(vaddr_t va)
416 {
417 	struct tee_ta_ctx *ctx = thread_get_tsd()->ctx;
418 
419 	if (!ctx || !is_user_ta_ctx(ctx))
420 		return NULL;
421 	return find_area(to_user_ta_ctx(ctx)->areas, va);
422 }
423 #else
424 static struct tee_pager_area *find_uta_area(vaddr_t va __unused)
425 {
426 	return NULL;
427 }
428 #endif /*CFG_PAGED_USER_TA*/
429 
430 
431 static uint32_t get_area_mattr(uint32_t area_flags)
432 {
433 	uint32_t attr = TEE_MATTR_VALID_BLOCK | TEE_MATTR_SECURE |
434 			TEE_MATTR_CACHE_CACHED << TEE_MATTR_CACHE_SHIFT |
435 			(area_flags & (TEE_MATTR_PRWX | TEE_MATTR_URWX));
436 
437 	if (!(area_flags & (TEE_MATTR_UR | TEE_MATTR_UX | TEE_MATTR_UW)))
438 		attr |= TEE_MATTR_GLOBAL;
439 
440 	return attr;
441 }
442 
443 static paddr_t get_pmem_pa(struct tee_pager_pmem *pmem)
444 {
445 	paddr_t pa;
446 	unsigned idx;
447 
448 	idx = core_mmu_va2idx(&pager_alias_tbl_info, (vaddr_t)pmem->va_alias);
449 	core_mmu_get_entry(&pager_alias_tbl_info, idx, &pa, NULL);
450 	return pa;
451 }
452 
453 static bool decrypt_page(struct pager_rw_pstate *rwp, const void *src,
454 			void *dst)
455 {
456 	struct pager_aes_gcm_iv iv = {
457 		{ (vaddr_t)rwp, rwp->iv >> 32, rwp->iv }
458 	};
459 
460 	return pager_aes_gcm_decrypt(pager_ae_key, sizeof(pager_ae_key),
461 				     &iv, rwp->tag, src, dst, SMALL_PAGE_SIZE);
462 }
463 
464 static void encrypt_page(struct pager_rw_pstate *rwp, void *src, void *dst)
465 {
466 	struct pager_aes_gcm_iv iv;
467 
468 	assert((rwp->iv + 1) > rwp->iv);
469 	rwp->iv++;
470 	/*
471 	 * IV is constructed as recommended in section "8.2.1 Deterministic
472 	 * Construction" of "Recommendation for Block Cipher Modes of
473 	 * Operation: Galois/Counter Mode (GCM) and GMAC",
474 	 * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
475 	 */
476 	iv.iv[0] = (vaddr_t)rwp;
477 	iv.iv[1] = rwp->iv >> 32;
478 	iv.iv[2] = rwp->iv;
479 
480 	if (!pager_aes_gcm_encrypt(pager_ae_key, sizeof(pager_ae_key),
481 				   &iv, rwp->tag,
482 				   src, dst, SMALL_PAGE_SIZE))
483 		panic("gcm failed");
484 }
485 
486 static void tee_pager_load_page(struct tee_pager_area *area, vaddr_t page_va,
487 			void *va_alias)
488 {
489 	size_t idx = (page_va - area->base) >> SMALL_PAGE_SHIFT;
490 	const void *stored_page = area->store + idx * SMALL_PAGE_SIZE;
491 
492 	switch (area->type) {
493 	case AREA_TYPE_RO:
494 		{
495 			const void *hash = area->u.hashes +
496 					   idx * TEE_SHA256_HASH_SIZE;
497 
498 			memcpy(va_alias, stored_page, SMALL_PAGE_SIZE);
499 			incr_ro_hits();
500 
501 			if (hash_sha256_check(hash, va_alias,
502 					      SMALL_PAGE_SIZE) != TEE_SUCCESS) {
503 				EMSG("PH 0x%" PRIxVA " failed", page_va);
504 				panic();
505 			}
506 		}
507 		break;
508 	case AREA_TYPE_RW:
509 		FMSG("Restore %p %#" PRIxVA " iv %#" PRIx64,
510 			va_alias, page_va, area->u.rwp[idx].iv);
511 		if (!area->u.rwp[idx].iv)
512 			memset(va_alias, 0, SMALL_PAGE_SIZE);
513 		else if (!decrypt_page(&area->u.rwp[idx], stored_page,
514 				       va_alias)) {
515 			EMSG("PH 0x%" PRIxVA " failed", page_va);
516 			panic();
517 		}
518 		incr_rw_hits();
519 		break;
520 	case AREA_TYPE_LOCK:
521 		FMSG("Zero init %p %#" PRIxVA, va_alias, page_va);
522 		memset(va_alias, 0, SMALL_PAGE_SIZE);
523 		break;
524 	default:
525 		panic();
526 	}
527 }
528 
529 static void tee_pager_save_page(struct tee_pager_pmem *pmem, uint32_t attr)
530 {
531 	const uint32_t dirty_bits = TEE_MATTR_PW | TEE_MATTR_UW |
532 				    TEE_MATTR_HIDDEN_DIRTY_BLOCK;
533 
534 	if (pmem->area->type == AREA_TYPE_RW && (attr & dirty_bits)) {
535 		size_t offs = pmem->area->base & CORE_MMU_PGDIR_MASK;
536 		size_t idx = pmem->pgidx - (offs >> SMALL_PAGE_SHIFT);
537 		void *stored_page = pmem->area->store + idx * SMALL_PAGE_SIZE;
538 
539 		assert(pmem->area->flags & (TEE_MATTR_PW | TEE_MATTR_UW));
540 		encrypt_page(&pmem->area->u.rwp[idx], pmem->va_alias,
541 			     stored_page);
542 		FMSG("Saved %#" PRIxVA " iv %#" PRIx64,
543 			pmem->area->base + idx * SMALL_PAGE_SIZE,
544 			pmem->area->u.rwp[idx].iv);
545 	}
546 }
547 
548 static void area_get_entry(struct tee_pager_area *area, size_t idx,
549 			   paddr_t *pa, uint32_t *attr)
550 {
551 	assert(area->pgt);
552 	assert(idx < tee_pager_tbl_info.num_entries);
553 	core_mmu_get_entry_primitive(area->pgt->tbl, tee_pager_tbl_info.level,
554 				     idx, pa, attr);
555 }
556 
557 static void area_set_entry(struct tee_pager_area *area, size_t idx,
558 			   paddr_t pa, uint32_t attr)
559 {
560 	assert(area->pgt);
561 	assert(idx < tee_pager_tbl_info.num_entries);
562 	core_mmu_set_entry_primitive(area->pgt->tbl, tee_pager_tbl_info.level,
563 				     idx, pa, attr);
564 }
565 
566 static size_t area_va2idx(struct tee_pager_area *area, vaddr_t va)
567 {
568 	return (va - (area->base & ~CORE_MMU_PGDIR_MASK)) >> SMALL_PAGE_SHIFT;
569 }
570 
571 static vaddr_t __maybe_unused area_idx2va(struct tee_pager_area *area,
572 					 size_t idx)
573 {
574 	return (idx << SMALL_PAGE_SHIFT) + (area->base & ~CORE_MMU_PGDIR_MASK);
575 }
576 
577 #ifdef CFG_PAGED_USER_TA
578 static void free_area(struct tee_pager_area *area)
579 {
580 	tee_mm_free(tee_mm_find(&tee_mm_sec_ddr,
581 				virt_to_phys(area->store)));
582 	if (area->type == AREA_TYPE_RW)
583 		free(area->u.rwp);
584 	free(area);
585 }
586 
587 static bool pager_add_uta_area(struct user_ta_ctx *utc, vaddr_t base,
588 			       size_t size)
589 {
590 	struct tee_pager_area *area;
591 	uint32_t flags;
592 	vaddr_t b = base;
593 	size_t s = ROUNDUP(size, SMALL_PAGE_SIZE);
594 
595 	if (!utc->areas) {
596 		utc->areas = malloc(sizeof(*utc->areas));
597 		if (!utc->areas)
598 			return false;
599 		TAILQ_INIT(utc->areas);
600 	}
601 
602 	flags = TEE_MATTR_PRW | TEE_MATTR_URWX;
603 
604 	while (s) {
605 		size_t s2;
606 
607 		if (find_area(utc->areas, b))
608 			return false;
609 
610 		s2 = MIN(CORE_MMU_PGDIR_SIZE - (b & CORE_MMU_PGDIR_MASK), s);
611 
612 		/* Table info will be set when the context is activated. */
613 		area = alloc_area(NULL, b, s2, flags, NULL, NULL);
614 		if (!area)
615 			return false;
616 		TAILQ_INSERT_TAIL(utc->areas, area, link);
617 		b += s2;
618 		s -= s2;
619 	}
620 
621 	return true;
622 }
623 
624 bool tee_pager_add_uta_area(struct user_ta_ctx *utc, vaddr_t base, size_t size)
625 {
626 	struct thread_specific_data *tsd = thread_get_tsd();
627 	struct tee_pager_area *area;
628 	struct core_mmu_table_info dir_info = { NULL };
629 
630 	if (&utc->ctx != tsd->ctx) {
631 		/*
632 		 * Changes are to an utc that isn't active. Just add the
633 		 * areas page tables will be dealt with later.
634 		 */
635 		return pager_add_uta_area(utc, base, size);
636 	}
637 
638 	/*
639 	 * Assign page tables before adding areas to be able to tell which
640 	 * are newly added and should be removed in case of failure.
641 	 */
642 	tee_pager_assign_uta_tables(utc);
643 	if (!pager_add_uta_area(utc, base, size)) {
644 		struct tee_pager_area *next_a;
645 
646 		/* Remove all added areas */
647 		TAILQ_FOREACH_SAFE(area, utc->areas, link, next_a) {
648 			if (!area->pgt) {
649 				TAILQ_REMOVE(utc->areas, area, link);
650 				free_area(area);
651 			}
652 		}
653 		return false;
654 	}
655 
656 	/*
657 	 * Assign page tables to the new areas and make sure that the page
658 	 * tables are registered in the upper table.
659 	 */
660 	tee_pager_assign_uta_tables(utc);
661 	core_mmu_get_user_pgdir(&dir_info);
662 	TAILQ_FOREACH(area, utc->areas, link) {
663 		paddr_t pa;
664 		size_t idx;
665 		uint32_t attr;
666 
667 		idx = core_mmu_va2idx(&dir_info, area->pgt->vabase);
668 		core_mmu_get_entry(&dir_info, idx, &pa, &attr);
669 
670 		/*
671 		 * Check if the page table already is used, if it is, it's
672 		 * already registered.
673 		 */
674 		if (area->pgt->num_used_entries) {
675 			assert(attr & TEE_MATTR_TABLE);
676 			assert(pa == virt_to_phys(area->pgt->tbl));
677 			continue;
678 		}
679 
680 		attr = TEE_MATTR_SECURE | TEE_MATTR_TABLE;
681 		pa = virt_to_phys(area->pgt->tbl);
682 		assert(pa);
683 		/*
684 		 * Note that the update of the table entry is guaranteed to
685 		 * be atomic.
686 		 */
687 		core_mmu_set_entry(&dir_info, idx, pa, attr);
688 	}
689 
690 	return true;
691 }
692 
693 static void init_tbl_info_from_pgt(struct core_mmu_table_info *ti,
694 				   struct pgt *pgt)
695 {
696 	assert(pgt);
697 	ti->table = pgt->tbl;
698 	ti->va_base = pgt->vabase;
699 	ti->level = tee_pager_tbl_info.level;
700 	ti->shift = tee_pager_tbl_info.shift;
701 	ti->num_entries = tee_pager_tbl_info.num_entries;
702 }
703 
704 static void transpose_area(struct tee_pager_area *area, struct pgt *new_pgt,
705 			   vaddr_t new_base)
706 {
707 	uint32_t exceptions = pager_lock();
708 
709 	/*
710 	 * If there's no pgt assigned to the old area there's no pages to
711 	 * deal with either, just update with a new pgt and base.
712 	 */
713 	if (area->pgt) {
714 		struct core_mmu_table_info old_ti;
715 		struct core_mmu_table_info new_ti;
716 		struct tee_pager_pmem *pmem;
717 
718 		init_tbl_info_from_pgt(&old_ti, area->pgt);
719 		init_tbl_info_from_pgt(&new_ti, new_pgt);
720 
721 
722 		TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) {
723 			vaddr_t va;
724 			paddr_t pa;
725 			uint32_t attr;
726 
727 			if (pmem->area != area)
728 				continue;
729 			core_mmu_get_entry(&old_ti, pmem->pgidx, &pa, &attr);
730 			core_mmu_set_entry(&old_ti, pmem->pgidx, 0, 0);
731 
732 			assert(pa == get_pmem_pa(pmem));
733 			assert(attr);
734 			assert(area->pgt->num_used_entries);
735 			area->pgt->num_used_entries--;
736 
737 			va = core_mmu_idx2va(&old_ti, pmem->pgidx);
738 			va = va - area->base + new_base;
739 			pmem->pgidx = core_mmu_va2idx(&new_ti, va);
740 			core_mmu_set_entry(&new_ti, pmem->pgidx, pa, attr);
741 			new_pgt->num_used_entries++;
742 		}
743 	}
744 
745 	area->pgt = new_pgt;
746 	area->base = new_base;
747 	pager_unlock(exceptions);
748 }
749 KEEP_PAGER(transpose_area);
750 
751 void tee_pager_transfer_uta_region(struct user_ta_ctx *src_utc,
752 				   vaddr_t src_base,
753 				   struct user_ta_ctx *dst_utc,
754 				   vaddr_t dst_base, struct pgt **dst_pgt,
755 				   size_t size)
756 {
757 	struct tee_pager_area *area;
758 	struct tee_pager_area *next_a;
759 
760 	TAILQ_FOREACH_SAFE(area, src_utc->areas, link, next_a) {
761 		vaddr_t new_area_base;
762 		size_t new_idx;
763 
764 		if (!core_is_buffer_inside(area->base, area->size,
765 					  src_base, size))
766 			continue;
767 
768 		TAILQ_REMOVE(src_utc->areas, area, link);
769 
770 		new_area_base = dst_base + (src_base - area->base);
771 		new_idx = (new_area_base - dst_pgt[0]->vabase) /
772 			  CORE_MMU_PGDIR_SIZE;
773 		assert((new_area_base & ~CORE_MMU_PGDIR_MASK) ==
774 		       dst_pgt[new_idx]->vabase);
775 		transpose_area(area, dst_pgt[new_idx], new_area_base);
776 
777 		/*
778 		 * Assert that this will not cause any conflicts in the new
779 		 * utc.  This should already be guaranteed, but a bug here
780 		 * could be tricky to find.
781 		 */
782 		assert(!find_area(dst_utc->areas, area->base));
783 		TAILQ_INSERT_TAIL(dst_utc->areas, area, link);
784 	}
785 }
786 
787 static void rem_area(struct tee_pager_area_head *area_head,
788 		     struct tee_pager_area *area)
789 {
790 	struct tee_pager_pmem *pmem;
791 	uint32_t exceptions;
792 
793 	exceptions = pager_lock();
794 
795 	TAILQ_REMOVE(area_head, area, link);
796 
797 	TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) {
798 		if (pmem->area == area) {
799 			area_set_entry(area, pmem->pgidx, 0, 0);
800 			pgt_dec_used_entries(area->pgt);
801 			pmem->area = NULL;
802 			pmem->pgidx = INVALID_PGIDX;
803 		}
804 	}
805 
806 	pager_unlock(exceptions);
807 	free_area(area);
808 }
809 KEEP_PAGER(rem_area);
810 
811 void tee_pager_rem_uta_region(struct user_ta_ctx *utc, vaddr_t base,
812 			      size_t size)
813 {
814 	struct tee_pager_area *area;
815 	struct tee_pager_area *next_a;
816 	size_t s = ROUNDUP(size, SMALL_PAGE_SIZE);
817 
818 	TAILQ_FOREACH_SAFE(area, utc->areas, link, next_a) {
819 		if (core_is_buffer_inside(area->base, area->size, base, s))
820 			rem_area(utc->areas, area);
821 	}
822 }
823 
824 void tee_pager_rem_uta_areas(struct user_ta_ctx *utc)
825 {
826 	struct tee_pager_area *area;
827 
828 	if (!utc->areas)
829 		return;
830 
831 	while (true) {
832 		area = TAILQ_FIRST(utc->areas);
833 		if (!area)
834 			break;
835 		TAILQ_REMOVE(utc->areas, area, link);
836 		free_area(area);
837 	}
838 
839 	free(utc->areas);
840 }
841 
842 bool tee_pager_set_uta_area_attr(struct user_ta_ctx *utc, vaddr_t base,
843 				 size_t size, uint32_t flags)
844 {
845 	bool ret;
846 	vaddr_t b = base;
847 	size_t s = size;
848 	size_t s2;
849 	struct tee_pager_area *area = find_area(utc->areas, b);
850 	uint32_t exceptions;
851 	struct tee_pager_pmem *pmem;
852 	paddr_t pa;
853 	uint32_t a;
854 	uint32_t f;
855 
856 	f = (flags & TEE_MATTR_URWX) | TEE_MATTR_UR | TEE_MATTR_PR;
857 	if (f & TEE_MATTR_UW)
858 		f |= TEE_MATTR_PW;
859 	f = get_area_mattr(f);
860 
861 	exceptions = pager_lock();
862 
863 	while (s) {
864 		s2 = MIN(CORE_MMU_PGDIR_SIZE - (b & CORE_MMU_PGDIR_MASK), s);
865 		if (!area || area->base != b || area->size != s2) {
866 			ret = false;
867 			goto out;
868 		}
869 		b += s2;
870 		s -= s2;
871 
872 		TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) {
873 			if (pmem->area != area)
874 				continue;
875 			area_get_entry(pmem->area, pmem->pgidx, &pa, &a);
876 			if (a & TEE_MATTR_VALID_BLOCK)
877 				assert(pa == get_pmem_pa(pmem));
878 			else
879 				pa = get_pmem_pa(pmem);
880 			if (a == f)
881 				continue;
882 			area_set_entry(pmem->area, pmem->pgidx, 0, 0);
883 			/* TODO only invalidate entries touched above */
884 			core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0);
885 			if (!(flags & TEE_MATTR_UW))
886 				tee_pager_save_page(pmem, a);
887 
888 			area_set_entry(pmem->area, pmem->pgidx, pa, f);
889 
890 			if (flags & TEE_MATTR_UX) {
891 				void *va = (void *)area_idx2va(pmem->area,
892 							       pmem->pgidx);
893 
894 				cache_maintenance_l1(DCACHE_AREA_CLEAN, va,
895 						     SMALL_PAGE_SIZE);
896 				cache_maintenance_l1(ICACHE_AREA_INVALIDATE, va,
897 						     SMALL_PAGE_SIZE);
898 			}
899 		}
900 
901 		area->flags = f;
902 		area = TAILQ_NEXT(area, link);
903 	}
904 
905 	ret = true;
906 out:
907 	pager_unlock(exceptions);
908 	return ret;
909 }
910 KEEP_PAGER(tee_pager_set_uta_area_attr);
911 #endif /*CFG_PAGED_USER_TA*/
912 
913 static bool tee_pager_unhide_page(vaddr_t page_va)
914 {
915 	struct tee_pager_pmem *pmem;
916 
917 	TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) {
918 		paddr_t pa;
919 		uint32_t attr;
920 
921 		if (pmem->pgidx == INVALID_PGIDX)
922 			continue;
923 
924 		area_get_entry(pmem->area, pmem->pgidx, &pa, &attr);
925 
926 		if (!(attr &
927 		     (TEE_MATTR_HIDDEN_BLOCK | TEE_MATTR_HIDDEN_DIRTY_BLOCK)))
928 			continue;
929 
930 		if (area_va2idx(pmem->area, page_va) == pmem->pgidx) {
931 			uint32_t a = get_area_mattr(pmem->area->flags);
932 
933 			/* page is hidden, show and move to back */
934 			if (pa != get_pmem_pa(pmem))
935 				panic("unexpected pa");
936 
937 			/*
938 			 * If it's not a dirty block, then it should be
939 			 * read only.
940 			 */
941 			if (!(attr & TEE_MATTR_HIDDEN_DIRTY_BLOCK))
942 				a &= ~(TEE_MATTR_PW | TEE_MATTR_UW);
943 			else
944 				FMSG("Unhide %#" PRIxVA, page_va);
945 
946 			if (page_va == 0x8000a000)
947 				FMSG("unhide %#" PRIxVA " a %#" PRIX32,
948 					page_va, a);
949 			area_set_entry(pmem->area, pmem->pgidx, pa, a);
950 
951 			TAILQ_REMOVE(&tee_pager_pmem_head, pmem, link);
952 			TAILQ_INSERT_TAIL(&tee_pager_pmem_head, pmem, link);
953 
954 			/* TODO only invalidate entry touched above */
955 			core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0);
956 
957 			incr_hidden_hits();
958 			return true;
959 		}
960 	}
961 
962 	return false;
963 }
964 
965 static void tee_pager_hide_pages(void)
966 {
967 	struct tee_pager_pmem *pmem;
968 	size_t n = 0;
969 
970 	TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) {
971 		paddr_t pa;
972 		uint32_t attr;
973 		uint32_t a;
974 
975 		if (n >= TEE_PAGER_NHIDE)
976 			break;
977 		n++;
978 
979 		/* we cannot hide pages when pmem->area is not defined. */
980 		if (!pmem->area)
981 			continue;
982 
983 		area_get_entry(pmem->area, pmem->pgidx, &pa, &attr);
984 		if (!(attr & TEE_MATTR_VALID_BLOCK))
985 			continue;
986 
987 		assert(pa == get_pmem_pa(pmem));
988 		if (attr & (TEE_MATTR_PW | TEE_MATTR_UW)){
989 			a = TEE_MATTR_HIDDEN_DIRTY_BLOCK;
990 			FMSG("Hide %#" PRIxVA,
991 			     area_idx2va(pmem->area, pmem->pgidx));
992 		} else
993 			a = TEE_MATTR_HIDDEN_BLOCK;
994 		area_set_entry(pmem->area, pmem->pgidx, pa, a);
995 	}
996 
997 	/* TODO only invalidate entries touched above */
998 	core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0);
999 }
1000 
1001 /*
1002  * Find mapped pmem, hide and move to pageble pmem.
1003  * Return false if page was not mapped, and true if page was mapped.
1004  */
1005 static bool tee_pager_release_one_phys(struct tee_pager_area *area,
1006 				       vaddr_t page_va)
1007 {
1008 	struct tee_pager_pmem *pmem;
1009 	unsigned pgidx;
1010 	paddr_t pa;
1011 	uint32_t attr;
1012 
1013 	pgidx = area_va2idx(area, page_va);
1014 	area_get_entry(area, pgidx, &pa, &attr);
1015 
1016 	FMSG("%" PRIxVA " : %" PRIxPA "|%x", page_va, pa, attr);
1017 
1018 	TAILQ_FOREACH(pmem, &tee_pager_lock_pmem_head, link) {
1019 		if (pmem->area != area || pmem->pgidx != pgidx)
1020 			continue;
1021 
1022 		assert(pa == get_pmem_pa(pmem));
1023 		area_set_entry(area, pgidx, 0, 0);
1024 		pgt_dec_used_entries(area->pgt);
1025 		TAILQ_REMOVE(&tee_pager_lock_pmem_head, pmem, link);
1026 		pmem->area = NULL;
1027 		pmem->pgidx = INVALID_PGIDX;
1028 		tee_pager_npages++;
1029 		set_npages();
1030 		TAILQ_INSERT_HEAD(&tee_pager_pmem_head, pmem, link);
1031 		incr_zi_released();
1032 		return true;
1033 	}
1034 
1035 	return false;
1036 }
1037 
1038 /* Finds the oldest page and unmats it from its old virtual address */
1039 static struct tee_pager_pmem *tee_pager_get_page(struct tee_pager_area *area)
1040 {
1041 	struct tee_pager_pmem *pmem;
1042 
1043 	pmem = TAILQ_FIRST(&tee_pager_pmem_head);
1044 	if (!pmem) {
1045 		EMSG("No pmem entries");
1046 		return NULL;
1047 	}
1048 	if (pmem->pgidx != INVALID_PGIDX) {
1049 		uint32_t a;
1050 
1051 		assert(pmem->area && pmem->area->pgt);
1052 		area_get_entry(pmem->area, pmem->pgidx, NULL, &a);
1053 		area_set_entry(pmem->area, pmem->pgidx, 0, 0);
1054 		pgt_dec_used_entries(pmem->area->pgt);
1055 		/* TODO only invalidate entries touched above */
1056 		core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0);
1057 		tee_pager_save_page(pmem, a);
1058 	}
1059 
1060 	TAILQ_REMOVE(&tee_pager_pmem_head, pmem, link);
1061 	pmem->pgidx = INVALID_PGIDX;
1062 	pmem->area = NULL;
1063 	if (area->type == AREA_TYPE_LOCK) {
1064 		/* Move page to lock list */
1065 		if (tee_pager_npages <= 0)
1066 			panic("running out of page");
1067 		tee_pager_npages--;
1068 		set_npages();
1069 		TAILQ_INSERT_TAIL(&tee_pager_lock_pmem_head, pmem, link);
1070 	} else {
1071 		/* move page to back */
1072 		TAILQ_INSERT_TAIL(&tee_pager_pmem_head, pmem, link);
1073 	}
1074 
1075 	return pmem;
1076 }
1077 
1078 static bool pager_update_permissions(struct tee_pager_area *area,
1079 			struct abort_info *ai, bool *handled)
1080 {
1081 	unsigned int pgidx = area_va2idx(area, ai->va);
1082 	uint32_t attr;
1083 	paddr_t pa;
1084 
1085 	*handled = false;
1086 
1087 	area_get_entry(area, pgidx, &pa, &attr);
1088 
1089 	/* Not mapped */
1090 	if (!(attr & TEE_MATTR_VALID_BLOCK))
1091 		return false;
1092 
1093 	/* Not readable, should not happen */
1094 	if (abort_is_user_exception(ai)) {
1095 		if (!(attr & TEE_MATTR_UR))
1096 			return true;
1097 	} else {
1098 		if (!(attr & TEE_MATTR_PR)) {
1099 			abort_print_error(ai);
1100 			panic();
1101 		}
1102 	}
1103 
1104 	switch (core_mmu_get_fault_type(ai->fault_descr)) {
1105 	case CORE_MMU_FAULT_TRANSLATION:
1106 	case CORE_MMU_FAULT_READ_PERMISSION:
1107 		if (ai->abort_type == ABORT_TYPE_PREFETCH) {
1108 			/* Check attempting to execute from an NOX page */
1109 			if (abort_is_user_exception(ai)) {
1110 				if (!(attr & TEE_MATTR_UX))
1111 					return true;
1112 			} else {
1113 				if (!(attr & TEE_MATTR_PX)) {
1114 					abort_print_error(ai);
1115 					panic();
1116 				}
1117 			}
1118 		}
1119 		/* Since the page is mapped now it's OK */
1120 		break;
1121 	case CORE_MMU_FAULT_WRITE_PERMISSION:
1122 		/* Check attempting to write to an RO page */
1123 		if (abort_is_user_exception(ai)) {
1124 			if (!(area->flags & TEE_MATTR_UW))
1125 				return true;
1126 			if (!(attr & TEE_MATTR_UW)) {
1127 				FMSG("Dirty %p",
1128 				     (void *)(ai->va & ~SMALL_PAGE_MASK));
1129 				area_set_entry(area, pgidx, pa,
1130 					       get_area_mattr(area->flags));
1131 				/* TODO only invalidate entry above */
1132 				core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0);
1133 			}
1134 
1135 		} else {
1136 			if (!(area->flags & TEE_MATTR_PW)) {
1137 				abort_print_error(ai);
1138 				panic();
1139 			}
1140 			if (!(attr & TEE_MATTR_PW)) {
1141 				FMSG("Dirty %p",
1142 				     (void *)(ai->va & ~SMALL_PAGE_MASK));
1143 				area_set_entry(area, pgidx, pa,
1144 					       get_area_mattr(area->flags));
1145 				/* TODO only invalidate entry above */
1146 				core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0);
1147 			}
1148 		}
1149 		/* Since permissions has been updated now it's OK */
1150 		break;
1151 	default:
1152 		/* Some fault we can't deal with */
1153 		if (abort_is_user_exception(ai))
1154 			return true;
1155 		abort_print_error(ai);
1156 		panic();
1157 	}
1158 	*handled = true;
1159 	return true;
1160 }
1161 
1162 #ifdef CFG_TEE_CORE_DEBUG
1163 static void stat_handle_fault(void)
1164 {
1165 	static size_t num_faults;
1166 	static size_t min_npages = SIZE_MAX;
1167 	static size_t total_min_npages = SIZE_MAX;
1168 
1169 	num_faults++;
1170 	if ((num_faults % 1024) == 0 || tee_pager_npages < total_min_npages) {
1171 		DMSG("nfaults %zu npages %zu (min %zu)",
1172 		     num_faults, tee_pager_npages, min_npages);
1173 		min_npages = tee_pager_npages; /* reset */
1174 	}
1175 	if (tee_pager_npages < min_npages)
1176 		min_npages = tee_pager_npages;
1177 	if (tee_pager_npages < total_min_npages)
1178 		total_min_npages = tee_pager_npages;
1179 }
1180 #else
1181 static void stat_handle_fault(void)
1182 {
1183 }
1184 #endif
1185 
1186 bool tee_pager_handle_fault(struct abort_info *ai)
1187 {
1188 	struct tee_pager_area *area;
1189 	vaddr_t page_va = ai->va & ~SMALL_PAGE_MASK;
1190 	uint32_t exceptions;
1191 	bool ret;
1192 
1193 #ifdef TEE_PAGER_DEBUG_PRINT
1194 	abort_print(ai);
1195 #endif
1196 
1197 	/*
1198 	 * We're updating pages that can affect several active CPUs at a
1199 	 * time below. We end up here because a thread tries to access some
1200 	 * memory that isn't available. We have to be careful when making
1201 	 * that memory available as other threads may succeed in accessing
1202 	 * that address the moment after we've made it available.
1203 	 *
1204 	 * That means that we can't just map the memory and populate the
1205 	 * page, instead we use the aliased mapping to populate the page
1206 	 * and once everything is ready we map it.
1207 	 */
1208 	exceptions = pager_lock();
1209 
1210 	stat_handle_fault();
1211 
1212 	/* check if the access is valid */
1213 	if (abort_is_user_exception(ai)) {
1214 		area = find_uta_area(ai->va);
1215 
1216 	} else {
1217 		area = find_area(&tee_pager_area_head, ai->va);
1218 		if (!area)
1219 			area = find_uta_area(ai->va);
1220 	}
1221 	if (!area || !area->pgt) {
1222 		ret = false;
1223 		goto out;
1224 	}
1225 
1226 	if (!tee_pager_unhide_page(page_va)) {
1227 		struct tee_pager_pmem *pmem = NULL;
1228 		uint32_t attr;
1229 
1230 		/*
1231 		 * The page wasn't hidden, but some other core may have
1232 		 * updated the table entry before we got here or we need
1233 		 * to make a read-only page read-write (dirty).
1234 		 */
1235 		if (pager_update_permissions(area, ai, &ret)) {
1236 			/*
1237 			 * Nothing more to do with the abort. The problem
1238 			 * could already have been dealt with from another
1239 			 * core or if ret is false the TA will be paniced.
1240 			 */
1241 			goto out;
1242 		}
1243 
1244 		pmem = tee_pager_get_page(area);
1245 		if (!pmem) {
1246 			abort_print(ai);
1247 			panic();
1248 		}
1249 
1250 		/* load page code & data */
1251 		tee_pager_load_page(area, page_va, pmem->va_alias);
1252 
1253 		/*
1254 		 * We've updated the page using the aliased mapping and
1255 		 * some cache maintenence is now needed if it's an
1256 		 * executable page.
1257 		 *
1258 		 * Since the d-cache is a Physically-indexed,
1259 		 * physically-tagged (PIPT) cache we can clean the aliased
1260 		 * address instead of the real virtual address.
1261 		 *
1262 		 * The i-cache can also be PIPT, but may be something else
1263 		 * to, to keep it simple we invalidate the entire i-cache.
1264 		 * As a future optimization we may invalidate only the
1265 		 * aliased area if it a PIPT cache else the entire cache.
1266 		 */
1267 		if (area->flags & (TEE_MATTR_PX | TEE_MATTR_UX)) {
1268 			/*
1269 			 * Doing these operations to LoUIS (Level of
1270 			 * unification, Inner Shareable) would be enough
1271 			 */
1272 			cache_maintenance_l1(DCACHE_AREA_CLEAN,
1273 				pmem->va_alias, SMALL_PAGE_SIZE);
1274 
1275 			cache_maintenance_l1(ICACHE_INVALIDATE, NULL, 0);
1276 		}
1277 
1278 		pmem->area = area;
1279 		pmem->pgidx = area_va2idx(area, ai->va);
1280 		attr = get_area_mattr(area->flags) &
1281 			~(TEE_MATTR_PW | TEE_MATTR_UW);
1282 		area_set_entry(area, pmem->pgidx, get_pmem_pa(pmem), attr);
1283 		pgt_inc_used_entries(area->pgt);
1284 
1285 		FMSG("Mapped 0x%" PRIxVA " -> 0x%" PRIxPA,
1286 		     area_idx2va(area, pmem->pgidx), get_pmem_pa(pmem));
1287 
1288 	}
1289 
1290 	tee_pager_hide_pages();
1291 	ret = true;
1292 out:
1293 	pager_unlock(exceptions);
1294 	return ret;
1295 }
1296 
1297 void tee_pager_add_pages(vaddr_t vaddr, size_t npages, bool unmap)
1298 {
1299 	struct core_mmu_table_info *ti = &tee_pager_tbl_info;
1300 	size_t n;
1301 
1302 	DMSG("0x%" PRIxVA " - 0x%" PRIxVA " : %d",
1303 	     vaddr, vaddr + npages * SMALL_PAGE_SIZE, (int)unmap);
1304 
1305 	/* setup memory */
1306 	for (n = 0; n < npages; n++) {
1307 		struct tee_pager_pmem *pmem;
1308 		vaddr_t va = vaddr + n * SMALL_PAGE_SIZE;
1309 		unsigned pgidx = core_mmu_va2idx(ti, va);
1310 		paddr_t pa;
1311 		uint32_t attr;
1312 
1313 		/*
1314 		 * Note that we can only support adding pages in the
1315 		 * valid range of this table info, currently not a problem.
1316 		 */
1317 		core_mmu_get_entry(ti, pgidx, &pa, &attr);
1318 
1319 		/* Ignore unmapped pages/blocks */
1320 		if (!(attr & TEE_MATTR_VALID_BLOCK))
1321 			continue;
1322 
1323 		pmem = malloc(sizeof(struct tee_pager_pmem));
1324 		if (!pmem)
1325 			panic("out of mem");
1326 
1327 		pmem->va_alias = pager_add_alias_page(pa);
1328 
1329 		if (unmap) {
1330 			pmem->area = NULL;
1331 			pmem->pgidx = INVALID_PGIDX;
1332 			core_mmu_set_entry(ti, pgidx, 0, 0);
1333 			pgt_dec_used_entries(&pager_core_pgt);
1334 		} else {
1335 			/*
1336 			 * The page is still mapped, let's assign the area
1337 			 * and update the protection bits accordingly.
1338 			 */
1339 			pmem->area = find_area(&tee_pager_area_head, va);
1340 			assert(pmem->area->pgt == &pager_core_pgt);
1341 			pmem->pgidx = pgidx;
1342 			assert(pa == get_pmem_pa(pmem));
1343 			area_set_entry(pmem->area, pgidx, pa,
1344 				       get_area_mattr(pmem->area->flags));
1345 		}
1346 
1347 		tee_pager_npages++;
1348 		incr_npages_all();
1349 		set_npages();
1350 		TAILQ_INSERT_TAIL(&tee_pager_pmem_head, pmem, link);
1351 	}
1352 
1353 	/* Invalidate secure TLB */
1354 	core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0);
1355 }
1356 
1357 #ifdef CFG_PAGED_USER_TA
1358 static struct pgt *find_pgt(struct pgt *pgt, vaddr_t va)
1359 {
1360 	struct pgt *p = pgt;
1361 
1362 	while (p && (va & ~CORE_MMU_PGDIR_MASK) != p->vabase)
1363 		p = SLIST_NEXT(p, link);
1364 	return p;
1365 }
1366 
1367 void tee_pager_assign_uta_tables(struct user_ta_ctx *utc)
1368 {
1369 	struct tee_pager_area *area;
1370 	struct pgt *pgt = SLIST_FIRST(&thread_get_tsd()->pgt_cache);
1371 
1372 	TAILQ_FOREACH(area, utc->areas, link) {
1373 		if (!area->pgt)
1374 			area->pgt = find_pgt(pgt, area->base);
1375 		else
1376 			assert(area->pgt == find_pgt(pgt, area->base));
1377 		if (!area->pgt)
1378 			panic();
1379 	}
1380 }
1381 
1382 static void pager_save_and_release_entry(struct tee_pager_pmem *pmem)
1383 {
1384 	uint32_t attr;
1385 
1386 	assert(pmem->area && pmem->area->pgt);
1387 
1388 	area_get_entry(pmem->area, pmem->pgidx, NULL, &attr);
1389 	area_set_entry(pmem->area, pmem->pgidx, 0, 0);
1390 	tee_pager_save_page(pmem, attr);
1391 	assert(pmem->area->pgt->num_used_entries);
1392 	pmem->area->pgt->num_used_entries--;
1393 	pmem->pgidx = INVALID_PGIDX;
1394 	pmem->area = NULL;
1395 }
1396 
1397 void tee_pager_pgt_save_and_release_entries(struct pgt *pgt)
1398 {
1399 	struct tee_pager_pmem *pmem;
1400 	struct tee_pager_area *area;
1401 	uint32_t exceptions = pager_lock();
1402 
1403 	if (!pgt->num_used_entries)
1404 		goto out;
1405 
1406 	TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) {
1407 		if (!pmem->area || pmem->pgidx == INVALID_PGIDX)
1408 			continue;
1409 		if (pmem->area->pgt == pgt)
1410 			pager_save_and_release_entry(pmem);
1411 	}
1412 	assert(!pgt->num_used_entries);
1413 
1414 out:
1415 	if (is_user_ta_ctx(pgt->ctx)) {
1416 		TAILQ_FOREACH(area, to_user_ta_ctx(pgt->ctx)->areas, link) {
1417 			if (area->pgt == pgt)
1418 				area->pgt = NULL;
1419 		}
1420 	}
1421 
1422 	pager_unlock(exceptions);
1423 }
1424 KEEP_PAGER(tee_pager_pgt_save_and_release_entries);
1425 #endif /*CFG_PAGED_USER_TA*/
1426 
1427 void tee_pager_release_phys(void *addr, size_t size)
1428 {
1429 	bool unmaped = false;
1430 	vaddr_t va = (vaddr_t)addr;
1431 	vaddr_t begin = ROUNDUP(va, SMALL_PAGE_SIZE);
1432 	vaddr_t end = ROUNDDOWN(va + size, SMALL_PAGE_SIZE);
1433 	struct tee_pager_area *area;
1434 	uint32_t exceptions;
1435 
1436 	if (!size)
1437 		return;
1438 
1439 	area = find_area(&tee_pager_area_head, begin);
1440 	if (!area ||
1441 	    area != find_area(&tee_pager_area_head, end - SMALL_PAGE_SIZE))
1442 		panic();
1443 
1444 	exceptions = pager_lock();
1445 
1446 	for (va = begin; va < end; va += SMALL_PAGE_SIZE)
1447 		unmaped |= tee_pager_release_one_phys(area, va);
1448 
1449 	/* Invalidate secure TLB */
1450 	if (unmaped)
1451 		core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0);
1452 
1453 	pager_unlock(exceptions);
1454 }
1455 KEEP_PAGER(tee_pager_release_phys);
1456 
1457 void *tee_pager_alloc(size_t size, uint32_t flags)
1458 {
1459 	tee_mm_entry_t *mm;
1460 	uint32_t f = TEE_MATTR_PW | TEE_MATTR_PR | (flags & TEE_MATTR_LOCKED);
1461 
1462 	if (!size)
1463 		return NULL;
1464 
1465 	mm = tee_mm_alloc(&tee_mm_vcore, ROUNDUP(size, SMALL_PAGE_SIZE));
1466 	if (!mm)
1467 		return NULL;
1468 
1469 	tee_pager_add_core_area(tee_mm_get_smem(mm), tee_mm_get_bytes(mm),
1470 				f, NULL, NULL);
1471 
1472 	return (void *)tee_mm_get_smem(mm);
1473 }
1474