Couldn't you mark kernel::main() as #[no_mangle] extern "C" fn main() (removes name mangling and directly exports the main symbol with the C ABI) then execute a jump/call to the main() function like calling any other C function? Then during compilation the linker should make sure your _start calls kernel::main().
As far as I can tell this is a perfectly legitimate thing to do. For example, the entry point to a normal OS kernel is often written in assembly to set up the hardware, then it'll jump to some function written in C (or Rust!) to begin the kernel proper.
Yep, that what I was initially doing. I just wanted to jump to main() from inline assembly block. And I managed to do it -- I just had to add use kernel::main;, so now the asm block looks like this:
mod kernel;
use kernel::main;
#[no_mangle]
fn _start() {
unsafe {
asm!("
mrs x0, mpidr_el1
and x0, x0, 3
cbz x0, 2f
1: wfe
b 1b
2: adr x0, _start
mov sp, x0
adr x0, main
br x0 // jump to kernel::main
");
}
}
The downside -- I started receiving warning: unused import: kernel::main but it can be turned off