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, Universitaetstrasse 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/armv8/arm_hal.h> 25#include <arch/armv8/init.h> 26#include <arch/armv8/exceptions.h> 27#include <arch/armv8/global.h> 28#include <arch/armv8/startup_arch.h> 29#include <efi.h> 30#include <sysreg.h> 31#include <arch/armv8/kernel_multiboot2.h> 32#include <arch/armv8/paging_kernel_arch.h> 33#include <arch/arm/platform.h> 34#include <systime.h> 35#include <coreboot.h> 36#include <dev/armv8_dev.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 48const char *kernel_command_line; 49 50#define MSG(format, ...) printk( LOG_NOTE, "ARMv8-A: "format, ## __VA_ARGS__ ) 51 52/* 53 * parsing of command line arguments 54 */ 55static struct cmdarg cmdargs[] = { 56 {"loglevel", ArgType_Int, { .integer = &kernel_loglevel }}, 57 {"logmask", ArgType_Int, { .integer = &kernel_log_subsystem_mask }}, 58 {"ticks", ArgType_Bool, { .boolean = &kernel_ticks_enabled }}, 59 {"timeslice", ArgType_UInt, { .uinteger = &config_timeslice }}, 60 {"serial", ArgType_ULong, { .ulonginteger = &platform_uart_base[0] }}, 61 {NULL, 0, {NULL}} 62}; 63 64static void mmap_find_memory(struct multiboot_tag_efi_mmap *mmap) 65{ 66 lpaddr_t physical_mem = 0; 67 68 for (size_t i = 0; i < mmap->size; i += mmap->descr_size) { 69 efi_memory_descriptor *desc = (efi_memory_descriptor *)(mmap->efi_mmap + i); 70 if (desc->Type == EfiConventionalMemory && desc->NumberOfPages > ARMV8_CORE_DATA_PAGES) { 71 physical_mem = ROUND_UP(desc->PhysicalStart, BASE_PAGE_SIZE); 72 break; 73 } 74 } 75 76 if (!physical_mem) { 77 panic("No free memory found!\n"); 78 } 79 80 armv8_glbl_core_data->start_kernel_ram = physical_mem; 81 armv8_glbl_core_data->start_free_ram = physical_mem; 82 83 global = (void*) local_phys_to_mem(armv8_glbl_core_data->start_free_ram); 84 85 // Construct the global structure 86 memset(&global->locks, 0, sizeof(global->locks)); 87 88 armv8_glbl_core_data->start_free_ram += sizeof(*global); 89 armv8_glbl_core_data->start_free_ram = ROUND_UP(armv8_glbl_core_data->start_free_ram, BASE_PAGE_SIZE); 90 91} 92 93bool cpu_is_bsp(void) 94{ 95 /* xxx: assumes the coreid to be set */ 96 return (my_core_id == 0); 97} 98 99bool arch_core_is_bsp(void) 100{ 101 return cpu_is_bsp(); 102} 103 104/** 105 * @param Entry point to architecture specific initialization 106 * 107 * @param magic Magic value to tell the kernel it was started by multiboot 108 * @param pointer Pointer to the ARMv8 core data 109 * 110 * ASSUMPTIONS: 111 * - the execution starts in HIGH addresses (e.g. > KERNEL_OFFSET) 112 * - Pointers to stack and multiboot structures point to HIGH memory 113 * - ARM exception level is EL1 (privileged) 114 */ 115void 116arch_init(struct armv8_core_data *core_data) { 117 global = &global_temp; 118 memset(&global->locks, 0, sizeof(global->locks)); 119 120 armv8_glbl_core_data = core_data; 121 122 my_core_id = armv8_glbl_core_data->dst_core_id; 123 124 /* parse the cmdline */ 125 kernel_command_line = (const char *)armv8_glbl_core_data->cpu_driver_cmdline; 126 parse_commandline(kernel_command_line, cmdargs); 127 128 /* initialize the serial console */ 129 serial_console_init(false); 130 131 /* store the stack pointers */ 132 kernel_stack = local_phys_to_mem(core_data->cpu_driver_stack); 133 kernel_stack_top = local_phys_to_mem(core_data->cpu_driver_stack_limit); 134 135 uint8_t mpidr_aff0 = armv8_MPIDR_EL1_Aff0_rdf(NULL); 136 uint8_t mpidr_aff1 = armv8_MPIDR_EL1_Aff1_rdf(NULL); 137 uint8_t mpidr_aff2 = armv8_MPIDR_EL1_Aff2_rdf(NULL); 138 uint8_t mpidr_aff3 = armv8_MPIDR_EL1_Aff3_rdf(NULL); 139 140 switch (armv8_glbl_core_data->boot_magic) { 141 case ARMV8_BOOTMAGIC_BSP: 142 assert(my_core_id == 0); 143 printf("Barrelfish CPU driver starting on ARMv8 (BSP)\n"); 144 145 struct multiboot_info *multiboot = (struct multiboot_info *) 146 local_phys_to_mem(armv8_glbl_core_data->multiboot_image.base); 147 struct multiboot_tag_efi_mmap *mmap = (struct multiboot_tag_efi_mmap *) 148 multiboot2_find_tag(multiboot->tags, multiboot->total_size - 8, MULTIBOOT_TAG_TYPE_EFI_MMAP); 149 150 mmap_find_memory(mmap); 151 break; 152 case ARMV8_BOOTMAGIC_PSCI : 153 case ARMV8_BOOTMAGIC_PARKING : 154 assert(my_core_id != 0); 155 156 global = (struct global *)core_data->cpu_driver_globals_pointer; 157 158 printf("Barrelfish CPU driver starting on ARMv8 (APP) " 159 "mpid=%"PRIu8":%"PRIu8":%"PRIu8":%"PRIu8"\n", 160 mpidr_aff3, mpidr_aff2, mpidr_aff1, mpidr_aff0); 161 162 break; 163 default: { 164 serial_console_putchar('x'); 165 serial_console_putchar('x'); 166 serial_console_putchar('\n'); 167 168 panic("Implement AP booting!"); 169 __asm volatile ("wfi":::); 170 break; 171 } 172 } 173 174 MSG("Global data at %p\n", global); 175 176 MSG("Kernel stack at 0x%016" PRIxPTR ".. 0x%016" PRIxPTR "\n", 177 kernel_stack_top, kernel_stack); 178 MSG("Kernel first byte at 0x%" PRIxPTR "\n", &kernel_first_byte); 179 180 MSG("Exception vectors (VBAR_EL1): %p\n", &vectors); 181 sysreg_write_vbar_el1((uint64_t)&vectors); 182 183 if (cpu_is_bsp()) { 184 platform_revision_init(); 185 MSG("%"PRIu32" cores in system\n", platform_get_core_count()); 186 MSG("Initializing the interrupt controller\n"); 187 platform_init_ic_bsp(); 188 } else { 189 platform_init_ic_app(); 190 } 191 192 MSG("Enabling timers\n"); 193 platform_timer_init(config_timeslice); 194 195 MSG("Setting coreboot spawn handler\n"); 196 coreboot_set_spawn_handler(CPU_ARM8, platform_boot_core); 197 198 MSG("Calling arm_kernel_startup\n"); 199 arm_kernel_startup(); 200 while (1) { 201 __asm volatile ("wfi":::); 202 } 203} 204