Call Rust from assembly instead, relocate linker script
This commit is contained in:
parent
d447232b0b
commit
e5b51efb87
|
@ -24,4 +24,5 @@ runner = """ qemu-system-riscv64
|
|||
-s
|
||||
-nographic
|
||||
-serial mon:stdio
|
||||
-bios """
|
||||
-bios none
|
||||
-kernel """
|
2
build.rs
2
build.rs
|
@ -2,7 +2,7 @@
|
|||
|
||||
fn main() {
|
||||
// Tell ld to use linker script.
|
||||
println!("cargo::rustc-link-arg=-Tsrc/script.lds");
|
||||
println!("cargo::rustc-link-arg=-Tlds/kernel.lds");
|
||||
// Don't do any magic linker stuff.
|
||||
println!("cargo::rustc-link-arg=--omagic");
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* src/script.lds */
|
||||
|
||||
OUTPUT_ARCH("riscv")
|
||||
ENTRY(_enter)
|
||||
ENTRY(_entry)
|
||||
|
||||
MEMORY {
|
||||
ram (wxa) : ORIGIN = 0x80000000, LENGTH = 128M
|
43
src/entry.S
Normal file
43
src/entry.S
Normal file
|
@ -0,0 +1,43 @@
|
|||
# entry.S
|
||||
.option norvc
|
||||
.section .data
|
||||
|
||||
.section .text.init
|
||||
.global _entry
|
||||
_entry:
|
||||
# Any hardware threads (hart) that are not bootstrapping
|
||||
# need to wait for an IPI
|
||||
csrr t0, mhartid
|
||||
bnez t0, 3f
|
||||
|
||||
# SATP should be zero, but let's make sure
|
||||
csrw satp, zero
|
||||
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, _global_pointer
|
||||
.option pop
|
||||
|
||||
li t5, 0xffff
|
||||
csrw medeleg, t5
|
||||
csrw mideleg, t5
|
||||
|
||||
la sp, _stack_end
|
||||
|
||||
li t0, (0b11 << 11) | (1 << 7) | (1 << 3)
|
||||
csrw mstatus, t0
|
||||
|
||||
la t0, _bss_start
|
||||
la t1, _bss_end
|
||||
bgeu t0, t1, 2f
|
||||
1:
|
||||
sb zero, 0(t0)
|
||||
addi t0, t0, 1
|
||||
bne t0, t1, 1b
|
||||
2:
|
||||
j 4f
|
||||
3:
|
||||
wfi
|
||||
j 3b
|
||||
4:
|
||||
tail start
|
10
src/entry.rs
10
src/entry.rs
|
@ -56,16 +56,6 @@ unsafe extern "C" fn entry() {
|
|||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn start() {
|
||||
// TODO start (start for hart 0)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn hstart() {
|
||||
// TODO starth (start for other harts)
|
||||
}
|
||||
|
||||
// TODO ...then kinit
|
||||
|
||||
#[no_mangle]
|
||||
|
|
76
src/main.rs
76
src/main.rs
|
@ -10,79 +10,9 @@ mod heap;
|
|||
mod trap;
|
||||
mod uart;
|
||||
|
||||
#[naked]
|
||||
core::arch::global_asm!(include_str!("entry.S"));
|
||||
|
||||
#[no_mangle]
|
||||
#[link_section = ".text.init"]
|
||||
unsafe extern "C" fn _enter() -> ! {
|
||||
// FIXME see if possible to replace this somehow...
|
||||
use core::arch::asm;
|
||||
asm!(
|
||||
// load hartid into `tp``
|
||||
// if hartid =/= 0, then jump to busy loop
|
||||
"csrr tp, mhartid",
|
||||
"bnez tp, 3f",
|
||||
|
||||
// before we use the `la` pseudo-instruction for the first time,
|
||||
// we need to set `gp` (look up linker relaxation)
|
||||
".option push", // pushes the current option stack
|
||||
".option norelax", // disable relaxation so we can properly set `gp`
|
||||
// this instruction compiles to:
|
||||
// 1:
|
||||
// auipc gp, %pcrel_hi(_global_pointer)
|
||||
// addi gp, gp, %pcrel_lo(1b)
|
||||
// if relaxation were on, this would simply be `mv gp, gp` or `addi gp, gp, 0`
|
||||
"la gp, _global_pointer",
|
||||
".option pop", // pops the current option stack
|
||||
|
||||
// delegate all traps to S-mode trap handler
|
||||
"li t5, 0xffff",
|
||||
"csrw medeleg, t5", // delegate all machine exceptions
|
||||
"csrw mideleg, t5", // delegate all machine interrupts
|
||||
|
||||
// set the stack pointer
|
||||
"la sp, _stack_end",
|
||||
|
||||
// Make sure machine mode is set, and enable coarse interrupts
|
||||
"li t0, (0b11 << 11) | (1 << 7) | (1 << 3)",
|
||||
"csrw mstatus, t0",
|
||||
|
||||
// Set mtvec to the location of our trap handler function
|
||||
"la t1, {trap_vector}",
|
||||
"csrw mtvec, t1",
|
||||
|
||||
// Set MSIE, MTIE, and MEIE on machine interrupt enable CSR:
|
||||
// (1 << 3) = MSIE to enable machine-/M-mode software interrupts
|
||||
// | (1 << 7) = MTIE to enable M-mode timer interrupts (disabled for now)
|
||||
// | (1 << 11) = MEIE to enable M-mode external interrupts
|
||||
"li t2, (1 << 3) | (1 << 11)",
|
||||
"csrw mie, t2",
|
||||
|
||||
// clear the BSS
|
||||
"la t0, _bss_start",
|
||||
"la t1, _bss_end",
|
||||
"bgeu t0, t1, 2f",
|
||||
"1:",
|
||||
"sb zero, 0(t0)",
|
||||
"addi t0, t0, 1",
|
||||
"bne t0, t1, 1b",
|
||||
"2:",
|
||||
"j 4f",
|
||||
// BSS is clear!
|
||||
|
||||
// busy loop if hartid =/= 0
|
||||
"3:",
|
||||
"wfi", // wait for interrupt (or nop)
|
||||
"j 3b",
|
||||
|
||||
"4:",
|
||||
// "tail-call" to {start} (call without saving a return address)
|
||||
"tail {start}",
|
||||
start = sym start, // {start} refers to the function [start] below
|
||||
trap_vector = sym trap::trap_handler, // {trap_vector} refers to function [trap::trap_handler]
|
||||
options(noreturn) // we must handle "returning" from assembly
|
||||
);
|
||||
}
|
||||
|
||||
extern "C" fn start() -> ! {
|
||||
// UNSAFE: Called exactly once, right here.
|
||||
unsafe { heap::init() };
|
||||
|
@ -125,4 +55,4 @@ extern "C" fn abort() -> ! {
|
|||
loop { riscv::asm::wfi(); }
|
||||
}
|
||||
|
||||
// TODO unit testing
|
||||
// TODO unit testing
|
Loading…
Reference in a new issue