void init_xlat_tables(void) { print_mmap(); init_xlation_table(mmap, 0, l1_xlation_table, 1); tcr_ps_bits = calc_physical_addr_size_bits(max_pa); assert(max_va < ADDR_SPACE_SIZE); }
static mmap_region_t *init_xlation_table(mmap_region_t *mm, unsigned long base_va, unsigned long *table, unsigned level) { unsigned level_size_shift = L1_XLAT_ADDRESS_SHIFT - (level - 1) * XLAT_TABLE_ENTRIES_SHIFT; unsigned level_size = 1 << level_size_shift; unsigned long level_index_mask = XLAT_TABLE_ENTRIES_MASK << level_size_shift; assert(level <= 3); debug_print("New xlat table:\n"); do { unsigned long desc = UNSET_DESC; if (mm->base_va + mm->size <= base_va) { /* Area now after the region so skip it */ ++mm; continue; } debug_print(" %010lx %8lx " + 6 - 2 * level, base_va, level_size); if (mm->base_va >= base_va + level_size) { /* Next region is after area so nothing to map yet */ desc = INVALID_DESC; } else if (mm->base_va <= base_va && mm->base_va + mm->size >= base_va + level_size) { /* Next region covers all of area */ int attr = mmap_region_attr(mm, base_va, level_size); if (attr >= 0) desc = mmap_desc(attr, base_va - mm->base_va + mm->base_pa, level); } /* else Next region only partially covers area, so need */ if (desc == UNSET_DESC) { /* Area not covered by a region so need finer table */ unsigned long *new_table = xlat_tables[next_xlat++]; assert(next_xlat <= MAX_XLAT_TABLES); desc = TABLE_DESC | (unsigned long)new_table; /* Recurse to fill in new table */ mm = init_xlation_table(mm, base_va, new_table, level+1); } debug_print("\n"); *table++ = desc; base_va += level_size; } while (mm->size && (base_va & level_index_mask)); return mm; }
void init_xlat_tables(void) { unsigned long long max_pa; uintptr_t max_va; print_mmap(); init_xlation_table(0, base_xlation_table, XLAT_TABLE_LEVEL_BASE, &max_va, &max_pa); tcr_ps_bits = calc_physical_addr_size_bits(max_pa); assert(max_va < ADDR_SPACE_SIZE); }
void init_xlat_tables(void) { unsigned long long max_pa; uintptr_t max_va; print_mmap(); init_xlation_table(0, base_xlation_table, XLAT_TABLE_LEVEL_BASE, &max_va, &max_pa); assert(max_va <= PLAT_VIRT_ADDR_SPACE_SIZE - 1); assert(max_pa <= PLAT_PHY_ADDR_SPACE_SIZE - 1); assert((PLAT_PHY_ADDR_SPACE_SIZE - 1) <= get_max_supported_pa()); tcr_ps_bits = calc_physical_addr_size_bits(max_pa); }
void core_init_mmu_tables(struct tee_mmap_region *mm) { paddr_t max_pa = 0; uint64_t max_va = 0; size_t n; for (n = 0; mm[n].size; n++) { paddr_t pa_end; vaddr_t va_end; debug_print(" %010" PRIxVA " %010" PRIxPA " %10zx %x", mm[n].va, mm[n].pa, mm[n].size, mm[n].attr); assert(IS_PAGE_ALIGNED(mm[n].pa)); assert(IS_PAGE_ALIGNED(mm[n].size)); pa_end = mm[n].pa + mm[n].size - 1; va_end = mm[n].va + mm[n].size - 1; if (pa_end > max_pa) max_pa = pa_end; if (va_end > max_va) max_va = va_end; } /* Clear table before use */ memset(l1_xlation_table[0], 0, NUM_L1_ENTRIES * XLAT_ENTRY_SIZE); init_xlation_table(mm, 0, l1_xlation_table[0], 1); for (n = 1; n < CFG_TEE_CORE_NB_CORE; n++) memcpy(l1_xlation_table[n], l1_xlation_table[0], XLAT_ENTRY_SIZE * NUM_L1_ENTRIES); for (n = 0; n < NUM_L1_ENTRIES; n++) { if (!l1_xlation_table[0][n]) { user_va_idx = n; break; } } assert(user_va_idx != -1); tcr_ps_bits = calc_physical_addr_size_bits(max_pa); COMPILE_TIME_ASSERT(ADDR_SPACE_SIZE > 0); assert(max_va < ADDR_SPACE_SIZE); }
void init_xlat_tables(void) { print_mmap(); init_xlation_table(mmap, 0, l1_xlation_table, 1); }
static struct tee_mmap_region *init_xlation_table(struct tee_mmap_region *mm, uint64_t base_va, uint64_t *table, unsigned level) { unsigned level_size_shift = L1_XLAT_ADDRESS_SHIFT - (level - 1) * XLAT_TABLE_ENTRIES_SHIFT; unsigned level_size = 1 << level_size_shift; uint64_t level_index_mask = XLAT_TABLE_ENTRIES_MASK << level_size_shift; assert(level <= 3); debug_print("New xlat table (level %u):", level); do { uint64_t desc = UNSET_DESC; if (mm->va + mm->size <= base_va) { /* Area now after the region so skip it */ mm++; continue; } if (mm->va >= base_va + level_size) { /* Next region is after area so nothing to map yet */ desc = INVALID_DESC; debug_print("%*s%010" PRIx64 " %8x", level * 2, "", base_va, level_size); } else if (mm->va <= base_va && mm->va + mm->size >= base_va + level_size) { /* Next region covers all of area */ int attr = mmap_region_attr(mm, base_va, level_size); if (attr >= 0) { desc = mmap_desc(attr, base_va - mm->va + mm->pa, level); debug_print("%*s%010" PRIx64 " %8x %s-%s-%s-%s", level * 2, "", base_va, level_size, attr & (TEE_MATTR_CACHE_CACHED << TEE_MATTR_CACHE_SHIFT) ? "MEM" : "DEV", attr & TEE_MATTR_PW ? "RW" : "RO", attr & TEE_MATTR_PX ? "X" : "XN", attr & TEE_MATTR_SECURE ? "S" : "NS"); } else { debug_print("%*s%010" PRIx64 " %8x", level * 2, "", base_va, level_size); } } /* else Next region only partially covers area, so need */ if (desc == UNSET_DESC) { /* Area not covered by a region so need finer table */ uint64_t *new_table = xlat_tables[next_xlat++]; /* Clear table before use */ memset(new_table, 0, XLAT_TABLE_SIZE); assert(next_xlat <= MAX_XLAT_TABLES); desc = TABLE_DESC | (uint64_t)(uintptr_t)new_table; /* Recurse to fill in new table */ mm = init_xlation_table(mm, base_va, new_table, level + 1); } *table++ = desc; base_va += level_size; } while (mm->size && (base_va & level_index_mask)); return mm; }