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
|
-s
|
||||||
-nographic
|
-nographic
|
||||||
-serial mon:stdio
|
-serial mon:stdio
|
||||||
-bios """
|
-bios none
|
||||||
|
-kernel """
|
2
build.rs
2
build.rs
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Tell ld to use linker script.
|
// 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.
|
// Don't do any magic linker stuff.
|
||||||
println!("cargo::rustc-link-arg=--omagic");
|
println!("cargo::rustc-link-arg=--omagic");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* src/script.lds */
|
/* src/script.lds */
|
||||||
|
|
||||||
OUTPUT_ARCH("riscv")
|
OUTPUT_ARCH("riscv")
|
||||||
ENTRY(_enter)
|
ENTRY(_entry)
|
||||||
|
|
||||||
MEMORY {
|
MEMORY {
|
||||||
ram (wxa) : ORIGIN = 0x80000000, LENGTH = 128M
|
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
|
// TODO ...then kinit
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|
76
src/main.rs
76
src/main.rs
|
@ -10,79 +10,9 @@ mod heap;
|
||||||
mod trap;
|
mod trap;
|
||||||
mod uart;
|
mod uart;
|
||||||
|
|
||||||
#[naked]
|
core::arch::global_asm!(include_str!("entry.S"));
|
||||||
|
|
||||||
#[no_mangle]
|
#[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() -> ! {
|
extern "C" fn start() -> ! {
|
||||||
// UNSAFE: Called exactly once, right here.
|
// UNSAFE: Called exactly once, right here.
|
||||||
unsafe { heap::init() };
|
unsafe { heap::init() };
|
||||||
|
@ -125,4 +55,4 @@ extern "C" fn abort() -> ! {
|
||||||
loop { riscv::asm::wfi(); }
|
loop { riscv::asm::wfi(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO unit testing
|
// TODO unit testing
|
Loading…
Reference in a new issue