/** * \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(); }
/** * Entry point called from boot.S for bootstrap processor. */ void arch_init(uint32_t board_id, struct atag *atag_base, lvaddr_t elf_file, lvaddr_t alloc_top) { // // Assumptions: // // - MMU and caches are enabled. No lockdowns in caches or TLB. // - Kernel has own section starting at KERNEL_OFFSET. // - Kernel section includes the highmem relocated exception vector table. // struct atag * ae = NULL; exceptions_init(); ae = atag_find(atag_base, ATAG_MEM); paging_map_memory(0, ae->u.mem.start, ae->u.mem.bytes); ae = atag_find(atag_base, ATAG_CMDLINE); if (ae != NULL) { parse_commandline(ae->u.cmdline.cmdline, cmdargs); tick_hz = CONSTRAIN(tick_hz, 10, 1000); } if (board_id == hal_get_board_id()) { errval_t errval; serial_console_init(true); // do not remove/change this printf: needed by regression harness printf("Barrelfish CPU driver starting on ARMv5 Board id 0x%08"PRIx32"\n", board_id); printf("The address of paging_map_kernel_section is %p\n", paging_map_kernel_section); errval = serial_debug_init(); if (err_is_fail(errval)) { printf("Failed to initialize debug port: %d", serial_debug_port); } debug(SUBSYS_STARTUP, "alloc_top %08"PRIxLVADDR" %08"PRIxLVADDR"\n", alloc_top, alloc_top - KERNEL_OFFSET); debug(SUBSYS_STARTUP, "elf_file %08"PRIxLVADDR"\n", elf_file); my_core_id = hal_get_cpu_id(); extern struct kcb bspkcb; memset(&bspkcb, 0, sizeof(bspkcb)); kcb_current = &bspkcb; pic_init(); pit_init(tick_hz); tsc_init(); ae = atag_find(atag_base, ATAG_MEM); // Add unused physical memory to memory map phys_mmap_t phys_mmap; // Kernel effectively consumes [0...alloc_top] // Add region above alloc_top with care to skip exception vector // page. if (alloc_top < ETABLE_ADDR) { phys_mmap_add(&phys_mmap, alloc_top - KERNEL_OFFSET, ETABLE_ADDR - KERNEL_OFFSET); } phys_mmap_add(&phys_mmap, ETABLE_ADDR - KERNEL_OFFSET + BASE_PAGE_SIZE, ae->u.mem.start + ae->u.mem.bytes); ae = atag_find(atag_base, ATAG_VIDEOLFB); if (NULL != ae) { // Remove frame buffer (if present). phys_mmap_remove(&phys_mmap, ae->u.videolfb.lfb_base, ae->u.videolfb.lfb_base + ae->u.videolfb.lfb_size); assert(!"Not supported"); } ae = atag_find(atag_base, ATAG_INITRD2); if (NULL != ae) { phys_mmap_remove(&phys_mmap, ae->u.initrd2.start, ae->u.initrd2.start + ae->u.initrd2.bytes); arm_kernel_startup(&phys_mmap, ae->u.initrd2.start, ae->u.initrd2.bytes); } else { panic("initrd not found\n"); } } else { panic("Mis-matched board id: [current %"PRIu32", kernel %"PRIu32"]", board_id, hal_get_board_id()); } }