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> { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
f.debug_struct("TrapFrame") f.debug_struct("TrapFrame")
.field("status", &self.status.bits) .field("status", &self.status.bits)
.field("epc", &self.epc.bits) .field("epc", &self.epc)
.field("cause", &self.cause.bits) .field("cause", &self.cause.bits)
.field("vaddr", &self.vaddr.bits) .field("vaddr", &self.vaddr)
.finish() .finish()
} }
} }

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

@ -9,24 +9,23 @@ mod context;
/// Initialize interrupt /// Initialize interrupt
pub fn init() { pub fn init() {
// TODO extern {
// extern { fn trap_entry();
// fn trap_entry(); }
// } unsafe {
// unsafe { // Set the exception vector address
// // Set sscratch register to 0, indicating to exception vector that we are cp0::ebase::write_u32(trap_entry as u32);
// // presently executing in the kernel
// sscratch::write(0); let mut status = cp0::status::read();
// // Set the exception vector address // Enable IPI
// stvec::write(trap_entry as usize, stvec::TrapMode::Direct); status.enable_soft_int0();
// // Enable IPI status.enable_soft_int1();
// sie::set_ssoft(); // Enable clock interrupt
// // Enable external interrupt status.enable_hard_int5();
// if super::cpu::id() == super::BOOT_HART_ID {
// sie::set_sext(); cp0::status::write(status);
// } }
// } info!("interrupt: init end");
// info!("interrupt: init end");
} }
/// Enable interrupt /// Enable interrupt
@ -56,22 +55,30 @@ pub unsafe fn restore(flags: usize) {
/// This function is called from `trap.asm`. /// This function is called from `trap.asm`.
#[no_mangle] #[no_mangle]
pub extern fn rust_trap(tf: &mut TrapFrame) { pub extern fn rust_trap(tf: &mut TrapFrame) {
// TODO use cp0::cause::{Exception as E};
use self::scause::{Trap, Interrupt as I, Exception as E}; trace!("Interrupt @ CPU{}: {:?} ", 0, tf.cause.cause());
// trace!("Interrupt @ CPU{}: {:?} ", super::cpu::id(), tf.scause.cause()); match tf.cause.cause() {
match tf.scause.cause() { E::Interrupt => interrupt_dispatcher(),
Trap::Interrupt(I::SupervisorExternal) => external(), E::Syscall => syscall(tf),
Trap::Interrupt(I::SupervisorSoft) => ipi(), E::TLBModification => page_fault(tf),
Trap::Interrupt(I::SupervisorTimer) => timer(), E::TLBLoadMiss => page_fault(tf),
Trap::Exception(E::UserEnvCall) => syscall(tf), E::TLBStoreMiss => page_fault(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), _ => crate::trap::error(tf),
} }
trace!("Interrupt end"); 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() { fn external() {
// TODO // TODO
// true means handled, false otherwise // true means handled, false otherwise
@ -104,7 +111,7 @@ fn try_process_drivers() -> bool {
} }
fn ipi() { fn ipi() {
// TODO /* do nothing */
debug!("IPI"); debug!("IPI");
// super::sbi::clear_ipi(); // super::sbi::clear_ipi();
} }
@ -115,14 +122,14 @@ fn timer() {
} }
fn syscall(tf: &mut TrapFrame) { 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); 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; tf.v0 = ret as usize;
} }
fn page_fault(tf: &mut TrapFrame) { fn page_fault(tf: &mut TrapFrame) {
// TODO // TODO: set access/dirty bit
let addr = tf.stval; let addr = tf.vaddr;
trace!("\nEXCEPTION: Page Fault @ {:#x}", addr); trace!("\nEXCEPTION: Page Fault @ {:#x}", addr);
if !crate::memory::handle_page_fault(addr) { if !crate::memory::handle_page_fault(addr) {

Loading…
Cancel
Save