[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.
This commit is contained in:
parent
21b607adbe
commit
6b16a276ef
@ -15,6 +15,8 @@
|
|||||||
#include "startup/baremetal/fini.h"
|
#include "startup/baremetal/fini.h"
|
||||||
#include "startup/baremetal/init.h"
|
#include "startup/baremetal/init.h"
|
||||||
|
|
||||||
|
#include <arm_acle.h> // For __arm_wsr
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
int main(int argc, char **argv);
|
int main(int argc, char **argv);
|
||||||
void _start();
|
void _start();
|
||||||
@ -33,6 +35,7 @@ extern uintptr_t __bss_size[];
|
|||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
#if __ARM_ARCH_PROFILE == 'M'
|
||||||
// Based on
|
// Based on
|
||||||
// https://developer.arm.com/documentation/107565/0101/Use-case-examples/Generic-Information/What-is-inside-a-program-image-/Vector-table
|
// https://developer.arm.com/documentation/107565/0101/Use-case-examples/Generic-Information/What-is-inside-a-program-image-/Vector-table
|
||||||
void NMI_Handler() {}
|
void NMI_Handler() {}
|
||||||
@ -55,8 +58,8 @@ const HandlerType vector_table[] = {
|
|||||||
reinterpret_cast<HandlerType>(&__stack), // SP
|
reinterpret_cast<HandlerType>(&__stack), // SP
|
||||||
_start, // Reset
|
_start, // Reset
|
||||||
NMI_Handler, // NMI Handler
|
NMI_Handler, // NMI Handler
|
||||||
HardFault_Handler, // Hard Fault Handlerß
|
HardFault_Handler, // Hard Fault Handler
|
||||||
MemManage_Handler, // MPU Fault Han`dler
|
MemManage_Handler, // MPU Fault Handler
|
||||||
BusFault_Handler, // Bus Fault Handler
|
BusFault_Handler, // Bus Fault Handler
|
||||||
UsageFault_Handler, // Usage Fault Handler
|
UsageFault_Handler, // Usage Fault Handler
|
||||||
0, // Reserved
|
0, // Reserved
|
||||||
@ -70,12 +73,64 @@ const HandlerType vector_table[] = {
|
|||||||
SysTick_Handler, // SysTick Handler
|
SysTick_Handler, // SysTick Handler
|
||||||
// Unused
|
// 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
|
||||||
|
|
||||||
namespace LIBC_NAMESPACE_DECL {
|
namespace LIBC_NAMESPACE_DECL {
|
||||||
[[noreturn]] void do_start() {
|
[[noreturn]] void do_start() {
|
||||||
// FIXME: set up the QEMU test environment
|
// 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
|
// Perform the equivalent of scatterloading
|
||||||
LIBC_NAMESPACE::memcpy(__data_start, __data_source,
|
LIBC_NAMESPACE::memcpy(__data_start, __data_source,
|
||||||
reinterpret_cast<uintptr_t>(__data_size));
|
reinterpret_cast<uintptr_t>(__data_size));
|
||||||
@ -89,7 +144,13 @@ namespace LIBC_NAMESPACE_DECL {
|
|||||||
}
|
}
|
||||||
} // 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("mov sp, %0" : : "r"(&__stack));
|
||||||
asm volatile("bl %0" : : "X"(LIBC_NAMESPACE::do_start));
|
asm volatile("bl %0" : : "X"(LIBC_NAMESPACE::do_start));
|
||||||
}
|
}
|
||||||
|
} // extern "C"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user