/** * \brief Reset kernel paging. * * This function resets the page maps for kernel and memory-space. It clears out * all other mappings. Use this only at system bootup! */ void paging_arm_reset(lpaddr_t paddr, size_t bytes) { // make sure kernel pagetable is aligned to 16K after relocation aligned_kernel_l1_table = (union arm_l1_entry *)ROUND_UP((uintptr_t)kernel_l1_table, ARM_L1_ALIGN); // make sure low l2 pagetable is aligned to 1K after relocation aligned_low_l2_table = (union arm_l2_entry *)ROUND_UP((uintptr_t)low_l2_table, ARM_L2_ALIGN); // Re-map physical memory paging_map_memory((uintptr_t)aligned_kernel_l1_table, paddr, bytes); // map first MB at granularity of 4K pages uint32_t l2_flags = ARM_L2_SMALL_USR_NONE | ARM_L2_SMALL_CACHEABLE | ARM_L2_SMALL_BUFFERABLE; paging_map_user_pages_l1((uintptr_t)aligned_kernel_l1_table, MEMORY_OFFSET, mem_to_local_phys((uintptr_t)aligned_low_l2_table)); for(lpaddr_t pa=0; pa < ARM_L1_SECTION_BYTES; pa += BYTES_PER_PAGE) { lvaddr_t va = pa + MEMORY_OFFSET; paging_set_l2_entry((uintptr_t *)&aligned_low_l2_table[ARM_L2_OFFSET(va)], pa, l2_flags); } // map high-mem relocated exception vector to corresponding page in low MB // core 0: 0xffff0000 -> 0x80000 // core 1: 0xffff0000 -> 0x81000 // ... paging_map_user_pages_l1((uintptr_t)aligned_kernel_l1_table, ETABLE_ADDR, mem_to_local_phys((uintptr_t)aligned_low_l2_table)); int core_id = hal_get_cpu_id(); lpaddr_t addr = ETABLE_PHYS_BASE + core_id * BASE_PAGE_SIZE; paging_set_l2_entry((uintptr_t *)&aligned_low_l2_table[ARM_L2_OFFSET(ETABLE_ADDR)], addr, l2_flags); cp15_write_ttbr1(mem_to_local_phys((uintptr_t)aligned_kernel_l1_table)); cp15_invalidate_tlb(); }
/** * Map frames into init process address space. Init has a contiguous set of * l2 entries so this is straightforward. * * @param l2_table pointer to init's L2 table. * @param l2_base virtual address represented by first L2 table entry * @param va_base virtual address to map. * @param pa_base physical address to associate with virtual address. * @param bytes number of bytes to map. * @param l2_flags ARM L2 small page flags for mapped pages. */ static void spawn_init_map(union arm_l2_entry* l2_table, lvaddr_t l2_base, lvaddr_t va_base, lpaddr_t pa_base, size_t bytes, uintptr_t l2_flags) { assert(va_base >= l2_base); assert(0 == (va_base & (BASE_PAGE_SIZE - 1))); assert(0 == (pa_base & (BASE_PAGE_SIZE - 1))); assert(0 == (bytes & (BASE_PAGE_SIZE - 1))); int bi = (va_base - l2_base) / BASE_PAGE_SIZE; int li = bi + bytes / BASE_PAGE_SIZE; while (bi < li) { paging_set_l2_entry((uintptr_t *)&l2_table[bi], pa_base, l2_flags); pa_base += BASE_PAGE_SIZE; bi++; } }