We should disable sie before trapping back to user.

This commit is contained in:
Yifan Wu 2022-03-10 16:27:05 -08:00
parent fbe8e39b38
commit 334d868a5c
8 changed files with 43 additions and 33 deletions

View File

@ -28,31 +28,18 @@ pub fn device_init() {
plic.enable(hart_id, supervisor, intr_src_id); plic.enable(hart_id, supervisor, intr_src_id);
plic.set_priority(intr_src_id, 1); plic.set_priority(intr_src_id, 1);
} }
crate::println!(
"Hart0M threshold = {}",
plic.get_threshold(hart_id, IntrTargetPriority::Machine)
);
crate::println!(
"Hart0S threshold = {}",
plic.get_threshold(hart_id, IntrTargetPriority::Supervisor)
);
crate::println!("1 prio = {}", plic.get_priority(1));
crate::println!("10 prio = {}", plic.get_priority(10));
unsafe { unsafe {
sie::set_sext(); sie::set_sext();
} }
} }
pub fn irq_handler() { pub fn irq_handler() {
//crate::println!("->irq_handler");
let mut plic = unsafe { PLIC::new(VIRT_PLIC) }; let mut plic = unsafe { PLIC::new(VIRT_PLIC) };
let intr_src_id = plic.claim(0, IntrTargetPriority::Supervisor); let intr_src_id = plic.claim(0, IntrTargetPriority::Supervisor);
//crate::println!("intr_src={}", intr_src_id);
match intr_src_id { match intr_src_id {
1 => BLOCK_DEVICE.handle_irq(), 1 => BLOCK_DEVICE.handle_irq(),
10 => UART.handle_irq(), 10 => UART.handle_irq(),
_ => panic!("unsupported IRQ {}", intr_src_id), _ => panic!("unsupported IRQ {}", intr_src_id),
} }
plic.complete(0, IntrTargetPriority::Supervisor, intr_src_id); plic.complete(0, IntrTargetPriority::Supervisor, intr_src_id);
//crate::println!("irq_handler->");
} }

View File

