From b44847716e6ac835314c2d307f61d7f4ec3d204c Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Mon, 18 Aug 2025 19:11:50 +0300 Subject: [PATCH 1/2] Move entry.S to naked functions Naked functions were stabilised in 1.88.0 [0], use them for entry.S code. This will make it easier for extending entry code with compile-time options in the future. [0]: https://blog.rust-lang.org/2025/07/03/stabilizing-naked-functions/ Signed-off-by: Manos Pitsidianakis --- Cargo.toml | 1 + src/entry.S | 77 ------------------------------------------------ src/entry.rs | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 13 ++------ 4 files changed, 86 insertions(+), 88 deletions(-) delete mode 100644 src/entry.S create mode 100644 src/entry.rs diff --git a/Cargo.toml b/Cargo.toml index 9a1e823..7d1b654 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ authors = ["Andrew Walbran "] repository = "https://github.com/google/aarch64-rt" keywords = ["arm", "aarch64", "cortex-a"] categories = ["embedded", "no-std"] +rust-version = "1.88.0" [dependencies] smccc = { version = "0.2.2", optional = true } diff --git a/src/entry.S b/src/entry.S deleted file mode 100644 index ab7077e..0000000 --- a/src/entry.S +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2025 The aarch64-rt Authors. - * - * This project is dual-licensed under Apache 2.0 and MIT terms. - * See LICENSE-APACHE and LICENSE-MIT for details. - */ - -.macro adr_l, reg:req, sym:req - adrp \reg, \sym - add \reg, \reg, :lo12:\sym -.endm - -/** - * This is a generic entry point for an image. It carries out the operations required to prepare the - * loaded image to be run. Specifically, it zeroes the bss section using registers x25 and above, - * prepares the stack, enables floating point, and sets up the exception vector. It preserves x0-x3 - * for the Rust entry point, as these may contain boot parameters. - */ -.section .init.entry, "ax" -.global entry -entry: - bl enable_mmu - - /* Disable trapping floating point access in EL1. */ - mrs x30, cpacr_el1 - orr x30, x30, #(0x3 << 20) - msr cpacr_el1, x30 - isb - - /* Zero out the bss section. */ - adr_l x29, bss_begin - adr_l x30, bss_end -0: cmp x29, x30 - b.hs 1f - stp xzr, xzr, [x29], #16 - b 0b - -1: /* Prepare the stack. */ - adr_l x30, boot_stack_end - mov sp, x30 - - /* Call into Rust code. */ - b rust_entry - -/** - * Entry point for secondary cores. - * - * This requires that an initial stack pointer value be passed in x0, and the stack must contain - * the address of a Rust entry point to jump to and a parameter value to pass to it. - */ -.global secondary_entry -secondary_entry: - bl enable_mmu - - /* Disable trapping floating point access in EL1. */ - mrs x30, cpacr_el1 - orr x30, x30, #(0x3 << 20) - msr cpacr_el1, x30 - isb - - /* Set the stack pointer which was passed. */ - mov sp, x0 - - /* - * Load Rust entry point address and argument from the bottom of the stack into callee-saved - * registers. - */ - ldp x19, x20, [sp, #-16] - - /* Set the exception vector. */ - bl set_exception_vector - - /* Pass argument to Rust entry point. */ - mov x0, x19 - - /* Call into Rust code. */ - br x20 diff --git a/src/entry.rs b/src/entry.rs new file mode 100644 index 0000000..1ef377f --- /dev/null +++ b/src/entry.rs @@ -0,0 +1,83 @@ +// Copyright 2025 The aarch64-rt Authors. +// This project is dual-licensed under Apache 2.0 and MIT terms. +// See LICENSE-APACHE and LICENSE-MIT for details. + +//! Entrypoint code + +use core::arch::naked_asm; + +/// This is a generic entry point for an image. It carries out the operations required to prepare the +/// loaded image to be run. Specifically, it zeroes the bss section using registers x25 and above, +/// prepares the stack, enables floating point, and sets up the exception vector. It preserves x0-x3 +/// for the Rust entry point, as these may contain boot parameters. +/// +/// # Safety +/// +/// This function is marked unsafe because it should never be called by anyone. The linker is +/// responsible for setting it as the entry function. +#[unsafe(naked)] +#[unsafe(link_section = ".init.entry")] +#[unsafe(export_name = "entry")] +unsafe extern "C" fn entry() -> ! { + naked_asm!( + ".macro adr_l, reg:req, sym:req", + r"adrp \reg, \sym", + r"add \reg, \reg, :lo12:\sym", + ".endm", + "bl enable_mmu", + // Disable trapping floating point access in EL1. + "mrs x30, cpacr_el1", + "orr x30, x30, #(0x3 << 20)", + "msr cpacr_el1, x30", + "isb", + // Zero out the bss section. + "adr_l x29, bss_begin", + "adr_l x30, bss_end", + "0:", + "cmp x29, x30", + "b.hs 1f", + "stp xzr, xzr, [x29], #16", + "b 0b", + "1:", + // Prepare the stack. + "adr_l x30, boot_stack_end", + "mov sp, x30", + // Call into Rust code. + "b {rust_entry}", + rust_entry = sym crate::rust_entry, + ) +} + +/// An assembly entry point for secondary cores. +/// +/// It will enable the MMU, disable trapping of floating point instructions, initialise the +/// stack pointer to `stack_end` and then jump to the function pointer at the bottom of the +/// stack with the u64 value second on the stack as a parameter. +/// +/// # Safety +/// +/// This requires that an initial stack pointer value be passed in `x0`, and the stack must contain +/// the address of a Rust entry point to jump to and a parameter value to pass to it. +#[unsafe(naked)] +pub unsafe extern "C" fn secondary_entry(stack_end: *mut u64) -> ! { + naked_asm!( + "bl enable_mmu", + // Disable trapping floating point access in EL1. + "mrs x30, cpacr_el1", + "orr x30, x30, #(0x3 << 20)", + "msr cpacr_el1, x30", + "isb", + // Set the stack pointer which was passed. + "mov sp, x0", + // Load Rust entry point address and argument from the bottom of the stack into + // callee-saved registers. + "ldp x19, x20, [sp, #-16]", + // Set the exception vector. + "bl {set_exception_vector}", + // Pass argument to Rust entry point. + "mov x0, x19", + // Call into Rust code. + "br x20", + set_exception_vector = sym crate::set_exception_vector, + ) +} diff --git a/src/lib.rs b/src/lib.rs index 1a19761..dd09720 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,32 +15,23 @@ ))] compile_error!("Only one `el` feature may be enabled at once."); +mod entry; #[cfg(feature = "initial-pagetable")] mod pagetable; #[cfg(any(feature = "exceptions", feature = "psci"))] use core::arch::asm; use core::arch::global_asm; +pub use entry::secondary_entry; #[cfg(feature = "initial-pagetable")] pub use pagetable::{DEFAULT_MAIR, DEFAULT_SCTLR, DEFAULT_TCR, InitialPagetable}; -global_asm!(include_str!("entry.S")); - #[cfg(not(feature = "initial-pagetable"))] global_asm!(include_str!("dummy_enable_mmu.S"),); #[cfg(feature = "exceptions")] global_asm!(include_str!("exceptions.S")); -unsafe extern "C" { - /// An assembly entry point for secondary cores. - /// - /// It will enable the MMU, disable trapping of floating point instructions, initialise the - /// stack pointer to `stack_end` and then jump to the function pointer at the bottom of the - /// stack with the u64 value second on the stack as a parameter. - pub unsafe fn secondary_entry(stack_end: *mut u64) -> !; -} - /// Sets the appropriate vbar to point to our `vector_table`, if the `exceptions` feature is /// enabled. #[unsafe(no_mangle)] From 993199df18d411dbaeb8daaa639c3d44ae1b0791 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Mon, 18 Aug 2025 19:17:01 +0300 Subject: [PATCH 2/2] Replace dummy_enable_mmu.S with naked function Signed-off-by: Manos Pitsidianakis --- src/dummy_enable_mmu.S | 11 ----------- src/lib.rs | 7 ++++++- 2 files changed, 6 insertions(+), 12 deletions(-) delete mode 100644 src/dummy_enable_mmu.S diff --git a/src/dummy_enable_mmu.S b/src/dummy_enable_mmu.S deleted file mode 100644 index 520e804..0000000 --- a/src/dummy_enable_mmu.S +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2025 The aarch64-rt Authors. - * - * This project is dual-licensed under Apache 2.0 and MIT terms. - * See LICENSE-APACHE and LICENSE-MIT for details. - */ - -.section .init, "ax" -.global enable_mmu -enable_mmu: - ret diff --git a/src/lib.rs b/src/lib.rs index dd09720..ea99195 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,12 @@ pub use entry::secondary_entry; pub use pagetable::{DEFAULT_MAIR, DEFAULT_SCTLR, DEFAULT_TCR, InitialPagetable}; #[cfg(not(feature = "initial-pagetable"))] -global_asm!(include_str!("dummy_enable_mmu.S"),); +#[unsafe(naked)] +#[unsafe(link_section = ".init")] +#[unsafe(export_name = "enable_mmu")] +extern "C" fn enable_mmu() { + core::arch::naked_asm!("ret") +} #[cfg(feature = "exceptions")] global_asm!(include_str!("exceptions.S"));