Add interrupt dispatcher.

master
Yuhao Zhou 6 years ago
parent 53317e84c4
commit a10a7cafa1

@ -92,9 +92,9 @@ impl Debug for TrapFrame {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
f.debug_struct("TrapFrame")
.field("status", &self.status.bits)
.field("epc", &self.epc.bits)
.field("epc", &self.epc)
.field("cause", &self.cause.bits)
.field("vaddr", &self.vaddr.bits)
.field("vaddr", &self.vaddr)
.finish()
}
}

@ -1,20 +1,11 @@
use mips::registers::cp0;
use crate::consts::MAX_CPU_NUM;
use core::ptr::{read_volatile, write_volatile};
static mut STARTED: [bool; MAX_CPU_NUM] = [false; MAX_CPU_NUM];
pub unsafe fn set_cpu_id(cpu_id: usize) {
asm!("mv gp, $0" : : "r"(cpu_id));
}
pub fn id() -> usize {
let cpu_id;
unsafe { asm!("mv $0, gp" : "=r"(cpu_id)); }
cpu_id
}
pub fn send_ipi(cpu_id: usize) {
super::sbi::send_ipi(1 << cpu_id);
(cp0::ebase::read_u32() as usize) & 0x3ff
}
pub unsafe fn has_started(cpu_id: usize) -> bool {
@ -30,9 +21,10 @@ pub unsafe fn start_others(hart_mask: usize) {
}
pub fn halt() {
unsafe { riscv::asm::wfi() }
/* nothing to do */
}
pub unsafe fn exit_in_qemu(error_code: u8) -> ! {
super::sbi::shutdown()
/* nothing to do */
loop {}
}

@ -9,24 +9,23 @@ 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");
extern {
fn trap_entry();
}
unsafe {
// Set the exception vector address
cp0::ebase::write_u32(trap_entry as u32);
let mut status = cp0::status::read();
// Enable IPI
status.enable_soft_int0();
status.enable_soft_int1();
// Enable clock interrupt
status.enable_hard_int5();
cp0::status::write(status);
}
info!("interrupt: init end");
}
/// Enable interrupt
@ -56,22 +55,30 @@ pub unsafe fn restore(flags: usize) {
/// 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),
use cp0::cause::{Exception as E};
trace!("Interrupt @ CPU{}: {:?} ", 0, tf.cause.cause());
match tf.cause.cause() {
E::Interrupt => interrupt_dispatcher(),
E::Syscall => syscall(tf),
E::TLBModification => page_fault(tf),
E::TLBLoadMiss => page_fault(tf),
E::TLBStoreMiss => page_fault(tf),
_ => crate::trap::error(tf),
}
trace!("Interrupt end");
}
fn interrupt_dispatcher(tf: &mut TrapFrame) {
let pint = tf.cause.pending_interrupt();
if (pint & 0b10000_00) != 0 {
timer();
} else if (pint & 0xb01111_00) != 0 {
external();
} else {
ipi();
}
}
fn external() {
// TODO
// true means handled, false otherwise
@ -104,7 +111,7 @@ fn try_process_drivers() -> bool {
}
fn ipi() {
// TODO
/* do nothing */
debug!("IPI");
// super::sbi::clear_ipi();
}
@ -115,14 +122,14 @@ fn timer() {
}
fn syscall(tf: &mut TrapFrame) {
tf.sepc += 4; // Must before syscall, because of fork.
tf.epc += 4; // Must before syscall, because of fork.
let ret = crate::syscall::syscall(tf.t0, [tf.t0, tf.t1, tf.t2, tf.t3, tf.s0, tf.s1], tf);
tf.v0 = ret as usize;
}
fn page_fault(tf: &mut TrapFrame) {
// TODO
let addr = tf.stval;
// TODO: set access/dirty bit
let addr = tf.vaddr;
trace!("\nEXCEPTION: Page Fault @ {:#x}", addr);
if !crate::memory::handle_page_fault(addr) {

Loading…
Cancel
Save