@ -7,8 +7,8 @@ struct Stdout;
impl Write for Stdout { impl Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result { fn write_str(&mut self, s: &str) -> fmt::Result {
for c in s.chars() { for c in s.chars() {
//UART.write(c as u8); UART.write(c as u8);
console_putchar(c as usize); //console_putchar(c as usize);
} }
Ok(()) Ok(())
} }

View File

@ -28,10 +28,17 @@ impl BlockDevice for VirtIOBlock {
let nb = *DEV_NON_BLOCKING_ACCESS.exclusive_access(); let nb = *DEV_NON_BLOCKING_ACCESS.exclusive_access();
if nb { if nb {
let mut resp = BlkResp::default(); let mut resp = BlkResp::default();
/*
let task_cx_ptr = self.virtio_blk.exclusive_session(|blk| { let task_cx_ptr = self.virtio_blk.exclusive_session(|blk| {
let token = unsafe { blk.read_block_nb(block_id, buf, &mut resp).unwrap() }; let token = unsafe { blk.read_block_nb(block_id, buf, &mut resp).unwrap() };
self.condvars.get(&token).unwrap().wait_no_sched() self.condvars.get(&token).unwrap().wait_no_sched()
}); });
*/
let mut blk = self.virtio_blk.exclusive_access();
let token = unsafe { blk.read_block_nb(block_id, buf, &mut resp).unwrap() };
//println!("waiting on token {}", token);
let task_cx_ptr = self.condvars.get(&token).unwrap().wait_no_sched();
drop(blk);
schedule(task_cx_ptr); schedule(task_cx_ptr);
assert_eq!( assert_eq!(
resp.status(), resp.status(),
@ -49,10 +56,16 @@ impl BlockDevice for VirtIOBlock {
let nb = *DEV_NON_BLOCKING_ACCESS.exclusive_access(); let nb = *DEV_NON_BLOCKING_ACCESS.exclusive_access();
if nb { if nb {
let mut resp = BlkResp::default(); let mut resp = BlkResp::default();
/*
let task_cx_ptr = self.virtio_blk.exclusive_session(|blk| { let task_cx_ptr = self.virtio_blk.exclusive_session(|blk| {
let token = unsafe { blk.write_block_nb(block_id, buf, &mut resp).unwrap() }; let token = unsafe { blk.write_block_nb(block_id, buf, &mut resp).unwrap() };
self.condvars.get(&token).unwrap().wait_no_sched() self.condvars.get(&token).unwrap().wait_no_sched()
}); });
*/
let mut blk = self.virtio_blk.exclusive_access();
let token = unsafe { blk.write_block_nb(block_id, buf, &mut resp).unwrap() };
let task_cx_ptr = self.condvars.get(&token).unwrap().wait_no_sched();
drop(blk);
schedule(task_cx_ptr); schedule(task_cx_ptr);
assert_eq!( assert_eq!(
resp.status(), resp.status(),
@ -68,6 +81,7 @@ impl BlockDevice for VirtIOBlock {
} }
fn handle_irq(&self) { fn handle_irq(&self) {
//println!("into handle_irq"); //println!("into handle_irq");
/*
self.virtio_blk.exclusive_session(|blk| { self.virtio_blk.exclusive_session(|blk| {
//println!("not panic here"); //println!("not panic here");
while let Ok(token) = blk.pop_used() { while let Ok(token) = blk.pop_used() {
@ -75,6 +89,12 @@ impl BlockDevice for VirtIOBlock {
self.condvars.get(&token).unwrap().signal(); self.condvars.get(&token).unwrap().signal();
} }
}); });
*/
let mut blk = self.virtio_blk.exclusive_access();
while let Ok(token) = blk.pop_used() {
//println!("wakeup virtio.token {}", token);
self.condvars.get(&token).unwrap().signal();
}
} }
} }

View File

@ -146,15 +146,15 @@ impl<const BASE_ADDR: usize> NS16550a<BASE_ADDR> {
impl<const BASE_ADDR: usize> CharDevice for NS16550a<BASE_ADDR> { impl<const BASE_ADDR: usize> CharDevice for NS16550a<BASE_ADDR> {
fn read(&self) -> u8 { fn read(&self) -> u8 {
println!("NS16550a::read"); //println!("NS16550a::read");
loop { loop {
let mut inner = self.inner.exclusive_access(); let mut inner = self.inner.exclusive_access();
if let Some(ch) = inner.read_buffer.pop_front() { if let Some(ch) = inner.read_buffer.pop_front() {
return ch; return ch;
} else { } else {
println!("no ch yet!");
let task_cx_ptr = self.condvar.wait_no_sched(); let task_cx_ptr = self.condvar.wait_no_sched();
drop(inner); drop(inner);
//println!("before scheduling");
schedule(task_cx_ptr); schedule(task_cx_ptr);
} }
} }
@ -167,7 +167,7 @@ impl<const BASE_ADDR: usize> CharDevice for NS16550a<BASE_ADDR> {
let mut inner = self.inner.exclusive_access(); let mut inner = self.inner.exclusive_access();
let mut count = 0; let mut count = 0;
while let Some(ch) = inner.ns16550a.read() { while let Some(ch) = inner.ns16550a.read() {
println!("got {}", ch as char); //println!("got {}", ch as char);
count += 1; count += 1;
inner.read_buffer.push_back(ch); inner.read_buffer.push_back(ch);
} }

View File

@ -14,7 +14,7 @@ impl File for Stdin {
} }
fn read(&self, mut user_buf: UserBuffer) -> usize { fn read(&self, mut user_buf: UserBuffer) -> usize {
assert_eq!(user_buf.len(), 1); assert_eq!(user_buf.len(), 1);
println!("before UART.read() in Stdin::read()"); //println!("before UART.read() in Stdin::read()");
let ch = UART.read(); let ch = UART.read();
unsafe { unsafe {
user_buf.buffers[0].as_mut_ptr().write_volatile(ch); user_buf.buffers[0].as_mut_ptr().write_volatile(ch);

View File

@ -36,9 +36,14 @@ impl Condvar {
} }
pub fn wait_no_sched(&self) -> *mut TaskContext { pub fn wait_no_sched(&self) -> *mut TaskContext {
/*
self.inner.exclusive_session(|inner| { self.inner.exclusive_session(|inner| {
inner.wait_queue.push_back(current_task().unwrap()); inner.wait_queue.push_back(current_task().unwrap());
}); });
*/
let mut inner = self.inner.exclusive_access();
inner.wait_queue.push_back(current_task().unwrap());
drop(inner);
block_current_task() block_current_task()
} }

View File

@ -3,6 +3,7 @@ use core::ops::{Deref, DerefMut};
use riscv::register::sstatus; use riscv::register::sstatus;
use lazy_static::*; use lazy_static::*;
/*
/// Wrap a static data structure inside it so that we are /// Wrap a static data structure inside it so that we are
/// able to access it without any `unsafe`. /// able to access it without any `unsafe`.
/// ///
@ -30,6 +31,7 @@ impl<T> UPSafeCell<T> {
self.inner.borrow_mut() self.inner.borrow_mut()
} }
} }
*/
pub struct UPSafeCellRaw<T> { pub struct UPSafeCellRaw<T> {
inner: UnsafeCell<T>, inner: UnsafeCell<T>,
@ -105,10 +107,12 @@ impl<T> UPIntrFreeCell<T> {
UPIntrRefMut(Some(self.inner.borrow_mut())) UPIntrRefMut(Some(self.inner.borrow_mut()))
} }
/*
pub fn exclusive_session<F, V>(&self, f: F) -> V where F: FnOnce(&mut T) -> V { pub fn exclusive_session<F, V>(&self, f: F) -> V where F: FnOnce(&mut T) -> V {
let mut inner = self.exclusive_access(); let mut inner = self.exclusive_access();
f(inner.deref_mut()) f(inner.deref_mut())
} }
*/
} }
impl<'a, T> Drop for UPIntrRefMut<'a, T> { impl<'a, T> Drop for UPIntrRefMut<'a, T> {

View File

@ -50,6 +50,12 @@ fn enable_supervisor_interrupt() {
} }
} }
fn disable_supervisor_interrupt() {
unsafe {
sstatus::clear_sie();
}
}
#[no_mangle] #[no_mangle]
pub fn trap_handler() -> ! { pub fn trap_handler() -> ! {
set_kernel_trap_entry(); set_kernel_trap_entry();
@ -62,8 +68,6 @@ pub fn trap_handler() -> ! {
let mut cx = current_trap_cx(); let mut cx = current_trap_cx();
cx.sepc += 4; cx.sepc += 4;
//println!("syscall id={}", cx.x[17]);
//println!("after setting sstatus.sie");
enable_supervisor_interrupt(); enable_supervisor_interrupt();
// get system call return value // get system call return value
@ -117,6 +121,7 @@ pub fn trap_handler() -> ! {
#[no_mangle] #[no_mangle]
pub fn trap_return() -> ! { pub fn trap_return() -> ! {
disable_supervisor_interrupt();
set_user_trap_entry(); set_user_trap_entry();
let trap_cx_user_va = current_trap_cx_user_va(); let trap_cx_user_va = current_trap_cx_user_va();
let user_satp = current_user_token(); let user_satp = current_user_token();
@ -139,17 +144,7 @@ pub fn trap_return() -> ! {
} }
#[no_mangle] #[no_mangle]
pub fn trap_from_kernel(trap_cx: &TrapContext) { pub fn trap_from_kernel(_trap_cx: &TrapContext) {
/*
use riscv::register::sepc;
println!("a trap {:?} from kernel!", scause::read().cause());
println!("stval = {:#x}, sepc = {:#x}", stval::read(), sepc::read());
//panic!("a trap {:?} from kernel!", scause::read().cause());
*/
//panic!("a trap {:?} from kernel!", scause::read().cause());
//println!("->trap_from_kernel");
//println!("a trap {:?} from kernel!", scause::read().cause());
//println!("sepc = {:#x}", trap_cx.sepc);
let scause = scause::read(); let scause = scause::read();
let stval = stval::read(); let stval = stval::read();
match scause.cause() { match scause.cause() {
@ -169,7 +164,6 @@ pub fn trap_from_kernel(trap_cx: &TrapContext) {
); );
}, },
} }
//println!("trap_from_kernel->");
} }
pub use context::TrapContext; pub use context::TrapContext;