-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[libc] Add boot code for AArch64 #154789
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc] Add boot code for AArch64 #154789
Conversation
@llvm/pr-subscribers-libc Author: William Huynh (saturn691) ChangesThis is required in hermetic testing downstream. It is not complete, and will not work on hardware, however it runs on QEMU, and can report a pass/fail on our tests. Full diff: https://github.com/llvm/llvm-project/pull/154789.diff 3 Files Affected:
diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index 267c32e956945..66ef3d3c1cb78 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -836,7 +836,7 @@ function(add_libc_hermetic test_name)
${fq_deps_list})
# TODO: currently the dependency chain is broken such that getauxval cannot properly
# propagate to hermetic tests. This is a temporary workaround.
- if (LIBC_TARGET_ARCHITECTURE_IS_AARCH64)
+ if (LIBC_TARGET_ARCHITECTURE_IS_AARCH64 AND NOT(LIBC_TARGET_OS_IS_BAREMETAL))
target_link_libraries(
${fq_build_target_name}
PRIVATE
diff --git a/libc/startup/baremetal/aarch64/CMakeLists.txt b/libc/startup/baremetal/aarch64/CMakeLists.txt
new file mode 100644
index 0000000000000..f75bd893c68bc
--- /dev/null
+++ b/libc/startup/baremetal/aarch64/CMakeLists.txt
@@ -0,0 +1,16 @@
+add_startup_object(
+ crt1
+ SRC
+ start.cpp
+ DEPENDS
+ libc.src.stdlib.atexit
+ libc.src.stdlib.exit
+ libc.src.string.memcpy
+ libc.src.string.memset
+ libc.startup.baremetal.init
+ libc.startup.baremetal.fini
+ COMPILE_OPTIONS
+ -ffreestanding # To avoid compiler warnings about calling the main function.
+ -fno-builtin
+ -Wno-global-constructors # To allow vector table initialization
+)
diff --git a/libc/startup/baremetal/aarch64/start.cpp b/libc/startup/baremetal/aarch64/start.cpp
new file mode 100644
index 0000000000000..94d44c849ff9a
--- /dev/null
+++ b/libc/startup/baremetal/aarch64/start.cpp
@@ -0,0 +1,110 @@
+//===-- Implementation of crt for aarch64----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "hdr/stdint_proxy.h"
+#include "src/__support/macros/config.h"
+#include "src/stdlib/atexit.h"
+#include "src/stdlib/exit.h"
+#include "src/string/memcpy.h"
+#include "src/string/memset.h"
+#include "startup/baremetal/fini.h"
+#include "startup/baremetal/init.h"
+
+#include <arm_acle.h>
+
+extern "C" {
+int main(int argc, char **argv);
+void _start();
+
+// Semihosting library initialisation if applicable. Required for printf, etc.
+[[gnu::weak]] void _platform_init() {}
+
+// These symbols are provided by the linker. The exact names are not defined by
+// a standard.
+extern uintptr_t __stack;
+extern uintptr_t __data_source[];
+extern uintptr_t __data_start[];
+extern uintptr_t __data_size[];
+extern uintptr_t __bss_start[];
+extern uintptr_t __bss_size[];
+} // extern "C"
+
+namespace {
+// The Arm ARM for the A-profile architecture (D14.1.5) defines the exceptions.
+// However, for simplicity, we don't bother logging, and just exit.
+void GenericException_Handler() { LIBC_NAMESPACE::exit(1); }
+
+// The AArch64 exception vector table has 16 entries, each of which is 128
+// bytes long, and contains code. The whole table must be 2048-byte aligned.
+// For our purposes, each entry just contains one branch instruction to the
+// exception reporting function, since we never want to resume after an
+// exception.
+[[gnu::section(".vectors"), gnu::aligned(2048), gnu::used, gnu::naked]]
+void vector_table() {
+#define VECTOR_TABLE_ENTRY \
+ asm(".balign 128"); \
+ asm("B %0" : : "X"(GenericException_Handler));
+
+ VECTOR_TABLE_ENTRY;
+ VECTOR_TABLE_ENTRY;
+ VECTOR_TABLE_ENTRY;
+ VECTOR_TABLE_ENTRY;
+ VECTOR_TABLE_ENTRY;
+ VECTOR_TABLE_ENTRY;
+ VECTOR_TABLE_ENTRY;
+ VECTOR_TABLE_ENTRY;
+ VECTOR_TABLE_ENTRY;
+ VECTOR_TABLE_ENTRY;
+ VECTOR_TABLE_ENTRY;
+ VECTOR_TABLE_ENTRY;
+ VECTOR_TABLE_ENTRY;
+ VECTOR_TABLE_ENTRY;
+ VECTOR_TABLE_ENTRY;
+ VECTOR_TABLE_ENTRY;
+}
+} // namespace
+
+namespace LIBC_NAMESPACE_DECL {
+
+[[noreturn]] void do_start() {
+ // TODO: This startup code is not extensive, but rather the MVP for QEMU
+ // testing.
+
+ // Set up exception handling
+ __arm_wsr64("VBAR_EL1", reinterpret_cast<uint64_t>(&vector_table));
+
+#ifdef __ARM_FP
+ // Do not trap FP/SME/SVE instructions
+ static constexpr uint64_t CPACR_SHIFT_FPEN = 20;
+ static constexpr uint64_t CPACR_SHIFT_SMEN = 24;
+ uint64_t cpacr = __arm_rsr64("CPACR_EL1");
+ cpacr |= (0x3 << CPACR_SHIFT_FPEN);
+ cpacr |= (0x3 << CPACR_SHIFT_SMEN);
+ __arm_wsr64("CPACR_EL1", cpacr);
+#endif
+
+ // Perform the equivalent of scatterloading
+ LIBC_NAMESPACE::memcpy(__data_start, __data_source,
+ reinterpret_cast<uintptr_t>(__data_size));
+ LIBC_NAMESPACE::memset(__bss_start, '\0',
+ reinterpret_cast<uintptr_t>(__bss_size));
+ __libc_init_array();
+
+ _platform_init();
+ LIBC_NAMESPACE::atexit(&__libc_fini_array);
+ LIBC_NAMESPACE::exit(main(0, 0));
+}
+} // namespace LIBC_NAMESPACE_DECL
+
+extern "C" {
+[[gnu::section(".text.init.enter"), gnu::naked]]
+void _start() {
+ asm volatile("mov sp, %0" : : "r"(&__stack));
+ asm volatile("bl %0" : : "X"(LIBC_NAMESPACE::do_start));
+}
+} // extern "C"
|
This is required in hermetic testing downstream. It is not complete, and will not work on hardware, however it runs on QEMU, and can report a pass/fail on our tests.
2f4135a
to
9a42e9d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM as an MVP.
If possible, please add TODOs on the parts that are incomplete
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Enabled in llvm/llvm-project#154789 Minor changes to the CMake file, to select `qemu-system-aarch64` if applicable. These tests don't pass, but they compile, so we enable them.
This is required in hermetic testing downstream. It is not complete, and will not work on hardware, however it runs on QEMU, and can report a pass/fail on our tests.