Skip to content

Commit 6b16a27

Browse files
authored
[libc] Add startup code for ARM v7-A, ARM v7-R variants (#153576)
These variants require a different exception table that requires a bit of initialisation. This allows us to enable testing for these variants downstream.
1 parent 21b607a commit 6b16a27

File tree

1 file changed

+64
-3
lines changed

1 file changed

+64
-3
lines changed

libc/startup/baremetal/arm/start.cpp

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include "startup/baremetal/fini.h"
1616
#include "startup/baremetal/init.h"
1717

18+
#include <arm_acle.h> // For __arm_wsr
19+
1820
extern "C" {
1921
int main(int argc, char **argv);
2022
void _start();
@@ -33,6 +35,7 @@ extern uintptr_t __bss_size[];
3335
} // extern "C"
3436

3537
namespace {
38+
#if __ARM_ARCH_PROFILE == 'M'
3639
// Based on
3740
// https://developer.arm.com/documentation/107565/0101/Use-case-examples/Generic-Information/What-is-inside-a-program-image-/Vector-table
3841
void NMI_Handler() {}
@@ -55,8 +58,8 @@ const HandlerType vector_table[] = {
5558
reinterpret_cast<HandlerType>(&__stack), // SP
5659
_start, // Reset
5760
NMI_Handler, // NMI Handler
58-
HardFault_Handler, // Hard Fault Handlerß
59-
MemManage_Handler, // MPU Fault Han`dler
61+
HardFault_Handler, // Hard Fault Handler
62+
MemManage_Handler, // MPU Fault Handler
6063
BusFault_Handler, // Bus Fault Handler
6164
UsageFault_Handler, // Usage Fault Handler
6265
0, // Reserved
@@ -70,12 +73,64 @@ const HandlerType vector_table[] = {
7073
SysTick_Handler, // SysTick Handler
7174
// Unused
7275
};
76+
#else
77+
// Based on
78+
// https://developer.arm.com/documentation/den0013/0400/Boot-Code/Booting-a-bare-metal-system
79+
void Reset_Handler() { LIBC_NAMESPACE::exit(1); }
80+
void Undefined_Handler() { LIBC_NAMESPACE::exit(1); }
81+
void SWI_Handler() { LIBC_NAMESPACE::exit(1); }
82+
void PrefetchAbort_Handler() { LIBC_NAMESPACE::exit(1); }
83+
void DataAbort_Handler() { LIBC_NAMESPACE::exit(1); }
84+
void IRQ_Handler() { LIBC_NAMESPACE::exit(1); }
85+
void FIQ_Handler() { LIBC_NAMESPACE::exit(1); }
86+
87+
// The AArch32 exception vector table has 8 entries, each of which is 4
88+
// bytes long, and contains code. The whole table must be 32-byte aligned.
89+
// The table may also be relocated, so we make it position-independent by
90+
// having a table of handler addresses and loading the address to pc.
91+
[[gnu::section(".vectors"), gnu::aligned(32), gnu::used, gnu::naked,
92+
gnu::target("arm")]]
93+
void vector_table() {
94+
asm("LDR pc, [pc, #24]");
95+
asm("LDR pc, [pc, #24]");
96+
asm("LDR pc, [pc, #24]");
97+
asm("LDR pc, [pc, #24]");
98+
asm("LDR pc, [pc, #24]");
99+
asm("LDR pc, [pc, #24]");
100+
asm("LDR pc, [pc, #24]");
101+
asm("LDR pc, [pc, #24]");
102+
asm(".word %c0" : : "X"(Reset_Handler));
103+
asm(".word %c0" : : "X"(Undefined_Handler));
104+
asm(".word %c0" : : "X"(SWI_Handler));
105+
asm(".word %c0" : : "X"(PrefetchAbort_Handler));
106+
asm(".word %c0" : : "X"(DataAbort_Handler));
107+
asm(".word %c0" : : "X"(0));
108+
asm(".word %c0" : : "X"(IRQ_Handler));
109+
asm(".word %c0" : : "X"(FIQ_Handler));
110+
}
111+
#endif
73112
} // namespace
74113

75114
namespace LIBC_NAMESPACE_DECL {
76115
[[noreturn]] void do_start() {
77116
// FIXME: set up the QEMU test environment
78117

118+
#if __ARM_ARCH_PROFILE == 'A' || __ARM_ARCH_PROFILE == 'R'
119+
// Set up registers to be used in exception handling
120+
// Copy the current sp value to each of the banked copies of sp.
121+
__arm_wsr("CPSR_c", 0x11); // FIQ
122+
asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));
123+
__arm_wsr("CPSR_c", 0x12); // IRQ
124+
asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));
125+
__arm_wsr("CPSR_c", 0x17); // ABT
126+
asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));
127+
__arm_wsr("CPSR_c", 0x1B); // UND
128+
asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));
129+
__arm_wsr("CPSR_c", 0x1F); // SYS
130+
asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));
131+
__arm_wsr("CPSR_c", 0x13); // SVC
132+
#endif
133+
79134
// Perform the equivalent of scatterloading
80135
LIBC_NAMESPACE::memcpy(__data_start, __data_source,
81136
reinterpret_cast<uintptr_t>(__data_size));
@@ -89,7 +144,13 @@ namespace LIBC_NAMESPACE_DECL {
89144
}
90145
} // namespace LIBC_NAMESPACE_DECL
91146

92-
extern "C" void _start() {
147+
extern "C" {
148+
#ifdef __ARM_ARCH_ISA_ARM
149+
// If ARM state is supported, it must be used (instead of Thumb)
150+
[[gnu::naked, gnu::target("arm")]]
151+
#endif
152+
void _start() {
93153
asm volatile("mov sp, %0" : : "r"(&__stack));
94154
asm volatile("bl %0" : : "X"(LIBC_NAMESPACE::do_start));
95155
}
156+
} // extern "C"

0 commit comments

Comments
 (0)