/** * @param Entry point to architecture specific initialization * * @param magic Magic value to tell the kernel it was started by multiboot * @param pointer Pointer to the multiboot structure * @param stack Pointer to the stack * * ASSUMPTIONS: * - the execution starts in HIGH addresses (e.g. > KERNEL_OFFSET) * - Pointers to stack and multiboot structures point to HIGH memory * - ARM exception level is EL1 (privileged) */ void arch_init(uint32_t magic, void *pointer, uintptr_t stack) { global = &global_temp; memset(&global->locks, 0, sizeof(global->locks)); switch (magic) { case MULTIBOOT2_BOOTLOADER_MAGIC: { my_core_id = 0; struct multiboot_header *mbhdr = pointer; uint32_t size = mbhdr->header_length; // sanity checks assert(mbhdr->architecture == MULTIBOOT_ARCHITECTURE_AARCH64); assert((mbhdr->architecture + mbhdr->checksum + mbhdr->header_length + mbhdr->magic) == 0); struct multiboot_header_tag *mb; struct multiboot_tag_string *kernel_cmd; // get the first header tag mb = (struct multiboot_header_tag *)(mbhdr + 1); // get the kernel cmdline. this may contain address which UART/GIC to use kernel_cmd = multiboot2_find_cmdline(mb, size); if (kernel_cmd == NULL) { panic("Multiboot did not contain an kernel CMD line\n"); } // parse the cmdline parse_commandline(kernel_cmd->string, cmdargs); // initialize the serial console. serial_init(serial_console_port, false); // serial_console_init(false); struct multiboot_tag_efi_mmap *mmap = (struct multiboot_tag_efi_mmap *) multiboot2_find_header(mb, size, MULTIBOOT_TAG_TYPE_EFI_MMAP); if (!mmap) { panic("Multiboot image does not have EFI mmap!"); } else { printf("Found EFI mmap: %p\n", mmap); } mmap_find_memory(mmap); armv8_glbl_core_data->multiboot_image.base = mem_to_local_phys((lvaddr_t) mb); armv8_glbl_core_data->multiboot_image.length = size; armv8_glbl_core_data->efi_mmap = mem_to_local_phys((lvaddr_t) mmap); armv8_glbl_core_data->cpu_driver_stack = stack; kernel_stack = stack; kernel_stack_top = stack + 16 - KERNEL_STACK_SIZE; break; } case ARMV8_BOOTMAGIC_PSCI : //serial_init(serial_console_port, false); serial_init(serial_console_port, false); struct armv8_core_data *core_data = (struct armv8_core_data*)pointer; armv8_glbl_core_data = core_data; global = (struct global *)core_data->cpu_driver_globals_pointer; kernel_stack = stack; kernel_stack_top = local_phys_to_mem(core_data->cpu_driver_stack_limit); my_core_id = core_data->dst_core_id; MSG("ARMv8 Core magic...\n"); break; default: { serial_init(serial_console_port, false); serial_console_putchar('x'); serial_console_putchar('x'); serial_console_putchar('\n'); panic("Implement AP booting!"); __asm volatile ("wfi":::); break; } } MSG("Barrelfish CPU driver starting on ARMv8\n"); MSG("Global data at %p\n", global); MSG("Multiboot record at %p\n", pointer); MSG("Kernel stack at 0x%016" PRIxPTR ".. 0x%016" PRIxPTR "\n", kernel_stack_top, kernel_stack); MSG("Kernel first byte at 0x%" PRIxPTR "\n", &kernel_first_byte); MSG("Exception vectors (VBAR_EL1): %p\n", &vectors); sysreg_write_vbar_el1((uint64_t)&vectors); MSG("Setting coreboot spawn handler\n"); coreboot_set_spawn_handler(CPU_ARM8, platform_boot_core); arm_kernel_startup(pointer); while (1) { __asm volatile ("wfi":::); } }
/** * 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()); } }