/* Copyright 2018 SiFive, Inc */ /* SPDX-License-Identifier: Apache-2.0 */ /* This code executes before _start, which is contained inside the C library. * In embedded systems we want to ensure that _enter, which contains the first * code to be executed, can be loaded at a specific address. To enable this * feature we provide the '.text.metal.init.enter' section, which is * defined to have the first address being where execution should start. */ .section .text.metal.init.enter .global _enter _enter: .cfi_startproc /* Inform the debugger that there is nowhere to backtrace past _enter. */ .cfi_undefined ra /* The absolute first thing that must happen is configuring the global * pointer register, which must be done with relaxation disabled because * it's not valid to obtain the address of any symbol without GP * configured. The C environment might go ahead and do this again, but * that's safe as it's a fixed register. */ .option push .option norelax 1:auipc gp, %pcrel_hi(__global_pointer$) addi gp, gp, %pcrel_lo(1b) .option pop /* Set up a trap vector */ la t0, eos_trap_vector csrw mtvec, t0 /* This is a bare-metal environment and therefor is expected * to define its own stack pointer. We also align the stack pointer here * because the only RISC-V ABI that's currently defined mandates 16-byte * stack alignment. */ la sp, _sp andi sp, sp, -16 /* At this point we can enter the C runtime's startup file. */ call _start /* If we've made it back here then there's probably something wrong. * There's not a whole lot we can do, just try to make some noise. */ la t0, 1f csrw mtvec, t0 1: lw t1, 0(x0) j 1b .cfi_endproc /* The GCC port might not emit a __register_frame_info symbol, which eventually * results in a weak undefined reference that eventually causes crash when it * is dereference early in boot. We really shouldn't need to put this here, * but to deal with what I think is probably a bug in the linker script I'm * going to leave this in for now. At least it's fairly cheap :) */ .weak __register_frame_info .global __register_frame_info .section .text.metal.init.__register_frame_info __register_frame_info: .cfi_startproc ret .cfi_endproc