You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
peari9jp6/kernel/src/arch/mipsel/interrupt.rs

137 lines
3.3 KiB

use mips::interrupts;
use mips::registers::cp0;
use crate::drivers::DRIVERS;
pub use self::context::*;
use log::*;
#[path = "context.rs"]
mod context;
/// Initialize interrupt
pub fn init() {
// TODO
// extern {
// fn trap_entry();
// }
// unsafe {
// // Set sscratch register to 0, indicating to exception vector that we are
// // presently executing in the kernel
// sscratch::write(0);
// // Set the exception vector address
// stvec::write(trap_entry as usize, stvec::TrapMode::Direct);
// // Enable IPI
// sie::set_ssoft();
// // Enable external interrupt
// if super::cpu::id() == super::BOOT_HART_ID {
// sie::set_sext();
// }
// }
// info!("interrupt: init end");
}
/// Enable interrupt
#[inline]
pub unsafe fn enable() {
interrupts::enable();
}
/// Disable interrupt and return current interrupt status
#[inline]
pub unsafe fn disable_and_store() -> usize {
let e = cp0::status::read_u32() & 1;
interrupts::disable();
e
}
/// Enable interrupt if `flags` != 0
#[inline]
pub unsafe fn restore(flags: usize) {
if flags != 0 {
enable();
}
}
/// Dispatch and handle interrupt.
///
/// This function is called from `trap.asm`.
#[no_mangle]
pub extern fn rust_trap(tf: &mut TrapFrame) {
// TODO
use self::scause::{Trap, Interrupt as I, Exception as E};
// trace!("Interrupt @ CPU{}: {:?} ", super::cpu::id(), tf.scause.cause());
match tf.scause.cause() {
Trap::Interrupt(I::SupervisorExternal) => external(),
Trap::Interrupt(I::SupervisorSoft) => ipi(),
Trap::Interrupt(I::SupervisorTimer) => timer(),
Trap::Exception(E::UserEnvCall) => syscall(tf),
Trap::Exception(E::LoadPageFault) => page_fault(tf),
Trap::Exception(E::StorePageFault) => page_fault(tf),
Trap::Exception(E::InstructionPageFault) => page_fault(tf),
_ => crate::trap::error(tf),
}
trace!("Interrupt end");
}
fn external() {
// TODO
#[cfg(feature = "board_u540")]
unsafe { super::board::handle_external_interrupt(); }
// true means handled, false otherwise
let handlers = [try_process_serial, try_process_drivers];
for handler in handlers.iter() {
if handler() == true {
break
}
}
}
fn try_process_serial() -> bool {
// TODO
match super::io::getchar_option() {
Some(ch) => {
crate::trap::serial(ch);
true
}
None => false
}
}
fn try_process_drivers() -> bool {
// TODO
for driver in DRIVERS.read().iter() {
if driver.try_handle_interrupt(None) == true {
return true
}
}
return false
}
fn ipi() {
// TODO
debug!("IPI");
// super::sbi::clear_ipi();
}
fn timer() {
super::timer::set_next();
crate::trap::timer();
}
fn syscall(tf: &mut TrapFrame) {
// TODO
tf.sepc += 4; // Must before syscall, because of fork.
let ret = crate::syscall::syscall(tf.x[17], [tf.x[10], tf.x[11], tf.x[12], tf.x[13], tf.x[14], tf.x[15]], tf);
tf.x[10] = ret as usize;
}
fn page_fault(tf: &mut TrapFrame) {
// TODO
let addr = tf.stval;
trace!("\nEXCEPTION: Page Fault @ {:#x}", addr);
if !crate::memory::handle_page_fault(addr) {
crate::trap::error(tf);
}
}