1 /* 2 * Copyright 2019-2022 Haiku, Inc. All rights reserved. 3 * Released under the terms of the MIT License. 4 */ 5 6 7 #include <boot/platform.h> 8 #include <boot/stage2.h> 9 #include <boot/stdio.h> 10 11 #include "efi_platform.h" 12 #include "generic_mmu.h" 13 #include "mmu.h" 14 #include "serial.h" 15 16 #include "aarch64.h" 17 18 extern "C" void arch_enter_kernel( 19 struct kernel_args* kernelArgs, addr_t kernelEntry, addr_t kernelStackTop); 20 21 extern const char* granule_type_str(int tg); 22 23 extern uint32_t arch_mmu_generate_post_efi_page_tables(size_t memory_map_size, 24 efi_memory_descriptor* memory_map, size_t descriptor_size, uint32_t descriptor_version); 25 26 extern void arch_mmu_post_efi_setup(size_t memory_map_size, efi_memory_descriptor* memory_map, 27 size_t descriptor_size, uint32_t descriptor_version); 28 29 extern void arch_mmu_setup_EL1(uint64 tcr); 30 31 32 void 33 arch_convert_kernel_args(void) 34 { 35 fix_address(gKernelArgs.arch_args.fdt); 36 } 37 38 39 void 40 arch_start_kernel(addr_t kernelEntry) 41 { 42 // Prepare to exit EFI boot services. 43 // Read the memory map. 44 // First call is to determine the buffer size. 45 size_t memory_map_size = 0; 46 efi_memory_descriptor dummy; 47 efi_memory_descriptor* memory_map; 48 size_t map_key; 49 size_t descriptor_size; 50 uint32_t descriptor_version; 51 if (kBootServices->GetMemoryMap( 52 &memory_map_size, &dummy, &map_key, &descriptor_size, &descriptor_version) 53 != EFI_BUFFER_TOO_SMALL) { 54 panic("Unable to determine size of system memory map"); 55 } 56 57 // Allocate a buffer twice as large as needed just in case it gets bigger 58 // between calls to ExitBootServices. 59 size_t actual_memory_map_size = memory_map_size * 2; 60 memory_map = (efi_memory_descriptor*) kernel_args_malloc(actual_memory_map_size); 61 62 if (memory_map == NULL) 63 panic("Unable to allocate memory map."); 64 65 // Read (and print) the memory map. 66 memory_map_size = actual_memory_map_size; 67 if (kBootServices->GetMemoryMap( 68 &memory_map_size, memory_map, &map_key, &descriptor_size, &descriptor_version) 69 != EFI_SUCCESS) { 70 panic("Unable to fetch system memory map."); 71 } 72 73 addr_t addr = (addr_t) memory_map; 74 efi_physical_addr loaderCode = 0LL; 75 dprintf("System provided memory map:\n"); 76 for (size_t i = 0; i < memory_map_size / descriptor_size; ++i) { 77 efi_memory_descriptor* entry = (efi_memory_descriptor*) (addr + i * descriptor_size); 78 dprintf(" phys: 0x%0lx-0x%0lx, virt: 0x%0lx-0x%0lx, size = 0x%0lx, type: %s (%#x), attr: " 79 "%#lx\n", 80 entry->PhysicalStart, entry->PhysicalStart + entry->NumberOfPages * B_PAGE_SIZE, 81 entry->VirtualStart, entry->VirtualStart + entry->NumberOfPages * B_PAGE_SIZE, 82 entry->NumberOfPages * B_PAGE_SIZE, memory_region_type_str(entry->Type), entry->Type, 83 entry->Attribute); 84 if (entry->Type == EfiLoaderCode) 85 loaderCode = entry->PhysicalStart; 86 } 87 // This is where our efi loader got relocated, therefore we need to use this 88 // offset for properly align symbols 89 dprintf("Efi loader symbols offset: 0x%0lx:\n", loaderCode); 90 91 /* 92 * "The AArch64 exception model is made up of a number of exception levels 93 * (EL0 - EL3), with EL0 and EL1 having a secure and a non-secure 94 * counterpart. EL2 is the hypervisor level and exists only in non-secure 95 * mode. EL3 is the highest priority level and exists only in secure mode." 96 * 97 * "2.3 UEFI System Environment and Configuration 98 * The resident UEFI boot-time environment shall use the highest non-secure 99 * privilege level available. The exact meaning of this is architecture 100 * dependent, as detailed below." 101 102 * "2.3.1 AArch64 Exception Levels 103 * On AArch64 UEFI shall execute as 64-bit code at either EL1 or EL2, 104 * depending on whether or not virtualization is available at OS load time." 105 */ 106 uint64 el = arch_exception_level(); 107 dprintf("Current Exception Level EL%1lx\n", el); 108 dprintf("TTBR0: %" B_PRIx64 " TTBRx: %" B_PRIx64 " SCTLR: %" B_PRIx64 " TCR: %" B_PRIx64 "\n", 109 arch_mmu_base_register(), arch_mmu_base_register(true), _arch_mmu_get_sctlr(), 110 _arch_mmu_get_tcr()); 111 112 if (arch_mmu_enabled()) { 113 dprintf("MMU Enabled, Granularity %s, bits %d\n", granule_type_str(arch_mmu_user_granule()), 114 arch_mmu_user_address_bits()); 115 116 dprintf("Kernel entry accessibility W: %x R: %x\n", arch_mmu_write_access(kernelEntry), 117 arch_mmu_read_access(kernelEntry)); 118 119 if (el == 1) { 120 // Disable CACHE & MMU before dealing with TTBRx 121 arch_cache_disable(); 122 } 123 } 124 125 // Generate page tables for use after ExitBootServices. 126 arch_mmu_generate_post_efi_page_tables( 127 memory_map_size, memory_map, descriptor_size, descriptor_version); 128 129 // Attempt to fetch the memory map and exit boot services. 130 // This needs to be done in a loop, as ExitBootServices can change the 131 // memory map. 132 // Even better: Only GetMemoryMap and ExitBootServices can be called after 133 // the first call to ExitBootServices, as the firmware is permitted to 134 // partially exit. This is why twice as much space was allocated for the 135 // memory map, as it's impossible to allocate more now. 136 // A changing memory map shouldn't affect the generated page tables, as 137 // they only needed to know about the maximum address, not any specific 138 // entry. 139 140 dprintf("Calling ExitBootServices. So long, EFI!\n"); 141 serial_disable(); 142 143 while (true) { 144 if (kBootServices->ExitBootServices(kImage, map_key) == EFI_SUCCESS) { 145 // Disconnect from EFI serial_io / stdio services 146 serial_kernel_handoff(); 147 dprintf("Unhooked from EFI serial services\n"); 148 break; 149 } 150 151 memory_map_size = actual_memory_map_size; 152 if (kBootServices->GetMemoryMap( 153 &memory_map_size, memory_map, &map_key, &descriptor_size, &descriptor_version) 154 != EFI_SUCCESS) { 155 panic("Unable to fetch system memory map."); 156 } 157 } 158 159 // Update EFI, generate final kernel physical memory map, etc. 160 arch_mmu_post_efi_setup(memory_map_size, memory_map, descriptor_size, descriptor_version); 161 162 // Re-init and activate serial in a horrific post-EFI landscape. Clowns roam the land freely. 163 serial_init(); 164 serial_enable(); 165 166 switch (el) { 167 case 1: 168 arch_mmu_setup_EL1(READ_SPECIALREG(TCR_EL1)); 169 break; 170 case 2: 171 arch_mmu_setup_EL1(READ_SPECIALREG(TCR_EL2)); 172 arch_cache_disable(); 173 _arch_transition_EL2_EL1(); 174 break; 175 default: 176 panic("Unexpected Exception Level\n"); 177 break; 178 } 179 180 arch_cache_enable(); 181 182 // smp_boot_other_cpus(final_pml4, kernelEntry, (addr_t)&gKernelArgs); 183 184 if (arch_mmu_read_access(kernelEntry) 185 && arch_mmu_read_access(gKernelArgs.cpu_kstack[0].start)) { 186 // Enter the kernel! 187 arch_enter_kernel(&gKernelArgs, kernelEntry, 188 gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size); 189 } else { 190 // _arch_exception_panic("Kernel or Stack memory not accessible\n", __LINE__); 191 panic("Kernel or Stack memory not accessible\n"); 192 } 193 } 194