use super::{START_PERCORE, STOP_PERCORE};
use core::arch::naked_asm;
#[allow(improper_ctypes)]
unsafe extern "Rust" {
#[link_name = "__start_percore_secondary"]
pub safe static START_PERCORE_SECONDARY: ();
#[link_name = "__stop_percore_secondary"]
pub safe static STOP_PERCORE_SECONDARY: ();
}
#[unsafe(naked)]
pub unsafe extern "C" fn percore_copy_secondary_data() {
naked_asm!(
"bti c
adrp x0, {START_PERCORE}
add x0, x0, :lo12:{START_PERCORE}
adrp x1, {STOP_PERCORE}
add x1, x1, :lo12:{STOP_PERCORE}
adrp x2, {START_PERCORE_SECONDARY}
add x2, x2, :lo12:{START_PERCORE_SECONDARY}
adrp x3, {STOP_PERCORE_SECONDARY}
add x3, x3, :lo12:{STOP_PERCORE_SECONDARY}
/* Check whether the percore section is empty. */
cmp x0, x1
b.eq 3f
/* Check whether the percore_secondary section is empty, i.e. no secondary cores */
cmp x2, x3
b.eq 3f
/* Save source start pointer */
mov x4, x0
/*
* Per-core loop
* X0: src
* X1: src_end
* X2: dst
* X3: dst_end (end of the percore area of the last core)
* X5, X6: data temp
*/
1:
mov x0, x4
/* Data loop */
2:
ldp x5, x6, [x0], #16
stp x5, x6, [x2], #16
/* src == src_end */
cmp x0, x1
b.ne 2b
/* dst == dst_end */
cmp x2, x3
b.ne 1b
3:
ret",
START_PERCORE = sym START_PERCORE,
STOP_PERCORE = sym STOP_PERCORE,
START_PERCORE_SECONDARY = sym START_PERCORE_SECONDARY,
STOP_PERCORE_SECONDARY = sym STOP_PERCORE_SECONDARY,
)
}
#[unsafe(naked)]
pub extern "C" fn percore_calculate_local_offset(core_index: usize) -> isize {
naked_asm!(
"bti c
adrp x1, {START_PERCORE}
add x1, x1, :lo12:{START_PERCORE}
adrp x2, {STOP_PERCORE}
add x2, x2, :lo12:{STOP_PERCORE}
sub x1, x2, x1
mul x0, x0, x1
ret",
START_PERCORE = sym START_PERCORE,
STOP_PERCORE = sym STOP_PERCORE,
)
}