Update entry code, switch to spin crate for spinlocks
This commit is contained in:
parent
e5b51efb87
commit
5dfd3f780f
22
Cargo.lock
generated
22
Cargo.lock
generated
|
@ -26,7 +26,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"linked_list_allocator",
|
||||
"riscv",
|
||||
"spinning_top 0.3.0",
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -35,7 +35,7 @@ version = "0.10.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286"
|
||||
dependencies = [
|
||||
"spinning_top 0.2.5",
|
||||
"spinning_top",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -64,6 +64,15 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spinning_top"
|
||||
version = "0.2.5"
|
||||
|
@ -72,12 +81,3 @@ checksum = "5b9eb1a2f4c41445a3a0ff9abc5221c5fcd28e1f13cd7c0397706f9ac938ddb0"
|
|||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spinning_top"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
|
|
@ -6,4 +6,4 @@ edition = "2021"
|
|||
[dependencies]
|
||||
linked_list_allocator = "0.10.5"
|
||||
riscv = "0.11.1"
|
||||
spinning_top = "0.3.0"
|
||||
spin = "0.9.8"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* src/script.lds */
|
||||
/* lds/kernel.lds */
|
||||
|
||||
OUTPUT_ARCH("riscv")
|
||||
ENTRY(_entry)
|
||||
|
|
139
src/entry.rs
139
src/entry.rs
|
@ -1,92 +1,86 @@
|
|||
// src/entry.rs
|
||||
|
||||
/// This is the first function called when the system boots. In this function,
|
||||
/// we set up important control status registers (CSR) such as `mstatus` and
|
||||
/// `satp`. The global, stack, and thread pointers are also configured here.
|
||||
static READY: spin::Once<()> = spin::Once::new();
|
||||
|
||||
/// After some initialization in asm/entry.S, the kernel will jump here and
|
||||
/// each hart will have its own setup sequence.
|
||||
#[no_mangle]
|
||||
#[link_section = ".text.init"]
|
||||
unsafe extern "C" fn entry() {
|
||||
unsafe extern "C" fn _start() {
|
||||
use core::arch::asm;
|
||||
use riscv::register::{mhartid, mstatus, satp, sstatus};
|
||||
use riscv::register::{mepc, mstatus, satp, sie, sstatus};
|
||||
|
||||
// Global pointer `gp`
|
||||
//
|
||||
// Push current option stack to temporarily disable relaxation, load
|
||||
// _global_pointer symbol (provided by linker), then pop option stack.
|
||||
//
|
||||
// Important to keep relaxation off for this instruction, so that
|
||||
// the instruction is emitted as:
|
||||
// 1:
|
||||
// auipc gp, %pcrel_hi(_global_pointer)
|
||||
// addi gp, gp, %pcrel_lo(1b)"
|
||||
// instead of:
|
||||
// mv gp, gp
|
||||
asm!(
|
||||
".option push",
|
||||
".option norelax",
|
||||
"la gp, _global_pointer",
|
||||
".option pop",
|
||||
);
|
||||
|
||||
// Stack pointer `sp`
|
||||
//
|
||||
// Set up the stack pointer for each hart, since each hart will have its own stack.
|
||||
asm!("la sp, _stack_end");
|
||||
|
||||
// Thread pointer `tp`
|
||||
//
|
||||
// Set up the thread pointer, which will hold the hart id for each hart.
|
||||
write_tp(&mhartid::read());
|
||||
|
||||
satp::write(0);
|
||||
|
||||
mstatus::set_mpp(mstatus::MPP::Machine);
|
||||
// Set previous privilege for all harts to M-mode, set previous interrupt
|
||||
// enable, and set floating-point unit to initial state
|
||||
mstatus::set_mpp(mstatus::MPP::Supervisor);
|
||||
mstatus::set_mpie();
|
||||
mstatus::set_fs(sstatus::FS::Initial);
|
||||
|
||||
asm!(
|
||||
"csrw mie, x0",
|
||||
// Store ref to main in M-mode exception program counter
|
||||
mepc::write(main as usize);
|
||||
|
||||
"la t1, {kinit}",
|
||||
"csrw mepc, t1",
|
||||
// Disable paging
|
||||
satp::write(0);
|
||||
|
||||
"la ra, 2f",
|
||||
"mret",
|
||||
"2:",
|
||||
kinit = sym kinit,
|
||||
);
|
||||
// Delegate all traps to S-mode, using inline assembly since we have not
|
||||
// provided a wrapper for it yet
|
||||
asm!("li t0, 0xffff", "csrw medeleg, t0", "csrw mideleg, t0",);
|
||||
|
||||
// Enable S-mode external, timer, and software interrupts
|
||||
sie::set_sext();
|
||||
sie::set_stimer();
|
||||
sie::set_ssoft();
|
||||
|
||||
// TODO configure PMP
|
||||
// TODO timer init
|
||||
|
||||
// Use mret to jump to main
|
||||
asm!("mret");
|
||||
}
|
||||
|
||||
// TODO ...then kinit
|
||||
extern "C" fn main() {
|
||||
use riscv::interrupt;
|
||||
use riscv::register::{mstatus, sstatus};
|
||||
|
||||
if hartid() == 0 {
|
||||
READY.call_once(|| {
|
||||
// Disable machine interrupts while initializing
|
||||
interrupt::machine::disable();
|
||||
// TODO Initialize console
|
||||
// TODO Write boot message
|
||||
|
||||
// TODO Set up paging
|
||||
// TODO Set up processes
|
||||
|
||||
// TODO Set up trap vectors
|
||||
// TODO Set up PLIC
|
||||
|
||||
kinit();
|
||||
unsafe {
|
||||
mstatus::set_mpp(mstatus::MPP::User);
|
||||
mstatus::set_mpie();
|
||||
mstatus::set_spie();
|
||||
mstatus::set_fs(sstatus::FS::Initial);
|
||||
}
|
||||
|
||||
riscv::asm::fence();
|
||||
});
|
||||
} else {
|
||||
READY.wait();
|
||||
kinit_hart();
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn kinit() {
|
||||
use crate::uart;
|
||||
use core::arch::asm;
|
||||
uart::Device::new(0x1000_0000);
|
||||
|
||||
if read_tp() == 0 {
|
||||
// Clear bss and set stack pointer
|
||||
// Only hart 0 does this
|
||||
unsafe {
|
||||
asm!(
|
||||
"la t0, _bss_start",
|
||||
"la t1, _bss_end",
|
||||
"bgeu t0, t1, 2f",
|
||||
"1:",
|
||||
"sw x0, (t0)", // Store zero as word at t0
|
||||
"addi t0, t0, 4",
|
||||
"bne t0, t1, 1b",
|
||||
"2:",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn kinit_hart() {}
|
||||
|
||||
#[inline]
|
||||
fn read_tp() -> usize {
|
||||
fn hartid() -> usize {
|
||||
use core::arch::asm;
|
||||
let id: usize;
|
||||
unsafe {
|
||||
|
@ -97,14 +91,3 @@ fn read_tp() -> usize {
|
|||
}
|
||||
id
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_tp(id: &usize) {
|
||||
use core::arch::asm;
|
||||
unsafe {
|
||||
asm!(
|
||||
"csrw mhartid, {id}",
|
||||
id = in(reg) id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
37
src/entry_alt.S
Normal file
37
src/entry_alt.S
Normal file
|
@ -0,0 +1,37 @@
|
|||
# entry.S
|
||||
.option norvc
|
||||
.section .data
|
||||
|
||||
.section .text.init
|
||||
.global _entry_alt
|
||||
_entry_alt:
|
||||
# Set global pointer (gp)
|
||||
# Important to have relaxation off for this instruction
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, _global_pointer
|
||||
.option pop
|
||||
|
||||
# Set thread pointer (tp) to hart id
|
||||
csrr tp, mhartid
|
||||
|
||||
# Set stack pointer (sp) for all harts
|
||||
la sp, _stack_end
|
||||
li t0, 0x10000 # Give each hart plenty of space for their stacks
|
||||
mul t0, t0, tp
|
||||
sub sp, sp, t0
|
||||
|
||||
# Jump to start if not hart 0
|
||||
bnez tp, 2f
|
||||
|
||||
# Prepare BSS section if hart 0
|
||||
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:
|
||||
# Tail call Rust start function
|
||||
tail start
|
|
@ -1,9 +1,9 @@
|
|||
// src/uart.rs
|
||||
//! This module provides access to the UART console.
|
||||
|
||||
use spinning_top::Spinlock;
|
||||
use spin::Mutex; // Replaces spinning_top crate
|
||||
|
||||
pub static CONSOLE: Spinlock<Option<Device>> = Spinlock::new(None);
|
||||
pub static CONSOLE: Mutex<Option<Device>> = Mutex::new(None);
|
||||
|
||||
/// Represents an initialised UART device.
|
||||
pub struct Device {
|
||||
|
@ -65,7 +65,7 @@ impl core::fmt::Write for Device {
|
|||
/// # Safety
|
||||
/// `base` must point to the base address of a UART device.
|
||||
pub fn init_console(base: usize) {
|
||||
let mut console: spinning_top::lock_api::MutexGuard<spinning_top::RawSpinlock, Option<Device>> = CONSOLE.lock();
|
||||
let mut console = CONSOLE.lock();
|
||||
*console = Some(Device::new(base));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue