mirror of
https://github.com/sgmarz/osblog.git
synced 2024-11-27 20:03:32 +04:00
151 lines
3.3 KiB
Rust
Executable File
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;
|
|
|
|
|