static void set_region(struct core_mmu_table_info *tbl_info, struct tee_mmap_region *region) { unsigned end; unsigned idx; paddr_t pa; /* va, len and pa should be block aligned */ assert(!core_mmu_get_block_offset(tbl_info, region->va)); assert(!core_mmu_get_block_offset(tbl_info, region->size)); assert(!core_mmu_get_block_offset(tbl_info, region->pa)); idx = core_mmu_va2idx(tbl_info, region->va); end = core_mmu_va2idx(tbl_info, region->va + region->size); pa = region->pa; debug_print("set_region va %016" PRIxVA " pa %016" PRIxPA " size %016zu", region->va, region->pa, region->size); while (idx < end) { core_mmu_set_entry(tbl_info, idx, pa, region->attr); idx++; pa += 1 << tbl_info->shift; } }
static TEE_Result tee_mmu_kmap_va2pa_attr(void *va, void **pa, uint32_t *attr) { struct core_mmu_table_info tbl_info; size_t block_offset; size_t n; paddr_t npa; uint32_t nattr; if (!core_mmu_find_table(TEE_MMU_KMAP_START_VA, UINT_MAX, &tbl_info)) panic(); if (!tee_mm_addr_is_within_range(&tee_mmu_virt_kmap, (vaddr_t)va)) return TEE_ERROR_ACCESS_DENIED; n = core_mmu_va2idx(&tbl_info, (vaddr_t)va); core_mmu_get_entry(&tbl_info, n, &npa, &nattr); if (!(nattr & TEE_MATTR_VALID_BLOCK)) return TEE_ERROR_ACCESS_DENIED; block_offset = core_mmu_get_block_offset(&tbl_info, (vaddr_t)va); *pa = (void *)(npa + block_offset); if (attr) *attr = nattr; return TEE_SUCCESS; }
TEE_Result tee_mmu_kmap_helper(tee_paddr_t pa, size_t len, void **va) { tee_mm_entry_t *mm; uint32_t attr; struct core_mmu_table_info tbl_info; uint32_t pa_s; uint32_t pa_e; size_t n; size_t offs; if (!core_mmu_find_table(TEE_MMU_KMAP_START_VA, UINT_MAX, &tbl_info)) panic(); pa_s = ROUNDDOWN(pa, 1 << tbl_info.shift); pa_e = ROUNDUP(pa + len, 1 << tbl_info.shift); mm = tee_mm_alloc(&tee_mmu_virt_kmap, pa_e - pa_s); if (!mm) return TEE_ERROR_OUT_OF_MEMORY; attr = TEE_MATTR_VALID_BLOCK | TEE_MATTR_PRW | TEE_MATTR_GLOBAL; if (tee_pbuf_is_sec(pa, len)) { attr |= TEE_MATTR_SECURE; attr |= TEE_MATTR_I_WRITE_BACK | TEE_MATTR_O_WRITE_BACK; } else if (tee_pbuf_is_non_sec(pa, len)) { if (core_mmu_is_shm_cached()) attr |= TEE_MATTR_I_WRITE_BACK | TEE_MATTR_O_WRITE_BACK; } else return TEE_ERROR_GENERIC; offs = (tee_mm_get_smem(mm) - tbl_info.va_base) >> tbl_info.shift; for (n = 0; n < tee_mm_get_size(mm); n++) core_mmu_set_entry(&tbl_info, n + offs, pa_s + (n << tbl_info.shift), attr); core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0); *va = (void *)(tee_mm_get_smem(mm) + core_mmu_get_block_offset(&tbl_info, pa)); return TEE_SUCCESS; }