xous-kernel/src/main.rs

126 lines
3.3 KiB
Rust

#![no_std]
#![no_main]
extern crate vexriscv;
#[macro_use]
mod debug;
mod definitions;
mod exception;
mod irq;
mod macros;
mod mem;
mod processtable;
mod syscalls;
mod timer;
pub use irq::sys_interrupt_claim;
use core::panic::PanicInfo;
use mem::MemoryManager;
use processtable::ProcessTable;
use vexriscv::register::{mcause, mepc, mie, mstatus, mtval, satp, vmim, vmip};
use xous_kernel_riscv_rt::xous_kernel_entry;
#[panic_handler]
fn handle_panic(arg: &PanicInfo) -> ! {
println!("PANIC!");
println!("Details: {:?}", arg);
loop {}
}
extern "Rust" {
fn return_from_interrupt() -> !;
}
extern "C" {
/// Debug function to read the current SATP. Useful since Renode
/// doesn't support reading it any other way.
fn read_satp() -> usize;
}
#[xous_kernel_entry]
fn mmu_init() -> ! {
let mut mm = MemoryManager::new().expect("Couldn't create memory manager");
mm.init().expect("Couldn't initialize memory manager");
let mut pt = ProcessTable::new().expect("Couldn't create process table");
// Allocate a page to PID 1 to use as the root page table, then create
// an identity mapping in preparation for enabling the MMU.
let process1 = pt
.create_process(&mut mm)
.expect("Couldn't create process for PID1");
let pid1_satp = pt.satp_for(process1).expect("Couldn't find SATP for PID1");
mm.create_identity(pid1_satp)
.expect("Couldn't create identity mapping for PID1");
println!("MMU enabled, jumping to kmain");
pt.switch_to(process1, kmain as usize).expect("Couldn't switch to PID1");
println!("SATP: {:08x}", unsafe { read_satp() });
unsafe {
mstatus::set_spp(mstatus::SPP::Supervisor);
mstatus::set_mpp(mstatus::MPP::Supervisor);
println!("kmain: MSTATUS: {:?}", mstatus::read());
return_from_interrupt()
}
}
/// This function runs with the MMU enabled, as part of PID 1
#[no_mangle]
fn kmain() -> ! {
unsafe {
vmim::write(0); // Disable all machine interrupts
mie::set_msoft();
mie::set_mtimer();
mie::set_mext();
mstatus::set_mpp(mstatus::MPP::Supervisor);
mstatus::set_spie();
mstatus::set_mie(); // Enable CPU interrupts
}
println!("kmain: SATP: {:08x}", satp::read().bits());
println!("kmain: MSTATUS: {:?}", mstatus::read());
let uart = debug::DEFAULT_UART;
uart.init();
// sys_interrupt_claim(0, timer::irq).unwrap();
// timer::time_init();
// Enable "RX_EMPTY" interrupt
uart.enable_rx();
sys_interrupt_claim(2, debug::irq).expect("Couldn't claim interrupt 2");
println!("Entering main loop");
// let mut last_time = timer::get_time();
loop {
// let new_time = timer::get_time();
// if new_time >= last_time + 1000 {
// last_time = new_time;
// println!("Uptime: {} ms", new_time);
// }
// unsafe { vexriscv::asm::wfi() };
}
}
#[no_mangle]
pub fn trap_handler() {
let mc = mcause::read();
let irqs_pending = vmip::read();
if mc.is_exception() {
println!("CPU Exception");
let ex = exception::RiscvException::from_regs(mc.bits(), mepc::read(), mtval::read());
println!("{}", ex);
unsafe { vexriscv::asm::ebreak() };
loop {}
}
if irqs_pending != 0 {
irq::handle(irqs_pending);
}
}