1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2016, Linaro Limited 4 * Copyright (c) 2014, STMicroelectronics International N.V. 5 */ 6 7 #include <arm.h> 8 #include <assert.h> 9 #include <io.h> 10 #include <keep.h> 11 #include <kernel/abort.h> 12 #include <kernel/asan.h> 13 #include <kernel/cache_helpers.h> 14 #include <kernel/panic.h> 15 #include <kernel/spinlock.h> 16 #include <kernel/tee_misc.h> 17 #include <kernel/tee_ta_manager.h> 18 #include <kernel/thread.h> 19 #include <kernel/tlb_helpers.h> 20 #include <mm/core_memprot.h> 21 #include <mm/fobj.h> 22 #include <mm/tee_mm.h> 23 #include <mm/tee_pager.h> 24 #include <stdlib.h> 25 #include <sys/queue.h> 26 #include <tee_api_defines.h> 27 #include <trace.h> 28 #include <types_ext.h> 29 #include <utee_defines.h> 30 #include <util.h> 31 32 33 static struct tee_pager_area_head tee_pager_area_head = 34 TAILQ_HEAD_INITIALIZER(tee_pager_area_head); 35 36 #define INVALID_PGIDX UINT_MAX 37 #define PMEM_FLAG_DIRTY BIT(0) 38 #define PMEM_FLAG_HIDDEN BIT(1) 39 40 /* 41 * struct tee_pager_pmem - Represents a physical page used for paging. 42 * 43 * @flags flags defined by PMEM_FLAG_* above 44 * @fobj_pgidx index of the page in the @fobj 45 * @fobj File object of which a page is made visible. 46 * @va_alias Virtual address where the physical page always is aliased. 47 * Used during remapping of the page when the content need to 48 * be updated before it's available at the new location. 49 */ 50 struct tee_pager_pmem { 51 unsigned int flags; 52 unsigned int fobj_pgidx; 53 struct fobj *fobj; 54 void *va_alias; 55 TAILQ_ENTRY(tee_pager_pmem) link; 56 }; 57 58 /* The list of physical pages. The first page in the list is the oldest */ 59 TAILQ_HEAD(tee_pager_pmem_head, tee_pager_pmem); 60 61 static struct tee_pager_pmem_head tee_pager_pmem_head = 62 TAILQ_HEAD_INITIALIZER(tee_pager_pmem_head); 63 64 static struct tee_pager_pmem_head tee_pager_lock_pmem_head = 65 TAILQ_HEAD_INITIALIZER(tee_pager_lock_pmem_head); 66 67 /* number of pages hidden */ 68 #define TEE_PAGER_NHIDE (tee_pager_npages / 3) 69 70 /* Number of registered physical pages, used hiding pages. */ 71 static size_t tee_pager_npages; 72 73 #ifdef CFG_WITH_STATS 74 static struct tee_pager_stats pager_stats; 75 76 static inline void incr_ro_hits(void) 77 { 78 pager_stats.ro_hits++; 79 } 80 81 static inline void incr_rw_hits(void) 82 { 83 pager_stats.rw_hits++; 84 } 85 86 static inline void incr_hidden_hits(void) 87 { 88 pager_stats.hidden_hits++; 89 } 90 91 static inline void incr_zi_released(void) 92 { 93 pager_stats.zi_released++; 94 } 95 96 static inline void incr_npages_all(void) 97 { 98 pager_stats.npages_all++; 99 } 100 101 static inline void set_npages(void) 102 { 103 pager_stats.npages = tee_pager_npages; 104 } 105 106 void tee_pager_get_stats(struct tee_pager_stats *stats) 107 { 108 *stats = pager_stats; 109 110 pager_stats.hidden_hits = 0; 111 pager_stats.ro_hits = 0; 112 pager_stats.rw_hits = 0; 113 pager_stats.zi_released = 0; 114 } 115 116 #else /* CFG_WITH_STATS */ 117 static inline void incr_ro_hits(void) { } 118 static inline void incr_rw_hits(void) { } 119 static inline void incr_hidden_hits(void) { } 120 static inline void incr_zi_released(void) { } 121 static inline void incr_npages_all(void) { } 122 static inline void set_npages(void) { } 123 124 void tee_pager_get_stats(struct tee_pager_stats *stats) 125 { 126 memset(stats, 0, sizeof(struct tee_pager_stats)); 127 } 128 #endif /* CFG_WITH_STATS */ 129 130 #define TBL_NUM_ENTRIES (CORE_MMU_PGDIR_SIZE / SMALL_PAGE_SIZE) 131 #define TBL_LEVEL CORE_MMU_PGDIR_LEVEL 132 #define TBL_SHIFT SMALL_PAGE_SHIFT 133 134 #define EFFECTIVE_VA_SIZE \ 135 (ROUNDUP(TEE_RAM_VA_START + TEE_RAM_VA_SIZE, \ 136 CORE_MMU_PGDIR_SIZE) - \ 137 ROUNDDOWN(TEE_RAM_VA_START, CORE_MMU_PGDIR_SIZE)) 138 139 static struct pager_table { 140 struct pgt pgt; 141 struct core_mmu_table_info tbl_info; 142 } pager_tables[EFFECTIVE_VA_SIZE / CORE_MMU_PGDIR_SIZE]; 143 144 static unsigned pager_spinlock = SPINLOCK_UNLOCK; 145 146 /* Defines the range of the alias area */ 147 static tee_mm_entry_t *pager_alias_area; 148 /* 149 * Physical pages are added in a stack like fashion to the alias area, 150 * @pager_alias_next_free gives the address of next free entry if 151 * @pager_alias_next_free is != 0 152 */ 153 static uintptr_t pager_alias_next_free; 154 155 #ifdef CFG_TEE_CORE_DEBUG 156 #define pager_lock(ai) pager_lock_dldetect(__func__, __LINE__, ai) 157 158 static uint32_t pager_lock_dldetect(const char *func, const int line, 159 struct abort_info *ai) 160 { 161 uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); 162 unsigned int retries = 0; 163 unsigned int reminder = 0; 164 165 while (!cpu_spin_trylock(&pager_spinlock)) { 166 retries++; 167 if (!retries) { 168 /* wrapped, time to report */ 169 trace_printf(func, line, TRACE_ERROR, true, 170 "possible spinlock deadlock reminder %u", 171 reminder); 172 if (reminder < UINT_MAX) 173 reminder++; 174 if (ai) 175 abort_print(ai); 176 } 177 } 178 179 return exceptions; 180 } 181 #else 182 static uint32_t pager_lock(struct abort_info __unused *ai) 183 { 184 return cpu_spin_lock_xsave(&pager_spinlock); 185 } 186 #endif 187 188 static uint32_t pager_lock_check_stack(size_t stack_size) 189 { 190 if (stack_size) { 191 int8_t buf[stack_size]; 192 size_t n; 193 194 /* 195 * Make sure to touch all pages of the stack that we expect 196 * to use with this lock held. We need to take eventual 197 * page faults before the lock is taken or we'll deadlock 198 * the pager. The pages that are populated in this way will 199 * eventually be released at certain save transitions of 200 * the thread. 201 */ 202 for (n = 0; n < stack_size; n += SMALL_PAGE_SIZE) 203 io_write8((vaddr_t)buf + n, 1); 204 io_write8((vaddr_t)buf + stack_size - 1, 1); 205 } 206 207 return pager_lock(NULL); 208 } 209 210 static void pager_unlock(uint32_t exceptions) 211 { 212 cpu_spin_unlock_xrestore(&pager_spinlock, exceptions); 213 } 214 215 void *tee_pager_phys_to_virt(paddr_t pa) 216 { 217 struct core_mmu_table_info ti; 218 unsigned idx; 219 uint32_t a; 220 paddr_t p; 221 vaddr_t v; 222 size_t n; 223 224 /* 225 * Most addresses are mapped lineary, try that first if possible. 226 */ 227 if (!tee_pager_get_table_info(pa, &ti)) 228 return NULL; /* impossible pa */ 229 idx = core_mmu_va2idx(&ti, pa); 230 core_mmu_get_entry(&ti, idx, &p, &a); 231 if ((a & TEE_MATTR_VALID_BLOCK) && p == pa) 232 return (void *)core_mmu_idx2va(&ti, idx); 233 234 n = 0; 235 idx = core_mmu_va2idx(&pager_tables[n].tbl_info, TEE_RAM_VA_START); 236 while (true) { 237 while (idx < TBL_NUM_ENTRIES) { 238 v = core_mmu_idx2va(&pager_tables[n].tbl_info, idx); 239 if (v >= (TEE_RAM_VA_START + TEE_RAM_VA_SIZE)) 240 return NULL; 241 242 core_mmu_get_entry(&pager_tables[n].tbl_info, 243 idx, &p, &a); 244 if ((a & TEE_MATTR_VALID_BLOCK) && p == pa) 245 return (void *)v; 246 idx++; 247 } 248 249 n++; 250 if (n >= ARRAY_SIZE(pager_tables)) 251 return NULL; 252 idx = 0; 253 } 254 255 return NULL; 256 } 257 258 static bool pmem_is_hidden(struct tee_pager_pmem *pmem) 259 { 260 return pmem->flags & PMEM_FLAG_HIDDEN; 261 } 262 263 static bool pmem_is_dirty(struct tee_pager_pmem *pmem) 264 { 265 return pmem->flags & PMEM_FLAG_DIRTY; 266 } 267 268 static bool pmem_is_covered_by_area(struct tee_pager_pmem *pmem, 269 struct tee_pager_area *area) 270 { 271 if (pmem->fobj != area->fobj) 272 return false; 273 if (pmem->fobj_pgidx < area->fobj_pgoffs) 274 return false; 275 if ((pmem->fobj_pgidx - area->fobj_pgoffs) >= 276 (area->size >> SMALL_PAGE_SHIFT)) 277 return false; 278 279 return true; 280 } 281 282 static size_t pmem_get_area_tblidx(struct tee_pager_pmem *pmem, 283 struct tee_pager_area *area) 284 { 285 size_t tbloffs = (area->base & CORE_MMU_PGDIR_MASK) >> SMALL_PAGE_SHIFT; 286 287 return pmem->fobj_pgidx - area->fobj_pgoffs + tbloffs; 288 } 289 290 static struct pager_table *find_pager_table_may_fail(vaddr_t va) 291 { 292 size_t n; 293 const vaddr_t mask = CORE_MMU_PGDIR_MASK; 294 295 n = ((va & ~mask) - pager_tables[0].tbl_info.va_base) >> 296 CORE_MMU_PGDIR_SHIFT; 297 if (n >= ARRAY_SIZE(pager_tables)) 298 return NULL; 299 300 assert(va >= pager_tables[n].tbl_info.va_base && 301 va <= (pager_tables[n].tbl_info.va_base | mask)); 302 303 return pager_tables + n; 304 } 305 306 static struct pager_table *find_pager_table(vaddr_t va) 307 { 308 struct pager_table *pt = find_pager_table_may_fail(va); 309 310 assert(pt); 311 return pt; 312 } 313 314 bool tee_pager_get_table_info(vaddr_t va, struct core_mmu_table_info *ti) 315 { 316 struct pager_table *pt = find_pager_table_may_fail(va); 317 318 if (!pt) 319 return false; 320 321 *ti = pt->tbl_info; 322 return true; 323 } 324 325 static struct core_mmu_table_info *find_table_info(vaddr_t va) 326 { 327 return &find_pager_table(va)->tbl_info; 328 } 329 330 static struct pgt *find_core_pgt(vaddr_t va) 331 { 332 return &find_pager_table(va)->pgt; 333 } 334 335 void tee_pager_set_alias_area(tee_mm_entry_t *mm) 336 { 337 struct pager_table *pt; 338 unsigned idx; 339 vaddr_t smem = tee_mm_get_smem(mm); 340 size_t nbytes = tee_mm_get_bytes(mm); 341 vaddr_t v; 342 uint32_t a = 0; 343 344 DMSG("0x%" PRIxVA " - 0x%" PRIxVA, smem, smem + nbytes); 345 346 assert(!pager_alias_area); 347 pager_alias_area = mm; 348 pager_alias_next_free = smem; 349 350 /* Clear all mapping in the alias area */ 351 pt = find_pager_table(smem); 352 idx = core_mmu_va2idx(&pt->tbl_info, smem); 353 while (pt <= (pager_tables + ARRAY_SIZE(pager_tables) - 1)) { 354 while (idx < TBL_NUM_ENTRIES) { 355 v = core_mmu_idx2va(&pt->tbl_info, idx); 356 if (v >= (smem + nbytes)) 357 goto out; 358 359 core_mmu_get_entry(&pt->tbl_info, idx, NULL, &a); 360 core_mmu_set_entry(&pt->tbl_info, idx, 0, 0); 361 if (a & TEE_MATTR_VALID_BLOCK) 362 pgt_dec_used_entries(&pt->pgt); 363 idx++; 364 } 365 366 pt++; 367 idx = 0; 368 } 369 370 out: 371 tlbi_mva_range(smem, nbytes, SMALL_PAGE_SIZE); 372 } 373 374 static size_t tbl_usage_count(struct core_mmu_table_info *ti) 375 { 376 size_t n; 377 uint32_t a = 0; 378 size_t usage = 0; 379 380 for (n = 0; n < ti->num_entries; n++) { 381 core_mmu_get_entry(ti, n, NULL, &a); 382 if (a & TEE_MATTR_VALID_BLOCK) 383 usage++; 384 } 385 return usage; 386 } 387 388 static void area_get_entry(struct tee_pager_area *area, size_t idx, 389 paddr_t *pa, uint32_t *attr) 390 { 391 assert(area->pgt); 392 assert(idx < TBL_NUM_ENTRIES); 393 core_mmu_get_entry_primitive(area->pgt->tbl, TBL_LEVEL, idx, pa, attr); 394 } 395 396 static void area_set_entry(struct tee_pager_area *area, size_t idx, 397 paddr_t pa, uint32_t attr) 398 { 399 assert(area->pgt); 400 assert(idx < TBL_NUM_ENTRIES); 401 core_mmu_set_entry_primitive(area->pgt->tbl, TBL_LEVEL, idx, pa, attr); 402 } 403 404 static size_t area_va2idx(struct tee_pager_area *area, vaddr_t va) 405 { 406 return (va - (area->base & ~CORE_MMU_PGDIR_MASK)) >> SMALL_PAGE_SHIFT; 407 } 408 409 static vaddr_t area_idx2va(struct tee_pager_area *area, size_t idx) 410 { 411 return (idx << SMALL_PAGE_SHIFT) + (area->base & ~CORE_MMU_PGDIR_MASK); 412 } 413 414 static void pmem_unmap(struct tee_pager_pmem *pmem, struct pgt *only_this_pgt) 415 { 416 struct tee_pager_area *area = NULL; 417 size_t tblidx = 0; 418 uint32_t a = 0; 419 420 TAILQ_FOREACH(area, &pmem->fobj->areas, fobj_link) { 421 /* 422 * If only_this_pgt points to a pgt then the pgt of this 423 * area has to match or we'll skip over it. 424 */ 425 if (only_this_pgt && area->pgt != only_this_pgt) 426 continue; 427 if (!area->pgt || !pmem_is_covered_by_area(pmem, area)) 428 continue; 429 tblidx = pmem_get_area_tblidx(pmem, area); 430 area_get_entry(area, tblidx, NULL, &a); 431 if (a & TEE_MATTR_VALID_BLOCK) { 432 area_set_entry(area, tblidx, 0, 0); 433 pgt_dec_used_entries(area->pgt); 434 tlbi_mva_allasid(area_idx2va(area, tblidx)); 435 } 436 } 437 } 438 439 void tee_pager_early_init(void) 440 { 441 size_t n; 442 443 /* 444 * Note that this depends on add_pager_vaspace() adding vaspace 445 * after end of memory. 446 */ 447 for (n = 0; n < ARRAY_SIZE(pager_tables); n++) { 448 if (!core_mmu_find_table(NULL, TEE_RAM_VA_START + 449 n * CORE_MMU_PGDIR_SIZE, UINT_MAX, 450 &pager_tables[n].tbl_info)) 451 panic("can't find mmu tables"); 452 453 if (pager_tables[n].tbl_info.shift != TBL_SHIFT) 454 panic("Unsupported page size in translation table"); 455 assert(pager_tables[n].tbl_info.num_entries == TBL_NUM_ENTRIES); 456 assert(pager_tables[n].tbl_info.level == TBL_LEVEL); 457 458 pager_tables[n].pgt.tbl = pager_tables[n].tbl_info.table; 459 pgt_set_used_entries(&pager_tables[n].pgt, 460 tbl_usage_count(&pager_tables[n].tbl_info)); 461 } 462 } 463 464 static void *pager_add_alias_page(paddr_t pa) 465 { 466 unsigned idx; 467 struct core_mmu_table_info *ti; 468 /* Alias pages mapped without write permission: runtime will care */ 469 uint32_t attr = TEE_MATTR_VALID_BLOCK | 470 (TEE_MATTR_CACHE_CACHED << TEE_MATTR_CACHE_SHIFT) | 471 TEE_MATTR_SECURE | TEE_MATTR_PR; 472 473 DMSG("0x%" PRIxPA, pa); 474 475 ti = find_table_info(pager_alias_next_free); 476 idx = core_mmu_va2idx(ti, pager_alias_next_free); 477 core_mmu_set_entry(ti, idx, pa, attr); 478 pgt_inc_used_entries(find_core_pgt(pager_alias_next_free)); 479 pager_alias_next_free += SMALL_PAGE_SIZE; 480 if (pager_alias_next_free >= (tee_mm_get_smem(pager_alias_area) + 481 tee_mm_get_bytes(pager_alias_area))) 482 pager_alias_next_free = 0; 483 return (void *)core_mmu_idx2va(ti, idx); 484 } 485 486 static void area_insert_tail(struct tee_pager_area *area) 487 { 488 uint32_t exceptions = pager_lock_check_stack(8); 489 490 TAILQ_INSERT_TAIL(&tee_pager_area_head, area, link); 491 TAILQ_INSERT_TAIL(&area->fobj->areas, area, fobj_link); 492 493 pager_unlock(exceptions); 494 } 495 KEEP_PAGER(area_insert_tail); 496 497 void tee_pager_add_core_area(vaddr_t base, enum tee_pager_area_type type, 498 struct fobj *fobj) 499 { 500 struct tee_pager_area *area = NULL; 501 uint32_t flags = 0; 502 size_t fobj_pgoffs = 0; 503 vaddr_t b = base; 504 size_t s = fobj->num_pages * SMALL_PAGE_SIZE; 505 size_t s2 = 0; 506 507 DMSG("0x%" PRIxPTR " - 0x%" PRIxPTR " : type %d", base, base + s, type); 508 509 if (base & SMALL_PAGE_MASK || !s) { 510 EMSG("invalid pager area [%" PRIxVA " +0x%zx]", base, s); 511 panic(); 512 } 513 514 switch (type) { 515 case PAGER_AREA_TYPE_RO: 516 flags = TEE_MATTR_PRX; 517 break; 518 case PAGER_AREA_TYPE_RW: 519 flags = TEE_MATTR_PRW; 520 break; 521 case PAGER_AREA_TYPE_LOCK: 522 flags = TEE_MATTR_PRW | TEE_MATTR_LOCKED; 523 break; 524 default: 525 panic(); 526 } 527 528 if (!fobj) 529 panic(); 530 531 while (s) { 532 s2 = MIN(CORE_MMU_PGDIR_SIZE - (b & CORE_MMU_PGDIR_MASK), s); 533 area = calloc(1, sizeof(*area)); 534 if (!area) 535 panic("alloc_area"); 536 537 area->fobj = fobj_get(fobj); 538 area->fobj_pgoffs = fobj_pgoffs; 539 area->type = type; 540 area->pgt = find_core_pgt(b); 541 area->base = b; 542 area->size = s2; 543 area->flags = flags; 544 area_insert_tail(area); 545 546 b += s2; 547 s -= s2; 548 fobj_pgoffs += s2 / SMALL_PAGE_SIZE; 549 } 550 } 551 552 static struct tee_pager_area *find_area(struct tee_pager_area_head *areas, 553 vaddr_t va) 554 { 555 struct tee_pager_area *area; 556 557 if (!areas) 558 return NULL; 559 560 TAILQ_FOREACH(area, areas, link) { 561 if (core_is_buffer_inside(va, 1, area->base, area->size)) 562 return area; 563 } 564 return NULL; 565 } 566 567 #ifdef CFG_PAGED_USER_TA 568 static struct tee_pager_area *find_uta_area(vaddr_t va) 569 { 570 struct tee_ta_ctx *ctx = thread_get_tsd()->ctx; 571 572 if (!is_user_ta_ctx(ctx)) 573 return NULL; 574 return find_area(to_user_ta_ctx(ctx)->areas, va); 575 } 576 #else 577 static struct tee_pager_area *find_uta_area(vaddr_t va __unused) 578 { 579 return NULL; 580 } 581 #endif /*CFG_PAGED_USER_TA*/ 582 583 584 static uint32_t get_area_mattr(uint32_t area_flags) 585 { 586 uint32_t attr = TEE_MATTR_VALID_BLOCK | TEE_MATTR_SECURE | 587 TEE_MATTR_CACHE_CACHED << TEE_MATTR_CACHE_SHIFT | 588 (area_flags & (TEE_MATTR_PRWX | TEE_MATTR_URWX)); 589 590 return attr; 591 } 592 593 static paddr_t get_pmem_pa(struct tee_pager_pmem *pmem) 594 { 595 struct core_mmu_table_info *ti; 596 paddr_t pa; 597 unsigned idx; 598 599 ti = find_table_info((vaddr_t)pmem->va_alias); 600 idx = core_mmu_va2idx(ti, (vaddr_t)pmem->va_alias); 601 core_mmu_get_entry(ti, idx, &pa, NULL); 602 return pa; 603 } 604 605 static void tee_pager_load_page(struct tee_pager_area *area, vaddr_t page_va, 606 void *va_alias) 607 { 608 size_t fobj_pgoffs = ((page_va - area->base) >> SMALL_PAGE_SHIFT) + 609 area->fobj_pgoffs; 610 struct core_mmu_table_info *ti; 611 uint32_t attr_alias; 612 paddr_t pa_alias; 613 unsigned int idx_alias; 614 615 /* Insure we are allowed to write to aliased virtual page */ 616 ti = find_table_info((vaddr_t)va_alias); 617 idx_alias = core_mmu_va2idx(ti, (vaddr_t)va_alias); 618 core_mmu_get_entry(ti, idx_alias, &pa_alias, &attr_alias); 619 if (!(attr_alias & TEE_MATTR_PW)) { 620 attr_alias |= TEE_MATTR_PW; 621 core_mmu_set_entry(ti, idx_alias, pa_alias, attr_alias); 622 tlbi_mva_allasid((vaddr_t)va_alias); 623 } 624 625 asan_tag_access(va_alias, (uint8_t *)va_alias + SMALL_PAGE_SIZE); 626 if (fobj_load_page(area->fobj, fobj_pgoffs, va_alias)) { 627 EMSG("PH 0x%" PRIxVA " failed", page_va); 628 panic(); 629 } 630 switch (area->type) { 631 case PAGER_AREA_TYPE_RO: 632 incr_ro_hits(); 633 /* Forbid write to aliases for read-only (maybe exec) pages */ 634 attr_alias &= ~TEE_MATTR_PW; 635 core_mmu_set_entry(ti, idx_alias, pa_alias, attr_alias); 636 tlbi_mva_allasid((vaddr_t)va_alias); 637 break; 638 case PAGER_AREA_TYPE_RW: 639 incr_rw_hits(); 640 break; 641 case PAGER_AREA_TYPE_LOCK: 642 break; 643 default: 644 panic(); 645 } 646 asan_tag_no_access(va_alias, (uint8_t *)va_alias + SMALL_PAGE_SIZE); 647 } 648 649 static void tee_pager_save_page(struct tee_pager_pmem *pmem) 650 { 651 if (pmem_is_dirty(pmem)) { 652 asan_tag_access(pmem->va_alias, 653 (uint8_t *)pmem->va_alias + SMALL_PAGE_SIZE); 654 if (fobj_save_page(pmem->fobj, pmem->fobj_pgidx, 655 pmem->va_alias)) 656 panic("fobj_save_page"); 657 asan_tag_no_access(pmem->va_alias, 658 (uint8_t *)pmem->va_alias + SMALL_PAGE_SIZE); 659 } 660 } 661 662 #ifdef CFG_PAGED_USER_TA 663 static void unlink_area(struct tee_pager_area_head *area_head, 664 struct tee_pager_area *area) 665 { 666 uint32_t exceptions = pager_lock_check_stack(64); 667 668 TAILQ_REMOVE(area_head, area, link); 669 TAILQ_REMOVE(&area->fobj->areas, area, fobj_link); 670 671 pager_unlock(exceptions); 672 } 673 KEEP_PAGER(unlink_area); 674 675 static void free_area(struct tee_pager_area *area) 676 { 677 fobj_put(area->fobj); 678 free(area); 679 } 680 681 static TEE_Result pager_add_uta_area(struct user_ta_ctx *utc, vaddr_t base, 682 struct fobj *fobj, uint32_t prot) 683 { 684 struct tee_pager_area *area; 685 vaddr_t b = base; 686 size_t fobj_pgoffs = 0; 687 size_t s = fobj->num_pages * SMALL_PAGE_SIZE; 688 689 if (!utc->areas) { 690 utc->areas = malloc(sizeof(*utc->areas)); 691 if (!utc->areas) 692 return TEE_ERROR_OUT_OF_MEMORY; 693 TAILQ_INIT(utc->areas); 694 } 695 696 while (s) { 697 size_t s2; 698 699 if (find_area(utc->areas, b)) 700 return TEE_ERROR_BAD_PARAMETERS; 701 702 s2 = MIN(CORE_MMU_PGDIR_SIZE - (b & CORE_MMU_PGDIR_MASK), s); 703 area = calloc(1, sizeof(*area)); 704 if (!area) 705 return TEE_ERROR_OUT_OF_MEMORY; 706 707 /* Table info will be set when the context is activated. */ 708 area->fobj = fobj_get(fobj); 709 area->fobj_pgoffs = fobj_pgoffs; 710 area->type = PAGER_AREA_TYPE_RW; 711 area->base = b; 712 area->size = s2; 713 area->flags = prot; 714 715 TAILQ_INSERT_TAIL(utc->areas, area, link); 716 TAILQ_INSERT_TAIL(&fobj->areas, area, fobj_link); 717 b += s2; 718 s -= s2; 719 fobj_pgoffs += s2 / SMALL_PAGE_SIZE; 720 } 721 722 return TEE_SUCCESS; 723 } 724 725 TEE_Result tee_pager_add_uta_area(struct user_ta_ctx *utc, vaddr_t base, 726 struct fobj *fobj, uint32_t prot) 727 { 728 TEE_Result res = TEE_SUCCESS; 729 struct thread_specific_data *tsd = thread_get_tsd(); 730 struct tee_pager_area *area = NULL; 731 struct core_mmu_table_info dir_info = { NULL }; 732 733 if (&utc->ctx != tsd->ctx) { 734 /* 735 * Changes are to an utc that isn't active. Just add the 736 * areas page tables will be dealt with later. 737 */ 738 return pager_add_uta_area(utc, base, fobj, prot); 739 } 740 741 /* 742 * Assign page tables before adding areas to be able to tell which 743 * are newly added and should be removed in case of failure. 744 */ 745 tee_pager_assign_uta_tables(utc); 746 res = pager_add_uta_area(utc, base, fobj, prot); 747 if (res) { 748 struct tee_pager_area *next_a; 749 750 /* Remove all added areas */ 751 TAILQ_FOREACH_SAFE(area, utc->areas, link, next_a) { 752 if (!area->pgt) { 753 unlink_area(utc->areas, area); 754 free_area(area); 755 } 756 } 757 return res; 758 } 759 760 /* 761 * Assign page tables to the new areas and make sure that the page 762 * tables are registered in the upper table. 763 */ 764 tee_pager_assign_uta_tables(utc); 765 core_mmu_get_user_pgdir(&dir_info); 766 TAILQ_FOREACH(area, utc->areas, link) { 767 paddr_t pa; 768 size_t idx; 769 uint32_t attr; 770 771 idx = core_mmu_va2idx(&dir_info, area->pgt->vabase); 772 core_mmu_get_entry(&dir_info, idx, &pa, &attr); 773 774 /* 775 * Check if the page table already is used, if it is, it's 776 * already registered. 777 */ 778 if (area->pgt->num_used_entries) { 779 assert(attr & TEE_MATTR_TABLE); 780 assert(pa == virt_to_phys(area->pgt->tbl)); 781 continue; 782 } 783 784 attr = TEE_MATTR_SECURE | TEE_MATTR_TABLE; 785 pa = virt_to_phys(area->pgt->tbl); 786 assert(pa); 787 /* 788 * Note that the update of the table entry is guaranteed to 789 * be atomic. 790 */ 791 core_mmu_set_entry(&dir_info, idx, pa, attr); 792 } 793 794 return TEE_SUCCESS; 795 } 796 797 static void rem_area(struct tee_pager_area_head *area_head, 798 struct tee_pager_area *area) 799 { 800 struct tee_pager_pmem *pmem; 801 size_t last_pgoffs = area->fobj_pgoffs + 802 (area->size >> SMALL_PAGE_SHIFT) - 1; 803 uint32_t exceptions; 804 size_t idx = 0; 805 uint32_t a = 0; 806 807 exceptions = pager_lock_check_stack(64); 808 809 TAILQ_REMOVE(area_head, area, link); 810 TAILQ_REMOVE(&area->fobj->areas, area, fobj_link); 811 812 TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) { 813 if (pmem->fobj != area->fobj || 814 pmem->fobj_pgidx < area->fobj_pgoffs || 815 pmem->fobj_pgidx > last_pgoffs) 816 continue; 817 818 idx = pmem_get_area_tblidx(pmem, area); 819 area_get_entry(area, idx, NULL, &a); 820 if (!(a & TEE_MATTR_VALID_BLOCK)) 821 continue; 822 823 area_set_entry(area, idx, 0, 0); 824 tlbi_mva_allasid(area_idx2va(area, idx)); 825 pgt_dec_used_entries(area->pgt); 826 } 827 828 pager_unlock(exceptions); 829 830 free_area(area); 831 } 832 KEEP_PAGER(rem_area); 833 834 void tee_pager_rem_uta_region(struct user_ta_ctx *utc, vaddr_t base, 835 size_t size) 836 { 837 struct tee_pager_area *area; 838 struct tee_pager_area *next_a; 839 size_t s = ROUNDUP(size, SMALL_PAGE_SIZE); 840 841 TAILQ_FOREACH_SAFE(area, utc->areas, link, next_a) { 842 if (core_is_buffer_inside(area->base, area->size, base, s)) 843 rem_area(utc->areas, area); 844 } 845 tlbi_asid(utc->vm_info->asid); 846 } 847 848 void tee_pager_rem_uta_areas(struct user_ta_ctx *utc) 849 { 850 struct tee_pager_area *area; 851 852 if (!utc->areas) 853 return; 854 855 while (true) { 856 area = TAILQ_FIRST(utc->areas); 857 if (!area) 858 break; 859 unlink_area(utc->areas, area); 860 free_area(area); 861 } 862 863 free(utc->areas); 864 } 865 866 static bool __maybe_unused same_context(struct tee_pager_pmem *pmem) 867 { 868 struct tee_pager_area *a = TAILQ_FIRST(&pmem->fobj->areas); 869 void *ctx = a->pgt->ctx; 870 871 do { 872 a = TAILQ_NEXT(a, fobj_link); 873 if (!a) 874 return true; 875 } while (a->pgt->ctx == ctx); 876 877 return false; 878 } 879 880 bool tee_pager_set_uta_area_attr(struct user_ta_ctx *utc, vaddr_t base, 881 size_t size, uint32_t flags) 882 { 883 bool ret = false; 884 vaddr_t b = base; 885 size_t s = size; 886 size_t s2 = 0; 887 struct tee_pager_area *area = find_area(utc->areas, b); 888 uint32_t exceptions = 0; 889 struct tee_pager_pmem *pmem = NULL; 890 uint32_t a = 0; 891 uint32_t f = 0; 892 uint32_t mattr = 0; 893 uint32_t f2 = 0; 894 size_t tblidx = 0; 895 896 f = (flags & TEE_MATTR_URWX) | TEE_MATTR_UR | TEE_MATTR_PR; 897 if (f & TEE_MATTR_UW) 898 f |= TEE_MATTR_PW; 899 mattr = get_area_mattr(f); 900 901 exceptions = pager_lock_check_stack(SMALL_PAGE_SIZE); 902 903 while (s) { 904 s2 = MIN(CORE_MMU_PGDIR_SIZE - (b & CORE_MMU_PGDIR_MASK), s); 905 if (!area || area->base != b || area->size != s2) { 906 ret = false; 907 goto out; 908 } 909 b += s2; 910 s -= s2; 911 912 if (area->flags == f) 913 goto next_area; 914 915 TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) { 916 if (!pmem_is_covered_by_area(pmem, area)) 917 continue; 918 919 tblidx = pmem_get_area_tblidx(pmem, area); 920 area_get_entry(area, tblidx, NULL, &a); 921 if (a == f) 922 continue; 923 area_set_entry(area, tblidx, 0, 0); 924 tlbi_mva_allasid(area_idx2va(area, tblidx)); 925 926 pmem->flags &= ~PMEM_FLAG_HIDDEN; 927 if (pmem_is_dirty(pmem)) 928 f2 = mattr; 929 else 930 f2 = mattr & ~(TEE_MATTR_UW | TEE_MATTR_PW); 931 area_set_entry(area, tblidx, get_pmem_pa(pmem), f2); 932 if (!(a & TEE_MATTR_VALID_BLOCK)) 933 pgt_inc_used_entries(area->pgt); 934 /* 935 * Make sure the table update is visible before 936 * continuing. 937 */ 938 dsb_ishst(); 939 940 /* 941 * Here's a problem if this page already is shared. 942 * We need do icache invalidate for each context 943 * in which it is shared. In practice this will 944 * never happen. 945 */ 946 if (flags & TEE_MATTR_UX) { 947 void *va = (void *)area_idx2va(area, tblidx); 948 949 /* Assert that the pmem isn't shared. */ 950 assert(same_context(pmem)); 951 952 dcache_clean_range_pou(va, SMALL_PAGE_SIZE); 953 cache_op_inner(ICACHE_INVALIDATE, NULL, 0); 954 } 955 } 956 957 area->flags = f; 958 next_area: 959 area = TAILQ_NEXT(area, link); 960 } 961 962 ret = true; 963 out: 964 pager_unlock(exceptions); 965 return ret; 966 } 967 KEEP_PAGER(tee_pager_set_uta_area_attr); 968 #endif /*CFG_PAGED_USER_TA*/ 969 970 void tee_pager_invalidate_fobj(struct fobj *fobj) 971 { 972 struct tee_pager_pmem *pmem; 973 uint32_t exceptions; 974 975 exceptions = pager_lock_check_stack(64); 976 977 TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) { 978 if (pmem->fobj == fobj) { 979 pmem->fobj = NULL; 980 pmem->fobj_pgidx = INVALID_PGIDX; 981 } 982 } 983 984 pager_unlock(exceptions); 985 } 986 KEEP_PAGER(tee_pager_invalidate_fobj); 987 988 static struct tee_pager_pmem *pmem_find(struct tee_pager_area *area, 989 unsigned int tblidx) 990 { 991 struct tee_pager_pmem *pmem = NULL; 992 993 TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) 994 if (pmem->fobj == area->fobj && 995 pmem_get_area_tblidx(pmem, area) == tblidx) 996 return pmem; 997 998 return NULL; 999 } 1000 1001 static bool tee_pager_unhide_page(struct tee_pager_area *area, 1002 unsigned int tblidx) 1003 { 1004 struct tee_pager_pmem *pmem = pmem_find(area, tblidx); 1005 uint32_t a = get_area_mattr(area->flags); 1006 uint32_t attr = 0; 1007 1008 if (!pmem) 1009 return false; 1010 1011 area_get_entry(area, tblidx, NULL, &attr); 1012 if (attr & TEE_MATTR_VALID_BLOCK) 1013 return false; 1014 1015 /* page is hidden, show and move to back */ 1016 1017 /* If it's not a dirty block, then it should be read only. */ 1018 if (!pmem_is_dirty(pmem)) 1019 a &= ~(TEE_MATTR_PW | TEE_MATTR_UW); 1020 1021 pmem->flags &= ~PMEM_FLAG_HIDDEN; 1022 area_set_entry(area, tblidx, get_pmem_pa(pmem), a); 1023 pgt_inc_used_entries(area->pgt); 1024 /* 1025 * Note that TLB invalidation isn't needed since 1026 * there wasn't a valid mapping before. We should 1027 * use a barrier though, to make sure that the 1028 * change is visible. 1029 */ 1030 dsb_ishst(); 1031 1032 TAILQ_REMOVE(&tee_pager_pmem_head, pmem, link); 1033 TAILQ_INSERT_TAIL(&tee_pager_pmem_head, pmem, link); 1034 incr_hidden_hits(); 1035 return true; 1036 } 1037 1038 static void tee_pager_hide_pages(void) 1039 { 1040 struct tee_pager_pmem *pmem = NULL; 1041 size_t n = 0; 1042 1043 TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) { 1044 if (n >= TEE_PAGER_NHIDE) 1045 break; 1046 n++; 1047 1048 /* we cannot hide pages when pmem->fobj is not defined. */ 1049 if (!pmem->fobj) 1050 continue; 1051 1052 if (pmem_is_hidden(pmem)) 1053 continue; 1054 1055 pmem->flags |= PMEM_FLAG_HIDDEN; 1056 pmem_unmap(pmem, NULL); 1057 } 1058 } 1059 1060 /* 1061 * Find mapped pmem, hide and move to pageble pmem. 1062 * Return false if page was not mapped, and true if page was mapped. 1063 */ 1064 static bool tee_pager_release_one_phys(struct tee_pager_area *area, 1065 vaddr_t page_va) 1066 { 1067 struct tee_pager_pmem *pmem; 1068 size_t tblidx = 0; 1069 size_t pgidx = area_va2idx(area, page_va) + area->fobj_pgoffs - 1070 ((area->base & CORE_MMU_PGDIR_MASK) >> SMALL_PAGE_SHIFT); 1071 1072 TAILQ_FOREACH(pmem, &tee_pager_lock_pmem_head, link) { 1073 if (pmem->fobj != area->fobj || pmem->fobj_pgidx != pgidx) 1074 continue; 1075 1076 /* 1077 * Locked pages may not be shared, these two asserts checks 1078 * that there's only a signed area recorded with this pmem. 1079 */ 1080 assert(TAILQ_FIRST(&pmem->fobj->areas) == area); 1081 assert(TAILQ_LAST(&pmem->fobj->areas, 1082 tee_pager_area_head) == area); 1083 1084 tblidx = pmem_get_area_tblidx(pmem, area); 1085 area_set_entry(area, tblidx, 0, 0); 1086 pgt_dec_used_entries(area->pgt); 1087 TAILQ_REMOVE(&tee_pager_lock_pmem_head, pmem, link); 1088 pmem->fobj = NULL; 1089 pmem->fobj_pgidx = INVALID_PGIDX; 1090 tee_pager_npages++; 1091 set_npages(); 1092 TAILQ_INSERT_HEAD(&tee_pager_pmem_head, pmem, link); 1093 incr_zi_released(); 1094 return true; 1095 } 1096 1097 return false; 1098 } 1099 1100 /* Finds the oldest page and unmaps it from all tables */ 1101 static struct tee_pager_pmem *tee_pager_get_page(enum tee_pager_area_type at) 1102 { 1103 struct tee_pager_pmem *pmem; 1104 1105 pmem = TAILQ_FIRST(&tee_pager_pmem_head); 1106 if (!pmem) { 1107 EMSG("No pmem entries"); 1108 return NULL; 1109 } 1110 1111 if (pmem->fobj) { 1112 pmem_unmap(pmem, NULL); 1113 tee_pager_save_page(pmem); 1114 } 1115 1116 TAILQ_REMOVE(&tee_pager_pmem_head, pmem, link); 1117 pmem->fobj = NULL; 1118 pmem->fobj_pgidx = INVALID_PGIDX; 1119 pmem->flags = 0; 1120 if (at == PAGER_AREA_TYPE_LOCK) { 1121 /* Move page to lock list */ 1122 if (tee_pager_npages <= 0) 1123 panic("running out of page"); 1124 tee_pager_npages--; 1125 set_npages(); 1126 TAILQ_INSERT_TAIL(&tee_pager_lock_pmem_head, pmem, link); 1127 } else { 1128 /* move page to back */ 1129 TAILQ_INSERT_TAIL(&tee_pager_pmem_head, pmem, link); 1130 } 1131 1132 return pmem; 1133 } 1134 1135 static bool pager_update_permissions(struct tee_pager_area *area, 1136 struct abort_info *ai, bool *handled) 1137 { 1138 unsigned int pgidx = area_va2idx(area, ai->va); 1139 struct tee_pager_pmem *pmem = NULL; 1140 uint32_t attr = 0; 1141 paddr_t pa = 0; 1142 1143 *handled = false; 1144 1145 area_get_entry(area, pgidx, &pa, &attr); 1146 1147 /* Not mapped */ 1148 if (!(attr & TEE_MATTR_VALID_BLOCK)) 1149 return false; 1150 1151 /* Not readable, should not happen */ 1152 if (abort_is_user_exception(ai)) { 1153 if (!(attr & TEE_MATTR_UR)) 1154 return true; 1155 } else { 1156 if (!(attr & TEE_MATTR_PR)) { 1157 abort_print_error(ai); 1158 panic(); 1159 } 1160 } 1161 1162 switch (core_mmu_get_fault_type(ai->fault_descr)) { 1163 case CORE_MMU_FAULT_TRANSLATION: 1164 case CORE_MMU_FAULT_READ_PERMISSION: 1165 if (ai->abort_type == ABORT_TYPE_PREFETCH) { 1166 /* Check attempting to execute from an NOX page */ 1167 if (abort_is_user_exception(ai)) { 1168 if (!(attr & TEE_MATTR_UX)) 1169 return true; 1170 } else { 1171 if (!(attr & TEE_MATTR_PX)) { 1172 abort_print_error(ai); 1173 panic(); 1174 } 1175 } 1176 } 1177 /* Since the page is mapped now it's OK */ 1178 break; 1179 case CORE_MMU_FAULT_WRITE_PERMISSION: 1180 /* Check attempting to write to an RO page */ 1181 pmem = pmem_find(area, pgidx); 1182 if (!pmem) 1183 panic(); 1184 if (abort_is_user_exception(ai)) { 1185 if (!(area->flags & TEE_MATTR_UW)) 1186 return true; 1187 if (!(attr & TEE_MATTR_UW)) { 1188 FMSG("Dirty %p", 1189 (void *)(ai->va & ~SMALL_PAGE_MASK)); 1190 pmem->flags |= PMEM_FLAG_DIRTY; 1191 area_set_entry(area, pgidx, pa, 1192 get_area_mattr(area->flags)); 1193 tlbi_mva_allasid(ai->va & ~SMALL_PAGE_MASK); 1194 } 1195 1196 } else { 1197 if (!(area->flags & TEE_MATTR_PW)) { 1198 abort_print_error(ai); 1199 panic(); 1200 } 1201 if (!(attr & TEE_MATTR_PW)) { 1202 FMSG("Dirty %p", 1203 (void *)(ai->va & ~SMALL_PAGE_MASK)); 1204 pmem->flags |= PMEM_FLAG_DIRTY; 1205 area_set_entry(area, pgidx, pa, 1206 get_area_mattr(area->flags)); 1207 tlbi_mva_allasid(ai->va & ~SMALL_PAGE_MASK); 1208 } 1209 } 1210 /* Since permissions has been updated now it's OK */ 1211 break; 1212 default: 1213 /* Some fault we can't deal with */ 1214 if (abort_is_user_exception(ai)) 1215 return true; 1216 abort_print_error(ai); 1217 panic(); 1218 } 1219 *handled = true; 1220 return true; 1221 } 1222 1223 #ifdef CFG_TEE_CORE_DEBUG 1224 static void stat_handle_fault(void) 1225 { 1226 static size_t num_faults; 1227 static size_t min_npages = SIZE_MAX; 1228 static size_t total_min_npages = SIZE_MAX; 1229 1230 num_faults++; 1231 if ((num_faults % 1024) == 0 || tee_pager_npages < total_min_npages) { 1232 DMSG("nfaults %zu npages %zu (min %zu)", 1233 num_faults, tee_pager_npages, min_npages); 1234 min_npages = tee_pager_npages; /* reset */ 1235 } 1236 if (tee_pager_npages < min_npages) 1237 min_npages = tee_pager_npages; 1238 if (tee_pager_npages < total_min_npages) 1239 total_min_npages = tee_pager_npages; 1240 } 1241 #else 1242 static void stat_handle_fault(void) 1243 { 1244 } 1245 #endif 1246 1247 bool tee_pager_handle_fault(struct abort_info *ai) 1248 { 1249 struct tee_pager_area *area; 1250 vaddr_t page_va = ai->va & ~SMALL_PAGE_MASK; 1251 uint32_t exceptions; 1252 bool ret; 1253 1254 #ifdef TEE_PAGER_DEBUG_PRINT 1255 if (!abort_is_user_exception(ai)) 1256 abort_print(ai); 1257 #endif 1258 1259 /* 1260 * We're updating pages that can affect several active CPUs at a 1261 * time below. We end up here because a thread tries to access some 1262 * memory that isn't available. We have to be careful when making 1263 * that memory available as other threads may succeed in accessing 1264 * that address the moment after we've made it available. 1265 * 1266 * That means that we can't just map the memory and populate the 1267 * page, instead we use the aliased mapping to populate the page 1268 * and once everything is ready we map it. 1269 */ 1270 exceptions = pager_lock(ai); 1271 1272 stat_handle_fault(); 1273 1274 /* check if the access is valid */ 1275 if (abort_is_user_exception(ai)) { 1276 area = find_uta_area(ai->va); 1277 1278 } else { 1279 area = find_area(&tee_pager_area_head, ai->va); 1280 if (!area) 1281 area = find_uta_area(ai->va); 1282 } 1283 if (!area || !area->pgt) { 1284 ret = false; 1285 goto out; 1286 } 1287 1288 if (!tee_pager_unhide_page(area, area_va2idx(area, page_va))) { 1289 struct tee_pager_pmem *pmem = NULL; 1290 uint32_t attr = 0; 1291 paddr_t pa = 0; 1292 size_t tblidx = 0; 1293 1294 /* 1295 * The page wasn't hidden, but some other core may have 1296 * updated the table entry before we got here or we need 1297 * to make a read-only page read-write (dirty). 1298 */ 1299 if (pager_update_permissions(area, ai, &ret)) { 1300 /* 1301 * Nothing more to do with the abort. The problem 1302 * could already have been dealt with from another 1303 * core or if ret is false the TA will be paniced. 1304 */ 1305 goto out; 1306 } 1307 1308 pmem = tee_pager_get_page(area->type); 1309 if (!pmem) { 1310 abort_print(ai); 1311 panic(); 1312 } 1313 1314 /* load page code & data */ 1315 tee_pager_load_page(area, page_va, pmem->va_alias); 1316 1317 1318 pmem->fobj = area->fobj; 1319 pmem->fobj_pgidx = area_va2idx(area, page_va) + 1320 area->fobj_pgoffs - 1321 ((area->base & CORE_MMU_PGDIR_MASK) >> 1322 SMALL_PAGE_SHIFT); 1323 tblidx = pmem_get_area_tblidx(pmem, area); 1324 attr = get_area_mattr(area->flags); 1325 /* 1326 * Pages from PAGER_AREA_TYPE_RW starts read-only to be 1327 * able to tell when they are updated and should be tagged 1328 * as dirty. 1329 */ 1330 if (area->type == PAGER_AREA_TYPE_RW) 1331 attr &= ~(TEE_MATTR_PW | TEE_MATTR_UW); 1332 pa = get_pmem_pa(pmem); 1333 1334 /* 1335 * We've updated the page using the aliased mapping and 1336 * some cache maintenence is now needed if it's an 1337 * executable page. 1338 * 1339 * Since the d-cache is a Physically-indexed, 1340 * physically-tagged (PIPT) cache we can clean either the 1341 * aliased address or the real virtual address. In this 1342 * case we choose the real virtual address. 1343 * 1344 * The i-cache can also be PIPT, but may be something else 1345 * too like VIPT. The current code requires the caches to 1346 * implement the IVIPT extension, that is: 1347 * "instruction cache maintenance is required only after 1348 * writing new data to a physical address that holds an 1349 * instruction." 1350 * 1351 * To portably invalidate the icache the page has to 1352 * be mapped at the final virtual address but not 1353 * executable. 1354 */ 1355 if (area->flags & (TEE_MATTR_PX | TEE_MATTR_UX)) { 1356 uint32_t mask = TEE_MATTR_PX | TEE_MATTR_UX | 1357 TEE_MATTR_PW | TEE_MATTR_UW; 1358 void *va = (void *)page_va; 1359 1360 /* Set a temporary read-only mapping */ 1361 area_set_entry(area, tblidx, pa, attr & ~mask); 1362 tlbi_mva_allasid(page_va); 1363 1364 dcache_clean_range_pou(va, SMALL_PAGE_SIZE); 1365 cache_op_inner(ICACHE_INVALIDATE, NULL, 0); 1366 1367 /* Set the final mapping */ 1368 area_set_entry(area, tblidx, pa, attr); 1369 tlbi_mva_allasid(page_va); 1370 } else { 1371 area_set_entry(area, tblidx, pa, attr); 1372 /* 1373 * No need to flush TLB for this entry, it was 1374 * invalid. We should use a barrier though, to make 1375 * sure that the change is visible. 1376 */ 1377 dsb_ishst(); 1378 } 1379 pgt_inc_used_entries(area->pgt); 1380 1381 FMSG("Mapped 0x%" PRIxVA " -> 0x%" PRIxPA, page_va, pa); 1382 1383 } 1384 1385 tee_pager_hide_pages(); 1386 ret = true; 1387 out: 1388 pager_unlock(exceptions); 1389 return ret; 1390 } 1391 1392 void tee_pager_add_pages(vaddr_t vaddr, size_t npages, bool unmap) 1393 { 1394 size_t n; 1395 1396 DMSG("0x%" PRIxVA " - 0x%" PRIxVA " : %d", 1397 vaddr, vaddr + npages * SMALL_PAGE_SIZE, (int)unmap); 1398 1399 /* setup memory */ 1400 for (n = 0; n < npages; n++) { 1401 struct core_mmu_table_info *ti; 1402 struct tee_pager_pmem *pmem; 1403 vaddr_t va = vaddr + n * SMALL_PAGE_SIZE; 1404 unsigned int pgidx; 1405 paddr_t pa; 1406 uint32_t attr; 1407 1408 ti = find_table_info(va); 1409 pgidx = core_mmu_va2idx(ti, va); 1410 /* 1411 * Note that we can only support adding pages in the 1412 * valid range of this table info, currently not a problem. 1413 */ 1414 core_mmu_get_entry(ti, pgidx, &pa, &attr); 1415 1416 /* Ignore unmapped pages/blocks */ 1417 if (!(attr & TEE_MATTR_VALID_BLOCK)) 1418 continue; 1419 1420 pmem = calloc(1, sizeof(struct tee_pager_pmem)); 1421 if (!pmem) 1422 panic("out of mem"); 1423 1424 pmem->va_alias = pager_add_alias_page(pa); 1425 1426 if (unmap) { 1427 pmem->fobj = NULL; 1428 pmem->fobj_pgidx = INVALID_PGIDX; 1429 core_mmu_set_entry(ti, pgidx, 0, 0); 1430 pgt_dec_used_entries(find_core_pgt(va)); 1431 } else { 1432 struct tee_pager_area *area = NULL; 1433 1434 /* 1435 * The page is still mapped, let's assign the area 1436 * and update the protection bits accordingly. 1437 */ 1438 area = find_area(&tee_pager_area_head, va); 1439 assert(area && area->pgt == find_core_pgt(va)); 1440 pmem->fobj = area->fobj; 1441 pmem->fobj_pgidx = pgidx + area->fobj_pgoffs - 1442 ((area->base & 1443 CORE_MMU_PGDIR_MASK) >> 1444 SMALL_PAGE_SHIFT); 1445 assert(pgidx == pmem_get_area_tblidx(pmem, area)); 1446 assert(pa == get_pmem_pa(pmem)); 1447 area_set_entry(area, pgidx, pa, 1448 get_area_mattr(area->flags)); 1449 } 1450 1451 tee_pager_npages++; 1452 incr_npages_all(); 1453 set_npages(); 1454 TAILQ_INSERT_TAIL(&tee_pager_pmem_head, pmem, link); 1455 } 1456 1457 /* 1458 * As this is done at inits, invalidate all TLBs once instead of 1459 * targeting only the modified entries. 1460 */ 1461 tlbi_all(); 1462 } 1463 1464 #ifdef CFG_PAGED_USER_TA 1465 static struct pgt *find_pgt(struct pgt *pgt, vaddr_t va) 1466 { 1467 struct pgt *p = pgt; 1468 1469 while (p && (va & ~CORE_MMU_PGDIR_MASK) != p->vabase) 1470 p = SLIST_NEXT(p, link); 1471 return p; 1472 } 1473 1474 void tee_pager_assign_uta_tables(struct user_ta_ctx *utc) 1475 { 1476 struct tee_pager_area *area = NULL; 1477 struct pgt *pgt = NULL; 1478 1479 if (!utc->areas) 1480 return; 1481 1482 pgt = SLIST_FIRST(&thread_get_tsd()->pgt_cache); 1483 TAILQ_FOREACH(area, utc->areas, link) { 1484 if (!area->pgt) 1485 area->pgt = find_pgt(pgt, area->base); 1486 else 1487 assert(area->pgt == find_pgt(pgt, area->base)); 1488 if (!area->pgt) 1489 panic(); 1490 } 1491 } 1492 1493 void tee_pager_pgt_save_and_release_entries(struct pgt *pgt) 1494 { 1495 struct tee_pager_pmem *pmem = NULL; 1496 struct tee_pager_area *area = NULL; 1497 struct tee_pager_area_head *areas = NULL; 1498 uint32_t exceptions = pager_lock_check_stack(SMALL_PAGE_SIZE); 1499 1500 if (!pgt->num_used_entries) 1501 goto out; 1502 1503 TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) { 1504 if (pmem->fobj) 1505 pmem_unmap(pmem, pgt); 1506 } 1507 assert(!pgt->num_used_entries); 1508 1509 out: 1510 areas = to_user_ta_ctx(pgt->ctx)->areas; 1511 if (areas) { 1512 TAILQ_FOREACH(area, areas, link) { 1513 if (area->pgt == pgt) 1514 area->pgt = NULL; 1515 } 1516 } 1517 1518 pager_unlock(exceptions); 1519 } 1520 KEEP_PAGER(tee_pager_pgt_save_and_release_entries); 1521 #endif /*CFG_PAGED_USER_TA*/ 1522 1523 void tee_pager_release_phys(void *addr, size_t size) 1524 { 1525 bool unmaped = false; 1526 vaddr_t va = (vaddr_t)addr; 1527 vaddr_t begin = ROUNDUP(va, SMALL_PAGE_SIZE); 1528 vaddr_t end = ROUNDDOWN(va + size, SMALL_PAGE_SIZE); 1529 struct tee_pager_area *area; 1530 uint32_t exceptions; 1531 1532 if (end <= begin) 1533 return; 1534 1535 exceptions = pager_lock_check_stack(128); 1536 1537 for (va = begin; va < end; va += SMALL_PAGE_SIZE) { 1538 area = find_area(&tee_pager_area_head, va); 1539 if (!area) 1540 panic(); 1541 unmaped |= tee_pager_release_one_phys(area, va); 1542 } 1543 1544 if (unmaped) 1545 tlbi_mva_range(begin, end - begin, SMALL_PAGE_SIZE); 1546 1547 pager_unlock(exceptions); 1548 } 1549 KEEP_PAGER(tee_pager_release_phys); 1550 1551 void *tee_pager_alloc(size_t size) 1552 { 1553 tee_mm_entry_t *mm = NULL; 1554 uint8_t *smem = NULL; 1555 size_t num_pages = 0; 1556 struct fobj *fobj = NULL; 1557 1558 if (!size) 1559 return NULL; 1560 1561 mm = tee_mm_alloc(&tee_mm_vcore, ROUNDUP(size, SMALL_PAGE_SIZE)); 1562 if (!mm) 1563 return NULL; 1564 1565 smem = (uint8_t *)tee_mm_get_smem(mm); 1566 num_pages = tee_mm_get_bytes(mm) / SMALL_PAGE_SIZE; 1567 fobj = fobj_locked_paged_alloc(num_pages); 1568 if (!fobj) { 1569 tee_mm_free(mm); 1570 return NULL; 1571 } 1572 1573 tee_pager_add_core_area((vaddr_t)smem, PAGER_AREA_TYPE_LOCK, fobj); 1574 fobj_put(fobj); 1575 1576 asan_tag_access(smem, smem + num_pages * SMALL_PAGE_SIZE); 1577 1578 return smem; 1579 } 1580