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:
parent
b3f86cc3d1
commit
3ac4d7a607
4
kernel/Cargo.lock
generated
4
kernel/Cargo.lock
generated
@ -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",
|
||||
|
@ -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"
|
||||
|
@ -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() {
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::arch::interrupt::TrapFrame;
|
||||
use trapframe::TrapFrame;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -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() {
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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::*;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user