2020-03-10 21:52:09 +04:00
|
|
|
// Steve Operating System
|
|
|
|
// Stephen Marz
|
|
|
|
// 21 Sep 2019
|
|
|
|
#![no_std]
|
|
|
|
#![feature(panic_info_message,
|
|
|
|
asm,
|
|
|
|
allocator_api,
|
|
|
|
alloc_error_handler,
|
|
|
|
alloc_prelude,
|
|
|
|
const_raw_ptr_to_usize_cast)]
|
|
|
|
|
|
|
|
// #[macro_use]
|
|
|
|
extern crate alloc;
|
|
|
|
// This is experimental and requires alloc_prelude as a feature
|
|
|
|
// use alloc::prelude::v1::*;
|
|
|
|
|
|
|
|
// ///////////////////////////////////
|
|
|
|
// / RUST MACROS
|
|
|
|
// ///////////////////////////////////
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! print
|
|
|
|
{
|
|
|
|
($($args:tt)+) => ({
|
|
|
|
use core::fmt::Write;
|
|
|
|
let _ = write!(crate::uart::Uart::new(0x1000_0000), $($args)+);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! println
|
|
|
|
{
|
|
|
|
() => ({
|
|
|
|
print!("\r\n")
|
|
|
|
});
|
|
|
|
($fmt:expr) => ({
|
|
|
|
print!(concat!($fmt, "\r\n"))
|
|
|
|
});
|
|
|
|
($fmt:expr, $($args:tt)+) => ({
|
|
|
|
print!(concat!($fmt, "\r\n"), $($args)+)
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// ///////////////////////////////////
|
|
|
|
// / LANGUAGE STRUCTURES / FUNCTIONS
|
|
|
|
// ///////////////////////////////////
|
|
|
|
#[no_mangle]
|
|
|
|
extern "C" fn eh_personality() {}
|
|
|
|
|
|
|
|
#[panic_handler]
|
|
|
|
fn panic(info: &core::panic::PanicInfo) -> ! {
|
|
|
|
print!("Aborting: ");
|
|
|
|
if let Some(p) = info.location() {
|
|
|
|
println!(
|
|
|
|
"line {}, file {}: {}",
|
|
|
|
p.line(),
|
|
|
|
p.file(),
|
|
|
|
info.message().unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
println!("no information available.");
|
|
|
|
}
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
#[no_mangle]
|
|
|
|
extern "C" fn abort() -> ! {
|
|
|
|
loop {
|
|
|
|
unsafe {
|
|
|
|
asm!("wfi"::::"volatile");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ///////////////////////////////////
|
|
|
|
// / CONSTANTS
|
|
|
|
// ///////////////////////////////////
|
|
|
|
// const STR_Y: &str = "\x1b[38;2;79;221;13m✓\x1b[m";
|
|
|
|
// const STR_N: &str = "\x1b[38;2;221;41;13m✘\x1b[m";
|
|
|
|
|
|
|
|
// The following symbols come from asm/mem.S. We can use
|
|
|
|
// the symbols directly, but the address of the symbols
|
|
|
|
// themselves are their values, which can cause issues.
|
|
|
|
// Instead, I created doubleword values in mem.S in the .rodata and .data
|
|
|
|
// sections.
|
2020-03-12 21:36:50 +04:00
|
|
|
// extern "C" {
|
|
|
|
// static TEXT_START: usize;
|
|
|
|
// static TEXT_END: usize;
|
|
|
|
// static DATA_START: usize;
|
|
|
|
// static DATA_END: usize;
|
|
|
|
// static RODATA_START: usize;
|
|
|
|
// static RODATA_END: usize;
|
|
|
|
// static BSS_START: usize;
|
|
|
|
// static BSS_END: usize;
|
|
|
|
// static KERNEL_STACK_START: usize;
|
|
|
|
// static KERNEL_STACK_END: usize;
|
|
|
|
// static HEAP_START: usize;
|
|
|
|
// static HEAP_SIZE: usize;
|
|
|
|
// }
|
2020-03-10 21:52:09 +04:00
|
|
|
/// Identity map range
|
|
|
|
/// Takes a contiguous allocation of memory and maps it using PAGE_SIZE
|
|
|
|
/// This assumes that start <= end
|
|
|
|
pub fn id_map_range(root: &mut page::Table,
|
|
|
|
start: usize,
|
|
|
|
end: usize,
|
|
|
|
bits: i64)
|
|
|
|
{
|
|
|
|
let mut memaddr = start & !(page::PAGE_SIZE - 1);
|
|
|
|
let num_kb_pages =
|
|
|
|
(page::align_val(end, 12) - memaddr) / page::PAGE_SIZE;
|
|
|
|
|
|
|
|
// I named this num_kb_pages for future expansion when
|
|
|
|
// I decide to allow for GiB (2^30) and 2MiB (2^21) page
|
|
|
|
// sizes. However, the overlapping memory regions are causing
|
|
|
|
// nightmares.
|
|
|
|
for _ in 0..num_kb_pages {
|
|
|
|
page::map(root, memaddr, memaddr, bits, 0);
|
|
|
|
memaddr += 1 << 12;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
extern "C" {
|
2020-03-13 04:10:36 +04:00
|
|
|
fn switch_to_user(frame: usize) -> !;
|
2020-03-10 21:52:09 +04:00
|
|
|
}
|
2020-03-13 04:10:36 +04:00
|
|
|
fn rust_switch_to_user(frame: usize) -> ! {
|
2020-03-12 21:54:39 +04:00
|
|
|
unsafe {
|
2020-03-13 04:10:36 +04:00
|
|
|
switch_to_user(frame);
|
2020-03-12 21:54:39 +04:00
|
|
|
}
|
|
|
|
}
|
2020-03-10 21:52:09 +04:00
|
|
|
// ///////////////////////////////////
|
|
|
|
// / ENTRY POINT
|
|
|
|
// ///////////////////////////////////
|
|
|
|
#[no_mangle]
|
|
|
|
extern "C" fn kinit() {
|
|
|
|
uart::Uart::new(0x1000_0000).init();
|
|
|
|
page::init();
|
|
|
|
kmem::init();
|
|
|
|
let ret = process::init();
|
2020-03-13 21:16:43 +04:00
|
|
|
// println!("Init process created at address 0x{:08x}", ret);
|
2020-03-10 21:52:09 +04:00
|
|
|
// We lower the threshold wall so our interrupts can jump over it.
|
|
|
|
plic::set_threshold(0);
|
|
|
|
// VIRTIO = [1..8]
|
|
|
|
// UART0 = 10
|
|
|
|
// PCIE = [32..35]
|
|
|
|
// Enable the UART interrupt.
|
2020-03-13 21:23:55 +04:00
|
|
|
for i in 1..=10 {
|
|
|
|
plic::enable(i);
|
|
|
|
plic::set_priority(i, 1);
|
|
|
|
}
|
2020-03-11 01:17:12 +04:00
|
|
|
virtio::probe();
|
2020-03-13 04:10:36 +04:00
|
|
|
let buffer = kmem::kmalloc(512);
|
2020-03-13 04:44:53 +04:00
|
|
|
block::read(8, buffer, 512, 0);
|
2020-03-13 03:47:58 +04:00
|
|
|
let mut i = 0;
|
|
|
|
loop {
|
|
|
|
if i > 100_000_000 {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
i += 1;
|
|
|
|
}
|
2020-03-13 04:10:36 +04:00
|
|
|
print!("Test hdd.dsk: ");
|
2020-03-13 03:47:58 +04:00
|
|
|
unsafe {
|
2020-03-13 04:10:36 +04:00
|
|
|
for i in 0..10 {
|
|
|
|
print!("{:02x} ", buffer.add(i).read());
|
|
|
|
}
|
|
|
|
println!();
|
2020-03-13 03:47:58 +04:00
|
|
|
}
|
2020-03-13 19:15:12 +04:00
|
|
|
kmem::kfree(buffer);
|
2020-03-10 21:52:09 +04:00
|
|
|
println!("Getting ready for first process.");
|
|
|
|
println!("Issuing the first context-switch timer.");
|
|
|
|
unsafe {
|
|
|
|
let mtimecmp = 0x0200_4000 as *mut u64;
|
|
|
|
let mtime = 0x0200_bff8 as *const u64;
|
2020-03-10 23:35:21 +04:00
|
|
|
mtimecmp.write_volatile(mtime.read_volatile().wrapping_add(cpu::CONTEXT_SWITCH_TIME));
|
2020-03-10 21:52:09 +04:00
|
|
|
}
|
2020-03-13 04:10:36 +04:00
|
|
|
rust_switch_to_user(sched::schedule());
|
2020-03-10 21:52:09 +04:00
|
|
|
// switch_to_user will not return, so we should never get here
|
|
|
|
}
|
|
|
|
#[no_mangle]
|
|
|
|
extern "C" fn kinit_hart(hartid: usize) {
|
|
|
|
// All non-0 harts initialize here.
|
|
|
|
unsafe {
|
|
|
|
// We have to store the kernel's table. The tables will be moved
|
|
|
|
// back and forth between the kernel's table and user
|
|
|
|
// applicatons' tables.
|
|
|
|
// Copy the same mscratch over to the supervisor version of the
|
|
|
|
// same register.
|
2020-03-13 23:31:47 +04:00
|
|
|
// cpu::KERNEL_TRAP_FRAME[hartid].hartid = hartid;
|
2020-03-10 21:52:09 +04:00
|
|
|
// We can't do the following until zalloc() is locked, but we
|
|
|
|
// don't have locks, yet :( cpu::KERNEL_TRAP_FRAME[hartid].satp
|
|
|
|
// = cpu::KERNEL_TRAP_FRAME[0].satp;
|
|
|
|
// cpu::KERNEL_TRAP_FRAME[hartid].trap_stack = page::zalloc(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ///////////////////////////////////
|
|
|
|
// / RUST MODULES
|
|
|
|
// ///////////////////////////////////
|
|
|
|
|
2020-03-11 03:29:29 +04:00
|
|
|
pub mod block;
|
2020-03-10 21:52:09 +04:00
|
|
|
pub mod cpu;
|
|
|
|
pub mod kmem;
|
|
|
|
pub mod page;
|
|
|
|
pub mod plic;
|
|
|
|
pub mod process;
|
|
|
|
pub mod sched;
|
|
|
|
pub mod syscall;
|
|
|
|
pub mod trap;
|
|
|
|
pub mod uart;
|
2020-03-11 01:17:12 +04:00
|
|
|
pub mod virtio;
|