1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-22 08:06:17 +04:00

Fix riscv external interrupt

This commit is contained in:
Jiajie Chen 2020-06-20 22:25:34 +08:00
parent b3f86cc3d1
commit 3ac4d7a607
14 changed files with 29 additions and 326 deletions

4
kernel/Cargo.lock generated
View File

@ -186,7 +186,7 @@ dependencies = [
[[package]]
name = "executor"
version = "0.6.0"
source = "git+https://github.com/rcore-os/executor.git?rev=93d0d54#93d0d54f1785dbf620ab98554e5fa320402183bb"
source = "git+https://github.com/rcore-os/executor.git?rev=662d3de#662d3ded46d53c4b6d144335719c50fc0adb2221"
dependencies = [
"executor-macros",
"lazy_static",
@ -199,7 +199,7 @@ dependencies = [
[[package]]
name = "executor-macros"
version = "0.0.1"
source = "git+https://github.com/rcore-os/executor.git?rev=93d0d54#93d0d54f1785dbf620ab98554e5fa320402183bb"
source = "git+https://github.com/rcore-os/executor.git?rev=662d3de#662d3ded46d53c4b6d144335719c50fc0adb2221"
dependencies = [
"proc-macro2",
"quote",

View File

@ -54,7 +54,7 @@ bit_field = "0.10"
buddy_system_allocator = "0.4.0"
compression = { version = "0.1.4", default-features = false, features = ["gzip"] }
device_tree = { git = "https://github.com/rcore-os/device_tree-rs", rev = "2fa8411c" }
executor = { git = "https://github.com/rcore-os/executor.git", rev = "93d0d54" }
executor = { git = "https://github.com/rcore-os/executor.git", rev = "662d3de" }
isomorphic_drivers = { git = "https://github.com/rcore-os/isomorphic_drivers", rev = "fcf694d2", features = ["log"] }
lazy_static = { version = "1.4", features = ["spin_no_std"] }
log = "0.4"

View File

@ -1,4 +1,5 @@
use crate::memory::phys_to_virt;
use riscv::register::sie;
/// Mask all external interrupt except serial.
pub unsafe fn init_external_interrupt() {
@ -15,6 +16,8 @@ pub unsafe fn init_external_interrupt() {
const HART0_S_MODE_PRIO_THRESH: *mut u32 = phys_to_virt(0x0C00_0000 + 0x20_1000) as *mut u32;
HART0_S_MODE_PRIO_THRESH.write_volatile(0); // Permits everything
sie::set_sext();
}
pub unsafe fn enable_serial_interrupt() {

View File

@ -1,13 +1,17 @@
// TODO
pub unsafe fn set_cpu_id(cpu_id: usize) {
llvm_asm!("mv gp, $0" : : "r"(cpu_id));
//llvm_asm!("mv gp, $0" : : "r"(cpu_id));
}
pub fn id() -> usize {
0
/*
let cpu_id;
unsafe {
llvm_asm!("mv $0, gp" : "=r"(cpu_id));
}
cpu_id
*/
}
pub fn send_ipi(cpu_id: usize) {

View File

@ -1,299 +0,0 @@
use riscv::register::{scause::Scause, sstatus, sstatus::Sstatus};
/// Saved registers on a trap.
///
/// WARN: sp needs to be 128-bit (16 Bytes) aligned
/// but we found it actually needs 32 Bytes aligned ???
#[derive(Clone)]
#[repr(C)]
pub struct TrapFrame {
/// General registers
pub x: [usize; 32],
/// Supervisor Status
pub sstatus: Sstatus,
/// Supervisor Exception Program Counter
pub sepc: usize,
/// Supervisor Trap Value
pub stval: usize,
/// Supervisor Cause
pub scause: Scause,
}
impl TrapFrame {
/// Constructs TrapFrame for a new kernel thread.
///
/// The new thread starts at function `entry` with an usize argument `arg`.
/// The stack pointer will be set to `sp`.
fn new_kernel_thread(entry: extern "C" fn(usize) -> !, arg: usize, sp: usize) -> Self {
use core::mem::zeroed;
let mut tf: Self = unsafe { zeroed() };
tf.x[10] = arg; // a0
tf.x[2] = sp;
tf.sepc = entry as usize;
tf.sstatus = sstatus::read();
tf.sstatus.set_spie(true);
tf.sstatus.set_sie(false);
tf.sstatus.set_spp(sstatus::SPP::Supervisor);
tf
}
/// Constructs TrapFrame for a new user thread.
///
/// The new thread starts at `entry_addr`.
/// The stack pointer will be set to `sp`.
pub fn new_user_thread(entry_addr: usize, sp: usize) -> Self {
use core::mem::zeroed;
let mut tf: Self = unsafe { zeroed() };
tf.x[2] = sp;
tf.sepc = entry_addr;
tf.sstatus = sstatus::read();
tf.sstatus.set_spie(true);
tf.sstatus.set_sie(false);
tf.sstatus.set_spp(sstatus::SPP::User);
tf
}
pub fn get_sp(&self) -> usize {
// sp is x2
self.x[2]
}
}
use core::fmt::{Debug, Error, Formatter};
impl Debug for TrapFrame {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
struct Regs<'a>(&'a [usize; 32]);
impl<'a> Debug for Regs<'a> {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
const REG_NAME: [&str; 32] = [
"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2",
"a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9",
"s10", "s11", "t3", "t4", "t5", "t6",
];
f.debug_map().entries(REG_NAME.iter().zip(self.0)).finish()
}
}
f.debug_struct("TrapFrame")
.field("regs", &Regs(&self.x))
.field("sstatus", &self.sstatus)
.field("sepc", &self.sepc)
.field("stval", &self.stval)
.field("scause", &self.scause.cause())
.finish()
}
}
/// Kernel stack contents for a new thread
#[derive(Debug)]
#[repr(C)]
pub struct InitStack {
context: ContextData,
tf: TrapFrame,
}
impl InitStack {
/// Push the InitStack on the stack and transfer to a Context.
unsafe fn push_at(self, stack_top: usize) -> Context {
let ptr = (stack_top as *mut Self).sub(1); //real kernel stack top
*ptr = self;
Context { sp: ptr as usize }
}
}
extern "C" {
fn trap_return();
}
/// Saved registers for kernel context switches.
#[derive(Debug, Default)]
#[repr(C)]
struct ContextData {
/// Return address
ra: usize,
/// Page table token
satp: usize,
/// Callee-saved registers
s: [usize; 12],
}
impl ContextData {
fn new(satp: usize) -> Self {
ContextData {
ra: trap_return as usize,
satp,
..ContextData::default()
}
}
}
/// Context of a kernel thread.
#[derive(Debug)]
#[repr(C)]
pub struct Context {
/// The stack pointer of the suspended thread.
/// A `ContextData` is stored here.
sp: usize,
}
impl Context {
/// Switch to another kernel thread.
///
/// Push all callee-saved registers at the current kernel stack.
/// Store current sp, switch to target.
/// Pop all callee-saved registers, then return to the target.
#[naked]
#[inline(never)]
pub unsafe extern "C" fn switch(&mut self, _target: &mut Self) {
#[cfg(target_arch = "riscv32")]
llvm_asm!(
r"
.equ XLENB, 4
.macro Load reg, mem
lw \reg, \mem
.endm
.macro Store reg, mem
sw \reg, \mem
.endm"
);
#[cfg(target_arch = "riscv64")]
llvm_asm!(
r"
.equ XLENB, 8
.macro Load reg, mem
ld \reg, \mem
.endm
.macro Store reg, mem
sd \reg, \mem
.endm"
);
llvm_asm!("
// save from's registers
addi sp, sp, (-XLENB*14)
Store sp, 0(a0)
Store ra, 0*XLENB(sp)
Store s0, 2*XLENB(sp)
Store s1, 3*XLENB(sp)
Store s2, 4*XLENB(sp)
Store s3, 5*XLENB(sp)
Store s4, 6*XLENB(sp)
Store s5, 7*XLENB(sp)
Store s6, 8*XLENB(sp)
Store s7, 9*XLENB(sp)
Store s8, 10*XLENB(sp)
Store s9, 11*XLENB(sp)
Store s10, 12*XLENB(sp)
Store s11, 13*XLENB(sp)
csrr s11, satp
Store s11, 1*XLENB(sp)
// restore to's registers
Load sp, 0(a1)
Load s11, 1*XLENB(sp)
csrw satp, s11
sfence.vma
Load ra, 0*XLENB(sp)
Load s0, 2*XLENB(sp)
Load s1, 3*XLENB(sp)
Load s2, 4*XLENB(sp)
Load s3, 5*XLENB(sp)
Load s4, 6*XLENB(sp)
Load s5, 7*XLENB(sp)
Load s6, 8*XLENB(sp)
Load s7, 9*XLENB(sp)
Load s8, 10*XLENB(sp)
Load s9, 11*XLENB(sp)
Load s10, 12*XLENB(sp)
Load s11, 13*XLENB(sp)
addi sp, sp, (XLENB*14)
Store zero, 0(a1)
ret"
: : : : "volatile" )
}
/// Constructs a null Context for the current running thread.
pub unsafe fn null() -> Self {
Context { sp: 0 }
}
/// Constructs Context for a new kernel thread.
///
/// The new thread starts at function `entry` with an usize argument `arg`.
/// The stack pointer will be set to `kstack_top`.
/// The SATP register will be set to `satp`.
pub unsafe fn new_kernel_thread(
entry: extern "C" fn(usize) -> !,
arg: usize,
kstack_top: usize,
satp: usize,
) -> Self {
InitStack {
context: ContextData::new(satp),
tf: TrapFrame::new_kernel_thread(entry, arg, kstack_top),
}
.push_at(kstack_top)
}
/// Constructs Context for a new user thread.
///
/// The new thread starts at `entry_addr`.
/// The stack pointer of user and kernel mode will be set to `ustack_top`, `kstack_top`.
/// The SATP register will be set to `satp`.
pub unsafe fn new_user_thread(
entry_addr: usize,
ustack_top: usize,
kstack_top: usize,
satp: usize,
) -> Self {
InitStack {
context: ContextData::new(satp),
tf: TrapFrame::new_user_thread(entry_addr, ustack_top),
}
.push_at(kstack_top)
}
/// Fork a user process and get the new Context.
///
/// The stack pointer in kernel mode will be set to `kstack_top`.
/// The SATP register will be set to `satp`.
/// All the other registers are same as the original.
pub unsafe fn new_fork(tf: &TrapFrame, kstack_top: usize, satp: usize) -> Self {
InitStack {
context: ContextData::new(satp),
tf: {
let mut tf = tf.clone();
// fork function's ret value, the new process is 0
tf.x[10] = 0; // a0
tf
},
}
.push_at(kstack_top)
}
/// Fork a user thread and get the new Context.
///
/// The stack pointer in kernel mode will be set to `kstack_top`.
/// The SATP register will be set to `satp`.
/// The new user stack will be set to `ustack_top`.
/// The new thread pointer will be set to `tls`.
/// All the other registers are same as the original.
pub unsafe fn new_clone(
tf: &TrapFrame,
ustack_top: usize,
kstack_top: usize,
satp: usize,
tls: usize,
) -> Self {
InitStack {
context: ContextData::new(satp),
tf: {
let mut tf = tf.clone();
tf.x[2] = ustack_top; // sp
tf.x[4] = tls; // tp
tf.x[10] = 0; // a0
tf
},
}
.push_at(kstack_top)
}
}

View File

@ -1,12 +1,10 @@
pub use self::context::*;
use crate::drivers::IRQ_MANAGER;
use log::*;
use riscv::register::*;
use riscv::register::{scause::Scause, sscratch, stvec};
use trapframe::UserContext;
use trapframe::{TrapFrame, UserContext};
pub mod consts;
mod context;
/// Enable interrupt
#[inline]
@ -36,20 +34,16 @@ pub unsafe fn restore(flags: usize) {
#[no_mangle]
pub extern "C" fn trap_handler(scause: Scause, stval: usize, tf: &mut TrapFrame) {
use self::scause::{Exception as E, Interrupt as I, Trap};
trace!(
"Interrupt @ CPU{}: {:?} ",
super::cpu::id(),
tf.scause.cause()
);
match tf.scause.cause() {
trace!("Interrupt @ CPU{}: {:?} ", super::cpu::id(), scause.cause());
match 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),
_ => panic!("unhandled trap"),
Trap::Exception(E::LoadPageFault) => page_fault(stval, tf),
Trap::Exception(E::StorePageFault) => page_fault(stval, tf),
Trap::Exception(E::InstructionPageFault) => page_fault(stval, tf),
_ => panic!("unhandled trap {:?}", scause.cause()),
}
trace!("Interrupt end");
}
@ -85,8 +79,8 @@ pub fn syscall(tf: &mut TrapFrame) {
*/
}
fn page_fault(tf: &mut TrapFrame) {
let addr = tf.stval;
fn page_fault(stval: usize, tf: &mut TrapFrame) {
let addr = stval;
trace!("\nEXCEPTION: Page Fault @ {:#x}", addr);
if crate::memory::handle_page_fault(addr) {

View File

@ -1,4 +1,4 @@
use crate::arch::interrupt::TrapFrame;
use trapframe::TrapFrame;
#[repr(C)]
#[derive(Clone, Debug)]

View File

@ -4,7 +4,7 @@ mod handler;
pub use self::handler::*;
use crate::memory::phys_to_virt;
use apic::*;
pub use trapframe::{TrapFrame, UserContext};
use trapframe::{TrapFrame, UserContext};
#[inline(always)]
pub unsafe fn enable() {

View File

@ -2,7 +2,6 @@ use super::{
abi::{self, ProcInitInfo},
Futex, Tid,
};
use crate::arch::interrupt::TrapFrame;
use crate::arch::paging::*;
use crate::fs::{FileHandle, FileLike, OpenOptions, FOLLOW_MAX_DEPTH};
use crate::ipc::SemProc;
@ -33,6 +32,7 @@ use pc_keyboard::KeyCode::BackTick;
use rcore_fs::vfs::INode;
use rcore_memory::{Page, PAGE_SIZE};
use spin::RwLock;
use trapframe::TrapFrame;
use trapframe::UserContext;
use xmas_elf::{
header,

View File

@ -1,5 +1,4 @@
use super::abi::{self, ProcInitInfo};
use crate::arch::interrupt::TrapFrame;
use crate::arch::paging::*;
use crate::fs::{FileHandle, FileLike, OpenOptions, FOLLOW_MAX_DEPTH};
use crate::ipc::SemProc;
@ -29,6 +28,7 @@ use pc_keyboard::KeyCode::BackTick;
use rcore_fs::vfs::INode;
use rcore_memory::{Page, PAGE_SIZE};
use spin::RwLock;
use trapframe::TrapFrame;
use trapframe::UserContext;
use xmas_elf::{
header,

View File

@ -3,7 +3,7 @@ use super::{
add_to_process_table, Pid, Process, PROCESSORS,
};
use crate::arch::interrupt::consts::{is_page_fault, IrqMax, IrqMin, Syscall, Timer};
use crate::arch::interrupt::{get_trap_num, TrapFrame};
use crate::arch::interrupt::get_trap_num;
use crate::arch::{
cpu,
memory::{get_page_fault_addr, set_page_table},
@ -39,6 +39,7 @@ use pc_keyboard::KeyCode::BackTick;
use rcore_fs::vfs::INode;
use rcore_memory::{Page, PAGE_SIZE};
use spin::RwLock;
use trapframe::TrapFrame;
use trapframe::UserContext;
use xmas_elf::{
header,

View File

@ -7,9 +7,9 @@ use num::FromPrimitive;
mod action;
pub use self::action::*;
use crate::arch::interrupt::TrapFrame;
use crate::arch::signal::MachineContext;
use crate::arch::syscall::SYS_RT_SIGRETURN;
use trapframe::TrapFrame;
#[derive(Eq, PartialEq, FromPrimitive, Debug, Copy, Clone)]
pub enum Signal {

View File

@ -1,7 +1,6 @@
//! System call
use crate::arch::cpu;
use crate::arch::interrupt::TrapFrame;
use crate::arch::syscall::*;
use crate::fs::epoll::EpollEvent;
use crate::memory::{copy_from_user, MemorySet};
@ -15,6 +14,7 @@ use core::{fmt, slice, str};
use num::FromPrimitive;
use rcore_fs::vfs::{FileType, FsError, INode, Metadata};
use rcore_memory::VMError;
use trapframe::TrapFrame;
use trapframe::{GeneralRegs, UserContext};
pub use self::custom::*;

View File

@ -1,11 +1,11 @@
use crate::arch::cpu;
use crate::arch::interrupt::TrapFrame;
use crate::consts::INFORM_PER_MSEC;
use crate::process::*;
use crate::sync::SpinNoIrqLock as Mutex;
use crate::{signal::SignalUserContext, sync::Condvar};
use core::time::Duration;
use naive_timer::Timer;
use trapframe::TrapFrame;
use trapframe::UserContext;
pub static mut TICK: usize = 0;