From a10a7cafa10eb873680b30f7fb201ae4ac131c2b Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Fri, 5 Apr 2019 21:18:24 +0800 Subject: [PATCH] Add interrupt dispatcher. --- kernel/src/arch/mipsel/context.rs | 4 +- kernel/src/arch/mipsel/cpu.rs | 18 ++----- kernel/src/arch/mipsel/interrupt.rs | 73 ++++++++++++++++------------- 3 files changed, 47 insertions(+), 48 deletions(-) diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index 09514c4..c968874 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -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() } } diff --git a/kernel/src/arch/mipsel/cpu.rs b/kernel/src/arch/mipsel/cpu.rs index dea1df9..ea27d1f 100644 --- a/kernel/src/arch/mipsel/cpu.rs +++ b/kernel/src/arch/mipsel/cpu.rs @@ -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 {} } diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index 12fda2e..22f23ce 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -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) {