1
0
mirror of https://github.com/sgmarz/osblog.git synced 2024-11-27 20:03:32 +04:00
osblog/risc_v/src/main.rs
2020-05-18 12:22:04 -04:00

151 lines
3.3 KiB
Rust
Executable File

// Steve Operating System
// Stephen Marz
// 21 Sep 2019
#![no_main]
#![no_std]
#![feature(panic_info_message,
asm,
llvm_asm,
global_asm,
allocator_api,
alloc_error_handler,
alloc_prelude,
const_raw_ptr_to_usize_cast,
lang_items)]
#[lang = "eh_personality"] extern fn eh_personality() {}
// #[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
// ///////////////////////////////////
#[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 {
llvm_asm!("wfi"::::"volatile");
}
}
}
extern "C" {
fn switch_to_user(frame: usize) -> !;
}
/// Switch to user is an assembly function that loads
/// a frame. Since it will jump to another program counter,
/// it will never return back here. We don't care if we leak
/// the stack, since we will recapture the stack during m_trap.
fn rust_switch_to_user(frame: usize) -> ! {
unsafe {
switch_to_user(frame);
}
}
// ///////////////////////////////////
// / ENTRY POINT
// ///////////////////////////////////
#[no_mangle]
extern "C" fn kinit() {
uart::Uart::new(0x1000_0000).init();
page::init();
kmem::init();
process::init();
// We lower the threshold wall so our interrupts can jump over it.
// Any priority > 0 will be able to be "heard"
plic::set_threshold(0);
// VIRTIO = [1..8]
// UART0 = 10
// PCIE = [32..35]
// Enable PLIC interrupts.
for i in 1..=10 {
plic::enable(i);
plic::set_priority(i, 1);
}
// Set up virtio. This requires a working heap and page-grained allocator.
virtio::probe();
// Test the block driver!
process::add_kernel_process(test::test);
// We schedule the next context switch using a multiplier of 1
// Block testing code removed.
trap::schedule_next_context_switch(1);
rust_switch_to_user(sched::schedule());
// switch_to_user will not return, so we should never get here
}
#[no_mangle]
extern "C" fn kinit_hart(_hartid: usize) {
// We aren't going to do anything here until we get SMP going.
// All non-0 harts initialize here.
}
// ///////////////////////////////////
// / RUST MODULES
// ///////////////////////////////////
pub mod assembly;
pub mod block;
pub mod buffer;
pub mod cpu;
pub mod elf;
pub mod fs;
pub mod gpu;
pub mod kmem;
pub mod lock;
pub mod page;
pub mod plic;
pub mod process;
pub mod rng;
pub mod sched;
pub mod syscall;
pub mod trap;
pub mod uart;
pub mod virtio;
pub mod test;