1/* 2 * Copyright (c) 2016, ETH Zurich. 3 * Copyright (c) 2016, Hewlett Packard Enterprise Development LP. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <kernel.h> 11#include <serial.h> 12#include <offsets.h> 13#include <stdio.h> 14#include <stddef.h> 15#include <errno.h> 16 17#include <multiboot2.h> 18 19// parsing commandline arguments 20#include <getopt/getopt.h> 21 22#include <barrelfish_kpi/arm_core_data.h> 23 24#include <arch/arm/gic.h> 25#include <arch/armv8/arm_hal.h> 26#include <arch/armv8/init.h> 27#include <arch/armv8/exceptions.h> 28#include <arch/armv8/global.h> 29#include <arch/armv8/startup_arch.h> 30#include <efi.h> 31#include <sysreg.h> 32#include <arch/armv8/kernel_multiboot2.h> 33#include <arch/armv8/paging_kernel_arch.h> 34#include <arch/armv8/platform.h> 35#include <systime.h> 36#include <coreboot.h> 37 38static struct global global_temp; 39 40/* 41 * Need to be initialized during kernel loading. 42 */ 43struct armv8_core_data *armv8_glbl_core_data = NULL; 44 45lpaddr_t kernel_stack = 0; 46lpaddr_t kernel_stack_top = 0; 47 48#define MSG(format, ...) printk( LOG_NOTE, "ARMv8-A: "format, ## __VA_ARGS__ ) 49 50/* 51 * parsing of command line arguments 52 */ 53static struct cmdarg cmdargs[] = { 54 {"loglevel", ArgType_Int, { .integer = &kernel_loglevel }}, 55 {"logmask", ArgType_Int, { .integer = &kernel_log_subsystem_mask }}, 56 {"ticks", ArgType_Bool, { .boolean = &kernel_ticks_enabled }}, 57 {"timeslice", ArgType_UInt, { .uinteger = &config_timeslice }}, 58 {"serial", ArgType_ULong, { .ulonginteger = &uart_base[0] }}, 59 {"gic", ArgType_ULong, { .ulonginteger = &platform_gic_cpu_base }}, 60 {"gicdist", ArgType_ULong, { .ulonginteger = &platform_gic_dist_base }}, 61 {"gicredist", ArgType_ULong, { .ulonginteger = &platform_gic_redist_base }}, 62 {NULL, 0, {NULL}} 63}; 64 65static void mmap_find_memory(struct multiboot_tag_efi_mmap *mmap) 66{ 67 lpaddr_t physical_mem = 0; 68 uint64_t pages = ARMV8_CORE_DATA_PAGES; 69 70 for (size_t i = 0; i < mmap->size; i += mmap->descr_size) { 71 efi_memory_descriptor *desc = (efi_memory_descriptor *)(mmap->efi_mmap + i); 72 if (desc->Type == EfiConventionalMemory && desc->NumberOfPages > pages) { 73 physical_mem = ROUND_UP(desc->PhysicalStart, BASE_PAGE_SIZE); 74 pages = desc->NumberOfPages; 75 } 76 } 77 78 if (!physical_mem) { 79 panic("No free memory found!\n"); 80 } 81 82 armv8_glbl_core_data = (void*) local_phys_to_mem(physical_mem); 83 armv8_glbl_core_data->start_kernel_ram = physical_mem; 84 armv8_glbl_core_data->start_free_ram = physical_mem + sizeof(*armv8_glbl_core_data); 85 86 global = (void*) local_phys_to_mem(armv8_glbl_core_data->start_free_ram); 87 88 // Construct the global structure 89 memset(&global->locks, 0, sizeof(global->locks)); 90 91 armv8_glbl_core_data->start_free_ram += sizeof(*global); 92 armv8_glbl_core_data->start_free_ram = ROUND_UP(armv8_glbl_core_data->start_free_ram, BASE_PAGE_SIZE); 93 94} 95 96bool cpu_is_bsp(void) 97{ 98 /* xxx: assumes the coreid to be set */ 99 return (my_core_id == 0); 100} 101 102bool arch_core_is_bsp(void) 103{ 104 return cpu_is_bsp(); 105} 106 107/** 108 * @param Entry point to architecture specific initialization 109 * 110 * @param magic Magic value to tell the kernel it was started by multiboot 111 * @param pointer Pointer to the multiboot structure 112 * @param stack Pointer to the stack 113 * 114 * ASSUMPTIONS: 115 * - the execution starts in HIGH addresses (e.g. > KERNEL_OFFSET) 116 * - Pointers to stack and multiboot structures point to HIGH memory 117 * - ARM exception level is EL1 (privileged) 118 */ 119void 120arch_init(uint32_t magic, void *pointer, uintptr_t stack) { 121 global = &global_temp; 122 memset(&global->locks, 0, sizeof(global->locks)); 123 124 switch (magic) { 125 case MULTIBOOT2_BOOTLOADER_MAGIC: 126 { 127 my_core_id = 0; 128 129 struct multiboot_header *mbhdr = pointer; 130 uint32_t size = mbhdr->header_length; 131 132 // sanity checks 133 assert(mbhdr->architecture == MULTIBOOT_ARCHITECTURE_AARCH64); 134 assert((mbhdr->architecture + mbhdr->checksum + mbhdr->header_length 135 + mbhdr->magic) == 0); 136 137 struct multiboot_header_tag *mb; 138 struct multiboot_tag_string *kernel_cmd; 139 140 // get the first header tag 141 mb = (struct multiboot_header_tag *)(mbhdr + 1); 142 143 // get the kernel cmdline. this may contain address which UART/GIC to use 144 kernel_cmd = multiboot2_find_cmdline(mb, size); 145 if (kernel_cmd == NULL) { 146 panic("Multiboot did not contain an kernel CMD line\n"); 147 } 148 149 // parse the cmdline 150 parse_commandline(kernel_cmd->string, cmdargs); 151 152 // initialize the serial console. 153 serial_init(serial_console_port, false); 154// serial_console_init(false); 155 156 struct multiboot_tag_efi_mmap *mmap = (struct multiboot_tag_efi_mmap *) 157 multiboot2_find_header(mb, size, MULTIBOOT_TAG_TYPE_EFI_MMAP); 158 if (!mmap) { 159 panic("Multiboot image does not have EFI mmap!"); 160 } else { 161 printf("Found EFI mmap: %p\n", mmap); 162 } 163 164 mmap_find_memory(mmap); 165 166 armv8_glbl_core_data->multiboot_image.base = mem_to_local_phys((lvaddr_t) mb); 167 armv8_glbl_core_data->multiboot_image.length = size; 168 armv8_glbl_core_data->efi_mmap = mem_to_local_phys((lvaddr_t) mmap); 169 170 armv8_glbl_core_data->cpu_driver_stack = stack; 171 172 kernel_stack = stack; 173 kernel_stack_top = stack + 16 - KERNEL_STACK_SIZE; 174 break; 175 } 176 case ARMV8_BOOTMAGIC_PSCI : 177 //serial_init(serial_console_port, false); 178 179 serial_init(serial_console_port, false); 180 181 struct armv8_core_data *core_data = (struct armv8_core_data*)pointer; 182 armv8_glbl_core_data = core_data; 183 global = (struct global *)core_data->cpu_driver_globals_pointer; 184 185 kernel_stack = stack; 186 kernel_stack_top = local_phys_to_mem(core_data->cpu_driver_stack_limit); 187 188 my_core_id = core_data->dst_core_id; 189 190 MSG("ARMv8 Core magic...\n"); 191 192 break; 193 default: { 194 serial_init(serial_console_port, false); 195 196 serial_console_putchar('x'); 197 serial_console_putchar('x'); 198 serial_console_putchar('\n'); 199 200 panic("Implement AP booting!"); 201 __asm volatile ("wfi":::); 202 break; 203 } 204 } 205 206 207 MSG("Barrelfish CPU driver starting on ARMv8\n"); 208 MSG("Global data at %p\n", global); 209 MSG("Multiboot record at %p\n", pointer); 210 MSG("Kernel stack at 0x%016" PRIxPTR ".. 0x%016" PRIxPTR "\n", 211 kernel_stack_top, kernel_stack); 212 MSG("Kernel first byte at 0x%" PRIxPTR "\n", &kernel_first_byte); 213 214 MSG("Exception vectors (VBAR_EL1): %p\n", &vectors); 215 sysreg_write_vbar_el1((uint64_t)&vectors); 216 217 MSG("Setting coreboot spawn handler\n"); 218 coreboot_set_spawn_handler(CPU_ARM8, platform_boot_core); 219 220 arm_kernel_startup(pointer); 221 while (1) { 222 __asm volatile ("wfi":::); 223 } 224} 225