Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite the ARM entry points to be pure assembly #699

Open
tomaka opened this issue Jan 2, 2021 · 0 comments
Open

Rewrite the ARM entry points to be pure assembly #699

tomaka opened this issue Jan 2, 2021 · 0 comments
Labels
A-standalone-arm Issues specific to ARM help wanted Extra attention is needed

Comments

@tomaka
Copy link
Owner

tomaka commented Jan 2, 2021

/// 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.

@tomaka tomaka added help wanted Extra attention is needed A-standalone-arm Issues specific to ARM labels Jan 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-standalone-arm Issues specific to ARM help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

1 participant