Call Rust from assembly instead, relocate linker script

This commit is contained in:
gil 2024-05-19 20:03:03 -05:00
parent d447232b0b
commit e5b51efb87
6 changed files with 50 additions and 86 deletions

View file

@ -24,4 +24,5 @@ runner = """ qemu-system-riscv64
-s
-nographic
-serial mon:stdio
-bios """
-bios none
-kernel """

View file

@ -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");
}

View file

@ -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
View 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

View file

@ -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]

View file

@ -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