-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[libc] Add startup code for ARM v7-A, ARM v7-R variants #153576
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
Conversation
These variants require a different exception table that requires a bit of initialisation. This allows us to enable testing for these variants downstream.
|
@llvm/pr-subscribers-libc Author: William Huynh (saturn691) ChangesThese variants require a different exception table that requires a bit of initialisation. This allows us to enable testing for these variants downstream. Full diff: https://github.com/llvm/llvm-project/pull/153576.diff 1 Files Affected:
diff --git a/libc/startup/baremetal/arm/start.cpp b/libc/startup/baremetal/arm/start.cpp
index 493445e2922b0..a926206c73a6f 100644
--- a/libc/startup/baremetal/arm/start.cpp
+++ b/libc/startup/baremetal/arm/start.cpp
@@ -15,6 +15,8 @@
#include "startup/baremetal/fini.h"
#include "startup/baremetal/init.h"
+#include <arm_acle.h>
+
extern "C" {
int main(int argc, char **argv);
void _start();
@@ -33,6 +35,7 @@ extern uintptr_t __bss_size[];
} // extern "C"
namespace {
+#if __ARM_ARCH_PROFILE == 'M'
// Based on
// https://developer.arm.com/documentation/107565/0101/Use-case-examples/Generic-Information/What-is-inside-a-program-image-/Vector-table
void NMI_Handler() {}
@@ -55,8 +58,8 @@ const HandlerType vector_table[] = {
reinterpret_cast<HandlerType>(&__stack), // SP
_start, // Reset
NMI_Handler, // NMI Handler
- HardFault_Handler, // Hard Fault Handlerß
- MemManage_Handler, // MPU Fault Han`dler
+ HardFault_Handler, // Hard Fault Handler
+ MemManage_Handler, // MPU Fault Handler
BusFault_Handler, // Bus Fault Handler
UsageFault_Handler, // Usage Fault Handler
0, // Reserved
@@ -70,12 +73,64 @@ const HandlerType vector_table[] = {
SysTick_Handler, // SysTick Handler
// Unused
};
+#else
+// Based on
+// https://developer.arm.com/documentation/den0013/0400/Boot-Code/Booting-a-bare-metal-system
+void Reset_Handler() { LIBC_NAMESPACE::exit(1); }
+void Undefined_Handler() { LIBC_NAMESPACE::exit(1); }
+void SWI_Handler() { LIBC_NAMESPACE::exit(1); }
+void PrefetchAbort_Handler() { LIBC_NAMESPACE::exit(1); }
+void DataAbort_Handler() { LIBC_NAMESPACE::exit(1); }
+void IRQ_Handler() { LIBC_NAMESPACE::exit(1); }
+void FIQ_Handler() { LIBC_NAMESPACE::exit(1); }
+
+// The AArch32 exception vector table has 8 entries, each of which is 4
+// bytes long, and contains code. The whole table must be 32-byte aligned.
+// The table may also be relocated, so we make it position-independent by
+// having a table of handler addresses and loading the address to pc.
+[[gnu::section(".vectors"), gnu::aligned(32), gnu::used, gnu::naked,
+ gnu::target("arm")]]
+void vector_table() {
+ asm("LDR pc, [pc, #24]");
+ asm("LDR pc, [pc, #24]");
+ asm("LDR pc, [pc, #24]");
+ asm("LDR pc, [pc, #24]");
+ asm("LDR pc, [pc, #24]");
+ asm("LDR pc, [pc, #24]");
+ asm("LDR pc, [pc, #24]");
+ asm("LDR pc, [pc, #24]");
+ asm(".word %c0" : : "X"(Reset_Handler));
+ asm(".word %c0" : : "X"(Undefined_Handler));
+ asm(".word %c0" : : "X"(SWI_Handler));
+ asm(".word %c0" : : "X"(PrefetchAbort_Handler));
+ asm(".word %c0" : : "X"(DataAbort_Handler));
+ asm(".word %c0" : : "X"(0));
+ asm(".word %c0" : : "X"(IRQ_Handler));
+ asm(".word %c0" : : "X"(FIQ_Handler));
+}
+#endif
} // namespace
namespace LIBC_NAMESPACE_DECL {
[[noreturn]] void do_start() {
// FIXME: set up the QEMU test environment
+#if __ARM_ARCH_PROFILE == 'A' || __ARM_ARCH_PROFILE == 'R'
+ // Set up registers to be used in exception handling
+ // Copy the current sp value to each of the banked copies of sp.
+ __arm_wsr("CPSR_c", 0x11); // FIQ
+ asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));
+ __arm_wsr("CPSR_c", 0x12); // IRQ
+ asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));
+ __arm_wsr("CPSR_c", 0x17); // ABT
+ asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));
+ __arm_wsr("CPSR_c", 0x1B); // UND
+ asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));
+ __arm_wsr("CPSR_c", 0x1F); // SYS
+ asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));
+ __arm_wsr("CPSR_c", 0x13); // SVC
+#endif
+
// Perform the equivalent of scatterloading
LIBC_NAMESPACE::memcpy(__data_start, __data_source,
reinterpret_cast<uintptr_t>(__data_size));
@@ -89,7 +144,13 @@ namespace LIBC_NAMESPACE_DECL {
}
} // namespace LIBC_NAMESPACE_DECL
-extern "C" void _start() {
+extern "C" {
+#ifdef __ARM_ARCH_ISA_ARM
+// If ARM state is supported, it must be used (instead of Thumb)
+[[gnu::naked, gnu::target("arm")]]
+#endif
+void _start() {
asm volatile("mov sp, %0" : : "r"(&__stack));
asm volatile("bl %0" : : "X"(LIBC_NAMESPACE::do_start));
}
+} // extern "C"
|
michaelrj-google
left a comment
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
|
I'm going to build upon this bootcode for more versions of Arm. If anyone has other nits please leave them here and I'll do a post-commit fixup. Please also feel free to approve if you're happy. |
Support added in llvm/llvm-project#153576 Also update bootcode to support v7-A/v7-R outside of hermetic tests.
These variants require a different exception table that requires a bit of initialisation.
This allows us to enable testing for these variants downstream.