#[cfg(any(
arm_architecture = "v7-a",
all(arm_architecture = "v8-r", not(feature = "el2-mode")),
))]
use aarch32_cpu::register::{cpsr::ProcessorMode, Cpsr, Hactlr};
#[cfg(any(
arm_architecture = "v7-a",
all(arm_architecture = "v8-r", not(feature = "el2-mode")),
))]
core::arch::global_asm!(
r#"
// Work around https://github.com/rust-lang/rust/issues/127269
.fpu vfp2
.cpu cortex-r52
.pushsection .text.default_start
.arm
.global _default_start
.type _default_start, %function
.p2align 2
_default_start:
// Read MPIDR into R0
mrc p15, 0, r0, c0, c0, 5
// Core ID in bottom 8 bits
and r0, r0, 0xFF
// Are we in EL2? If not, skip the EL2 setup portion
mrs r1, cpsr
and r1, r1, 0x1F
cmp r1, {cpsr_mode_hyp}
bne 1f
// Set up the Hyp stack for this core
ldr sp, =_hyp_stack_high_end
ldr r1, =_hyp_stack_size
muls r1, r1, r0
subs sp, sp, r1
// Set the HVBAR (for EL2) to _vector_table
ldr r1, =_vector_table
mcr p15, 4, r1, c12, c0, 0
// Configure HACTLR to let us enter EL1
mrc p15, 4, r1, c1, c0, 1
mov r2, {hactlr_bits}
orr r1, r1, r2
mcr p15, 4, r1, c1, c0, 1
// Program the SPSR - enter system mode (0x1F) in Arm mode with IRQ, FIQ masked
mov r1, {sys_mode}
msr spsr_hyp, r1
adr r1, 1f
msr elr_hyp, r1
dsb
isb
eret
1:
// Set the VBAR (for EL1) to _vector_table.
ldr r1, =_vector_table
mcr p15, 0, r1, c12, c0, 0
// Check if core ID is zero
cmp r0, 0
bne 2f
// Primary core (core 0) can do normal start-up
mov r4, r0
bl _asm_init_segments
mov r0, r4
b _asm_core_start
2:
// Secondary core needs to spin until some magic flag is set
mov r4, r0
bl _asm_secondary_core_park
mov r0, r4
b _asm_core_start
.size _default_start, . - _default_start
.popsection
"#,
cpsr_mode_hyp = const ProcessorMode::Hyp as u8,
hactlr_bits = const {
Hactlr::new_with_raw_value(0)
.with_cpuactlr(true)
.with_cdbgdci(true)
.with_flashifregionr(true)
.with_periphpregionr(true)
.with_qosr(true)
.with_bustimeoutr(true)
.with_intmonr(true)
.with_err(true)
.with_testr1(true)
.raw_value()
},
sys_mode = const {
Cpsr::new_with_raw_value(0)
.with_mode(ProcessorMode::Sys)
.with_i(true)
.with_f(true)
.raw_value()
}
);
#[unsafe(naked)]
#[unsafe(no_mangle)]
extern "C" fn _asm_default_secondary_core_park() {
core::arch::naked_asm!(
"b ."
)
}