use core::{arch::naked_asm, mem::offset_of};
use crate::StartCoreStack;
#[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",
"mrs x30, cpacr_el1",
"orr x30, x30, #(0x3 << 20)",
"msr cpacr_el1, x30",
"isb",
"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:",
"adr_l x30, boot_stack_end",
"mov sp, x30",
"b {rust_entry}",
rust_entry = sym crate::rust_entry,
)
}
#[unsafe(naked)]
pub unsafe extern "C" fn secondary_entry(stack_end: *mut u64) -> ! {
naked_asm!(
"bl enable_mmu",
"mrs x30, cpacr_el1",
"orr x30, x30, #(0x3 << 20)",
"msr cpacr_el1, x30",
"isb",
"mov sp, x0",
"ldr x19, [sp, #{entry_ptr_offset}]",
"ldr x20, [sp, #{trampoline_ptr_offset}]",
"bl {set_exception_vector}",
"mov x0, x19",
"br x20",
entry_ptr_offset = const offset_of!(StartCoreStack<()>, entry_ptr) as isize
- size_of::<StartCoreStack<()>>() as isize,
trampoline_ptr_offset = const offset_of!(StartCoreStack<()>, trampoline_ptr) as isize
- size_of::<StartCoreStack<()>>() as isize,
set_exception_vector = sym crate::set_exception_vector,
)
}
#[unsafe(naked)]
pub unsafe extern "C" fn warm_boot_entry(context: *const SuspendContext) -> ! {
naked_asm!(
"bl enable_mmu",
"mrs x30, cpacr_el1",
"orr x30, x30, #(0x3 << 20)",
"msr cpacr_el1, x30",
"isb",
"ldr x19, [x0, #{stack_ptr_offset}]",
"ldr x20, [x0, #{entry_offset}]",
"ldr x21, [x0, #{arg_offset}]",
"mov sp, x19",
"bl {set_exception_vector}",
"mov x0, x21",
"br x20",
set_exception_vector = sym crate::set_exception_vector,
stack_ptr_offset = const offset_of!(SuspendContext, stack_ptr),
entry_offset = const offset_of!(SuspendContext, entry),
arg_offset = const offset_of!(SuspendContext, arg),
)
}
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct SuspendContext {
pub stack_ptr: *mut u64,
pub entry: extern "C" fn(u64) -> !,
pub arg: u64,
}