tomaka/redshirt

Rewrite the ARM entry points to be pure assembly

tomaka opened this issue · 0 comments

/// This is the main entry point of the kernel for ARM 32bits architectures.
#[cfg(target_arch = "arm")]
#[export_name = "_start"]
#[naked]
unsafe extern "C" fn entry_point_arm32() -> ! {
// TODO: always fails :-/
/*#[cfg(not(any(target_feature = "armv7-a", target_feature = "armv7-r")))]
compile_error!("The ARMv7-A or ARMv7-R instruction sets must be enabled");*/
// Detect which CPU we are.
//
// See sections B4.1.106 and B6.1.67 of the ARM® Architecture Reference Manual
// (ARMv7-A and ARMv7-R edition).
//
// This is specific to ARMv7-A and ARMv7-R, hence the compile_error! above.
asm!(
"
mrc p15, 0, r5, c0, c0, 5
and r5, r5, #3
cmp r5, #0
bne {}
",
sym halt,
out("r3") _, out("r5") _,
options(nomem, nostack, preserves_flags)
);
// Only one CPU reaches here.
// Zero the memory requested to be zero'ed.
// TODO: that's illegal ; naked functions must only contain an asm! block (for good reasons)
let mut ptr = &mut $memory_zeroing_start as *mut u8;
while ptr < &mut $memory_zeroing_end as *mut u8 {
ptr.write_volatile(0);
ptr = ptr.add(1);
}
// Set up the stack and jump to the entry point.
asm!("
.comm stack, 0x400000, 8
ldr sp, =stack+0x400000
b {}
",
sym cpu_enter,
options(noreturn)
)
}
/// This is the main entry point of the kernel for ARM 64bits architectures.
#[cfg(target_arch = "aarch64")]
#[export_name = "_start"]
#[naked]
unsafe extern "C" fn entry_point_arm64() -> ! {
// TODO: review this
asm!(
"
mrs x6, MPIDR_EL1
and x6, x6, #0x3
cbz x6, L0
b {}
L0: nop
",
sym halt,
out("x6") _,
options(nomem, nostack)
);
// Only one CPU reaches here.
// Zero the memory requested to be zero'ed.
// TODO: that's illegal ; naked functions must only contain an asm! block (for good reasons)
let mut ptr = &mut $memory_zeroing_start as *mut u8;
while ptr < &mut $memory_zeroing_end as *mut u8 {
ptr.write_volatile(0);
ptr = ptr.add(1);
}
// Set up the stack and jump to `cpu_enter`.
asm!(
"
.comm stack, 0x400000, 8
ldr x5, =stack+0x400000
mov sp, x5
b {}
", sym cpu_enter, options(noreturn))
}

Since they are #[naked] functions, they can't use Rust code.

The BSS needs to be cleared, but since the BSS includes the stack, this clearing can only be done before jumping to the Rust code, and thus needs to be in assembly.

I personally have a lot of trouble 1) navigating the ARM assembly documentation 2) putting the start and end offsets into registers. For 2), you'd normally use the adrl pseudo-opcode, but LLVM doesn't support it.