154 lines
3.9 KiB
Rust
154 lines
3.9 KiB
Rust
#![no_std]
|
|
#![no_main]
|
|
|
|
mod board;
|
|
mod hw;
|
|
mod kernel_cell;
|
|
mod mmu;
|
|
mod platform;
|
|
mod trap;
|
|
|
|
use core::arch::global_asm;
|
|
use hw::uart::Uart;
|
|
use kernel_cell::KernelCell;
|
|
|
|
static KERNEL: KernelCell<kernel::Kernel<platform::RiscVPlatform>> = KernelCell::uninit();
|
|
|
|
pub fn kernel_ref() -> &'static mut kernel::Kernel<platform::RiscVPlatform> {
|
|
KERNEL.get_mut()
|
|
}
|
|
|
|
global_asm!(
|
|
r#"
|
|
.section .text.entry
|
|
.globl _start
|
|
_start:
|
|
la sp, _stack_top
|
|
call kmain
|
|
spin:
|
|
wfi
|
|
j spin
|
|
"#
|
|
);
|
|
|
|
unsafe extern "C" {
|
|
static _bss_start: u8;
|
|
static _bss_end: u8;
|
|
static _heap_start: u8;
|
|
}
|
|
|
|
fn zero_bss() {
|
|
unsafe {
|
|
let start = &_bss_start as *const u8 as *mut u8;
|
|
let end = &_bss_end as *const u8 as *mut u8;
|
|
let len = end as usize - start as usize;
|
|
core::ptr::write_bytes(start, 0, len);
|
|
}
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
extern "C" fn kmain() -> ! {
|
|
zero_bss();
|
|
|
|
let uart = Uart::new();
|
|
uart.write_str("k-os: booted on RISC-V\n");
|
|
|
|
let heap_start = unsafe { &_heap_start as *const u8 as usize };
|
|
mmu::init_allocator(heap_start);
|
|
let kernel_pt = mmu::init_kernel_page_table();
|
|
mmu::activate(kernel_pt);
|
|
uart.write_str("k-os: MMU enabled (Sv39)\n");
|
|
|
|
trap::init();
|
|
hw::timer::init();
|
|
hw::plic::Plic::init();
|
|
uart.write_str("k-os: traps and timer initialized\n");
|
|
|
|
let riscv_platform = platform::RiscVPlatform::new(kernel_pt as *const mmu::PageTable as usize);
|
|
let pool = domain::memory::page_pool::PagePool::new(
|
|
types::address::PhysicalAddress::from_raw(board::USER_POOL_BASE),
|
|
board::USER_POOL_PAGES,
|
|
);
|
|
KERNEL.init(kernel::Kernel::new(riscv_platform, pool));
|
|
let kern = kernel_ref();
|
|
|
|
let (_pid, _tid) = kern
|
|
.boot(types::bounded::Priority::DEFAULT, types::time::TimeSlice::DEFAULT)
|
|
.unwrap_or_else(|_| loop { unsafe { core::arch::asm!("wfi") }; });
|
|
uart.write_str("k-os: kernel started\n");
|
|
|
|
userspace_demo(&uart, kernel_pt);
|
|
|
|
uart.write_str("k-os: demo complete\n");
|
|
loop {
|
|
unsafe { core::arch::asm!("wfi") };
|
|
}
|
|
}
|
|
|
|
static USER_EXIT_PROGRAM: [u8; 12] = [
|
|
0x93, 0x08, 0x00, 0x01, // addi a7, zero, 16 (SYS_EXIT)
|
|
0x73, 0x00, 0x00, 0x00, // ecall
|
|
0x6f, 0xf0, 0xdf, 0xff, // j -4
|
|
];
|
|
|
|
const USER_VA_RAW: usize = 0x10000;
|
|
|
|
fn userspace_demo(uart: &Uart, kernel_pt: &mmu::PageTable) {
|
|
uart.write_str("k-os: --- userspace demo ---\n");
|
|
|
|
let program_page = mmu::allocator::alloc_zeroed_page();
|
|
unsafe {
|
|
core::ptr::copy_nonoverlapping(
|
|
USER_EXIT_PROGRAM.as_ptr(),
|
|
program_page as *mut u8,
|
|
USER_EXIT_PROGRAM.len(),
|
|
);
|
|
}
|
|
|
|
let user_pt = mmu::create_user_page_table(
|
|
kernel_pt,
|
|
types::address::PhysicalAddress::from_raw(program_page),
|
|
1,
|
|
types::address::VirtualAddress::from_raw(USER_VA_RAW),
|
|
);
|
|
|
|
uart.write_str("k-os: user page table created, entering U-mode\n");
|
|
|
|
mmu::activate(user_pt);
|
|
|
|
let kernel_sp: usize;
|
|
unsafe { core::arch::asm!("mv {0}, sp", out(reg) kernel_sp) };
|
|
trap::set_kernel_stack(kernel_sp);
|
|
|
|
let user_stack = USER_VA_RAW - 8;
|
|
unsafe {
|
|
core::arch::asm!(
|
|
"csrc sstatus, {spp}",
|
|
"csrs sstatus, {spie}",
|
|
"csrw sepc, {entry}",
|
|
"mv sp, {stack}",
|
|
"sret",
|
|
spp = in(reg) 1usize << 8,
|
|
spie = in(reg) 1usize << 5,
|
|
entry = in(reg) USER_VA_RAW,
|
|
stack = in(reg) user_stack,
|
|
options(noreturn),
|
|
);
|
|
}
|
|
}
|
|
|
|
#[panic_handler]
|
|
fn panic(info: &core::panic::PanicInfo) -> ! {
|
|
let uart = Uart::new();
|
|
uart.write_str("PANIC: ");
|
|
if let Some(location) = info.location() {
|
|
uart.write_str(location.file());
|
|
uart.put_char(b':');
|
|
uart.write_dec(location.line() as usize);
|
|
}
|
|
uart.put_char(b'\n');
|
|
loop {
|
|
unsafe { core::arch::asm!("wfi") };
|
|
}
|
|
}
|