// SPDX-License-Identifier: MIT OR Apache-2.0 // // Copyright (c) 2021-2022 Andre Richter //-------------------------------------------------------------------------------------------------- // Definitions //-------------------------------------------------------------------------------------------------- // Load the address of a symbol into a register, PC-relative. // // The symbol must lie within +/- 4 GiB of the Program Counter. // // # Resources // // - https://sourceware.org/binutils/docs-2.36/as/AArch64_002dRelocations.html .macro ADR_REL register, symbol adrp \register, \symbol add \register, \register, #:lo12:\symbol .endm //-------------------------------------------------------------------------------------------------- // Public Code //-------------------------------------------------------------------------------------------------- .section .text._start //------------------------------------------------------------------------------ // fn _start() //------------------------------------------------------------------------------ _start: // Only proceed if the core executes in EL2. Park it otherwise. mrs x0, CurrentEL cmp x0, {CONST_CURRENTEL_EL2} b.ne .L_parking_loop // Only proceed on the boot core. Park it otherwise. mrs x1, MPIDR_EL1 and x1, x1, {CONST_CORE_ID_MASK} ldr x2, BOOT_CORE_ID // provided by bsp/__board_name__/cpu.rs cmp x1, x2 b.ne .L_parking_loop // If execution reaches here, it is the boot core. // Initialize DRAM. ADR_REL x0, __bss_start ADR_REL x1, __bss_end_exclusive .L_bss_init_loop: cmp x0, x1 b.eq .L_prepare_rust stp xzr, xzr, [x0], #16 b .L_bss_init_loop // Prepare the jump to Rust code. .L_prepare_rust: // Set the stack pointer. This ensures that any code in EL2 that needs the stack will work. ADR_REL x0, __boot_core_stack_end_exclusive mov sp, x0 // Read the CPU's timer counter frequency and store it in ARCH_TIMER_COUNTER_FREQUENCY. // Abort if the frequency read back as 0. ADR_REL x1, ARCH_TIMER_COUNTER_FREQUENCY // provided by aarch64/time.rs mrs x2, CNTFRQ_EL0 cmp x2, xzr b.eq .L_parking_loop str w2, [x1] // Jump to Rust code. x0 holds the function argument provided to _start_rust(). b _start_rust // Infinitely wait for events (aka "park the core"). .L_parking_loop: wfe b .L_parking_loop .size _start, . - _start .type _start, function .global _start