From 817c6ca445c2b473aea72f07b65126e9e83fef15 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Mon, 21 Dec 2020 17:42:36 -0600 Subject: [PATCH] efi/arm64: Fill in some arm64 arch stuff Change-Id: I55eeba828f523f7358c25134bd5284eeefcf5ce7 Reviewed-on: https://review.haiku-os.org/c/haiku/+/3544 Reviewed-by: Adrien Destugues --- .../boot/platform/efi/arch/arm64/Jamfile | 32 ++++++ .../boot/platform/efi/arch/arm64/arch_mmu.cpp | 10 ++ .../boot/platform/efi/arch/arm64/arch_smp.cpp | 72 ++++++++++++++ .../platform/efi/arch/arm64/arch_start.cpp | 98 +++++++++++++++++++ .../platform/efi/arch/arm64/arch_timer.cpp | 32 ++++++ .../boot/platform/efi/arch/arm64/entry.S | 36 +++++++ .../efi/arch/arm64/relocation_func.cpp | 6 +- 7 files changed, 283 insertions(+), 3 deletions(-) create mode 100644 src/system/boot/platform/efi/arch/arm64/Jamfile create mode 100644 src/system/boot/platform/efi/arch/arm64/arch_mmu.cpp create mode 100644 src/system/boot/platform/efi/arch/arm64/arch_smp.cpp create mode 100644 src/system/boot/platform/efi/arch/arm64/arch_start.cpp create mode 100644 src/system/boot/platform/efi/arch/arm64/arch_timer.cpp create mode 100644 src/system/boot/platform/efi/arch/arm64/entry.S diff --git a/src/system/boot/platform/efi/arch/arm64/Jamfile b/src/system/boot/platform/efi/arch/arm64/Jamfile new file mode 100644 index 0000000000..e36cc216df --- /dev/null +++ b/src/system/boot/platform/efi/arch/arm64/Jamfile @@ -0,0 +1,32 @@ +SubDir HAIKU_TOP src system boot platform efi arch arm64 ; + +SubDirHdrs $(HAIKU_TOP) src system boot platform efi ; + +UsePrivateHeaders [ FDirName kernel platform ] ; +UsePrivateHeaders [ FDirName kernel boot platform efi ] ; + +local platform ; +for platform in [ MultiBootSubDirSetup efi ] { + on $(platform) { + { + local defines = _BOOT_MODE _BOOT_PLATFORM_EFI ; + defines = [ FDefines $(defines) ] ; + SubDirCcFlags $(defines) ; + SubDirC++Flags $(defines) -fno-rtti ; + } + + local arch_src = + crt0-efi-$(TARGET_ARCH).S + entry.S + relocation_func.cpp + arch_mmu.cpp + arch_smp.cpp + arch_start.cpp + arch_timer.cpp + ; + + BootMergeObject boot_platform_efi_arm64.o : + $(arch_src) + ; + } +} diff --git a/src/system/boot/platform/efi/arch/arm64/arch_mmu.cpp b/src/system/boot/platform/efi/arch/arm64/arch_mmu.cpp new file mode 100644 index 0000000000..9a86a8590b --- /dev/null +++ b/src/system/boot/platform/efi/arch/arm64/arch_mmu.cpp @@ -0,0 +1,10 @@ +/* + * Copyright 2019-2020 Haiku, Inc. All rights reserved. + * Released under the terms of the MIT License. + */ + +void +arch_mmu_init() +{ + // Stub +} diff --git a/src/system/boot/platform/efi/arch/arm64/arch_smp.cpp b/src/system/boot/platform/efi/arch/arm64/arch_smp.cpp new file mode 100644 index 0000000000..84e25b57ac --- /dev/null +++ b/src/system/boot/platform/efi/arch/arm64/arch_smp.cpp @@ -0,0 +1,72 @@ +/* + * Copyright 2019-2020, Haiku, Inc. All rights reserved. + * Released under the terms of the MIT License. +*/ + + +#include "arch_smp.h" + +#include + +#include + +#include +#include +#include +#include +#include + + +//#define TRACE_SMP +#ifdef TRACE_SMP +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + + +int +arch_smp_get_current_cpu(void) +{ + // One cpu for now. + return 0; +} + + +void +arch_smp_init_other_cpus(void) +{ + // One cpu for now. + gKernelArgs.num_cpus = 1; + return; +} + + +void +arch_smp_boot_other_cpus(uint32 pml4, uint64 kernel_entry) +{ + // One cpu for now. +} + + +void +arch_smp_add_safemode_menus(Menu *menu) +{ + MenuItem *item; + + if (gKernelArgs.num_cpus < 2) + return; + + item = new(nothrow) MenuItem("Disable SMP"); + menu->AddItem(item); + item->SetData(B_SAFEMODE_DISABLE_SMP); + item->SetType(MENU_ITEM_MARKABLE); + item->SetHelpText("Disables all but one CPU core."); +} + + +void +arch_smp_init(void) +{ + // One cpu for now. +} diff --git a/src/system/boot/platform/efi/arch/arm64/arch_start.cpp b/src/system/boot/platform/efi/arch/arm64/arch_start.cpp new file mode 100644 index 0000000000..0744e103e4 --- /dev/null +++ b/src/system/boot/platform/efi/arch/arm64/arch_start.cpp @@ -0,0 +1,98 @@ +/* + * Copyright 2019-2020 Haiku, Inc. All rights reserved. + * Released under the terms of the MIT License. + */ + + +#include +#include +#include + +#include "efi_platform.h" + + +extern "C" void arch_enter_kernel(struct kernel_args *kernelArgs, + addr_t kernelEntry, addr_t kernelStackTop); + + +void +arch_start_kernel(addr_t kernelEntry) +{ + // Prepare to exit EFI boot services. + // Read the memory map. + // First call is to determine the buffer size. + size_t memory_map_size = 0; + efi_memory_descriptor dummy; + efi_memory_descriptor *memory_map; + size_t map_key; + size_t descriptor_size; + uint32_t descriptor_version; + if (kBootServices->GetMemoryMap(&memory_map_size, &dummy, &map_key, + &descriptor_size, &descriptor_version) != EFI_BUFFER_TOO_SMALL) { + panic("Unable to determine size of system memory map"); + } + + // Allocate a buffer twice as large as needed just in case it gets bigger + // between calls to ExitBootServices. + size_t actual_memory_map_size = memory_map_size * 2; + memory_map + = (efi_memory_descriptor *)kernel_args_malloc(actual_memory_map_size); + + if (memory_map == NULL) + panic("Unable to allocate memory map."); + + // Read (and print) the memory map. + memory_map_size = actual_memory_map_size; + if (kBootServices->GetMemoryMap(&memory_map_size, memory_map, &map_key, + &descriptor_size, &descriptor_version) != EFI_SUCCESS) { + panic("Unable to fetch system memory map."); + } + + addr_t addr = (addr_t)memory_map; + dprintf("System provided memory map:\n"); + for (size_t i = 0; i < memory_map_size / descriptor_size; ++i) { + efi_memory_descriptor *entry + = (efi_memory_descriptor *)(addr + i * descriptor_size); + dprintf(" %#lx-%#lx %#lx %#x %#lx\n", entry->PhysicalStart, + entry->PhysicalStart + entry->NumberOfPages * B_PAGE_SIZE, + entry->VirtualStart, entry->Type, entry->Attribute); + } + + // Attempt to fetch the memory map and exit boot services. + // This needs to be done in a loop, as ExitBootServices can change the + // memory map. + // Even better: Only GetMemoryMap and ExitBootServices can be called after + // the first call to ExitBootServices, as the firmware is permitted to + // partially exit. This is why twice as much space was allocated for the + // memory map, as it's impossible to allocate more now. + // A changing memory map shouldn't affect the generated page tables, as + // they only needed to know about the maximum address, not any specific + // entry. + dprintf("Calling ExitBootServices. So long, EFI!\n"); + while (true) { + if (kBootServices->ExitBootServices(kImage, map_key) == EFI_SUCCESS) { + // The console was provided by boot services, disable it. + stdout = NULL; + stderr = NULL; + // Can we adjust gKernelArgs.platform_args.serial_base_ports[0] + // to something fixed in qemu for debugging? + break; + } + + memory_map_size = actual_memory_map_size; + if (kBootServices->GetMemoryMap(&memory_map_size, memory_map, &map_key, + &descriptor_size, &descriptor_version) != EFI_SUCCESS) { + panic("Unable to fetch system memory map."); + } + } + + // Update EFI, generate final kernel physical memory map, etc. + //arch_mmu_post_efi_setup(memory_map_size, memory_map, + // descriptor_size, descriptor_version); + + //smp_boot_other_cpus(final_pml4, kernelEntry); + + // Enter the kernel! + arch_enter_kernel(&gKernelArgs, kernelEntry, + gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size); +} diff --git a/src/system/boot/platform/efi/arch/arm64/arch_timer.cpp b/src/system/boot/platform/efi/arch/arm64/arch_timer.cpp new file mode 100644 index 0000000000..2debfcf8f6 --- /dev/null +++ b/src/system/boot/platform/efi/arch/arm64/arch_timer.cpp @@ -0,0 +1,32 @@ +/* + * Copyright, 2019-2020, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Alexander von Gluck IV +*/ + + +#include "arch_timer.h" + +#include + +#include +#include +#include + +#include + +//#define TRACE_TIMER +#ifdef TRACE_TIMER +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + + +void +arch_timer_init(void) +{ + // Stub +} diff --git a/src/system/boot/platform/efi/arch/arm64/entry.S b/src/system/boot/platform/efi/arch/arm64/entry.S new file mode 100644 index 0000000000..82d44b0743 --- /dev/null +++ b/src/system/boot/platform/efi/arch/arm64/entry.S @@ -0,0 +1,36 @@ +/* + * Copyright 2020-2021, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include + + + .text + +/* status_t arch_enter_kernel(struct kernel_args *kernelArgs, + addr_t kernelEntry, addr_t kernelStackTop); + + x0 - kernelArgs + x1 - kernelEntry + x2 - kernelStackTop +*/ +FUNCTION(arch_enter_kernel): + + // set the kernel stack + mov sp,x2 + + // set up kernel _start args + //mov x0,x0 // kernelArgs + mov x4,x1 + mov x1,#0 // currentCPU=0 + + // call the kernel + b x4 + + // return + mov x0,#-1 // B_ERROR + ret + +FUNCTION_END(arch_enter_kernel) + diff --git a/src/system/boot/platform/efi/arch/arm64/relocation_func.cpp b/src/system/boot/platform/efi/arch/arm64/relocation_func.cpp index e430e40f2b..6883886126 100644 --- a/src/system/boot/platform/efi/arch/arm64/relocation_func.cpp +++ b/src/system/boot/platform/efi/arch/arm64/relocation_func.cpp @@ -34,12 +34,12 @@ SUCH DAMAGE. */ -#include -#include +#include +#include #include -efi_status _relocate (long ldbase, Elf64_Dyn *dyn, +extern "C" efi_status _relocate (long ldbase, Elf64_Dyn *dyn, efi_handle image EFI_UNUSED, efi_system_table *systab EFI_UNUSED) {