remove Mutex in drivers::irq::intc::{xxx_handler}

This commit is contained in:
DeathWish5 2022-03-24 14:34:10 +08:00
parent 682d274998
commit 3559a39b1f
23 changed files with 151 additions and 114 deletions

3
.gitmodules vendored
View File

@ -1,9 +1,6 @@
[submodule "rboot"]
path = rboot
url = https://github.com/rcore-os/rboot.git
[submodule "rcore-user"]
path = linux-user
url = https://github.com/DeathWish5/rcore-user.git
[submodule "tests"]
path = tests
url = https://github.com/rcore-os/zcore-tests.git

View File

@ -62,10 +62,7 @@ image: $(OUT_IMG)
@echo Resizing $(ARCH).img
@qemu-img resize $(OUT_IMG) +5M
rcore-user: riscv-rootfs
@make -C linux-user zcore-img ARCH=$(ARCH)
riscv-image: rcore-user # rcore-fs-fuse riscv-rootfs
riscv-image: rcore-fs-fuse riscv-rootfs
@echo building riscv.img
@rcore-fs-fuse zCore/riscv64.img riscv_rootfs zip
@qemu-img resize -f raw zCore/riscv64.img +5M

View File

@ -1,6 +1,7 @@
use riscv::register::sie;
// use spin::Mutex;
use lock::mutex::Mutex;
use spin::Once;
use crate::prelude::IrqHandler;
use crate::scheme::{IrqScheme, Scheme};
@ -22,31 +23,62 @@ pub enum ScauseIntCode {
SupervisorExternal = S_EXT,
}
// pub struct Intc {
// name: String,
// soft_handler: Mutex<Option<IrqHandler>>,
// timer_handler: Mutex<Option<IrqHandler>>,
// ext_handler: Mutex<Option<IrqHandler>>,
// }
pub struct Intc {
name: String,
soft_handler: Mutex<Option<IrqHandler>>,
timer_handler: Mutex<Option<IrqHandler>>,
ext_handler: Mutex<Option<IrqHandler>>,
soft_handler: Once<IrqHandler>,
timer_handler: Once<IrqHandler>,
ext_handler: Once<IrqHandler>,
}
impl Intc {
// pub fn new() -> Self {
// Self {
// name: format!("riscv-intc-cpu{}", INTC_NUM.fetch_add(1, Ordering::Relaxed)),
// soft_handler: Mutex::new(None),
// timer_handler: Mutex::new(None),
// ext_handler: Mutex::new(None),
// }
// }
pub fn new() -> Self {
Self {
name: format!("riscv-intc-cpu{}", INTC_NUM.fetch_add(1, Ordering::Relaxed)),
soft_handler: Mutex::new(None),
timer_handler: Mutex::new(None),
ext_handler: Mutex::new(None),
soft_handler: Once::new(),
timer_handler: Once::new(),
ext_handler: Once::new(),
}
}
// fn with_handler<F>(&self, cause: usize, op: F) -> DeviceResult
// where
// F: FnOnce(&mut Option<IrqHandler>) -> DeviceResult,
// {
// match cause {
// S_SOFT => op(&self.soft_handler.lock()),
// S_TIMER => op(&self.timer_handler.lock()),
// S_EXT => op(&mut self.ext_handler.lock()),
// _ => {
// error!("invalid SCAUSE value {:#x}!", cause);
// Err(DeviceError::InvalidParam)
// }
// }
// }
fn with_handler<F>(&self, cause: usize, op: F) -> DeviceResult
where
F: FnOnce(&mut Option<IrqHandler>) -> DeviceResult,
F: FnOnce(&Once<IrqHandler>) -> DeviceResult,
{
match cause {
S_SOFT => op(&mut self.soft_handler.lock()),
S_TIMER => op(&mut self.timer_handler.lock()),
S_EXT => op(&mut self.ext_handler.lock()),
S_SOFT => op(&self.soft_handler),
S_TIMER => op(&self.timer_handler),
S_EXT => op(&self.ext_handler),
_ => {
error!("invalid SCAUSE value {:#x}!", cause);
Err(DeviceError::InvalidParam)
@ -66,9 +98,23 @@ impl Scheme for Intc {
self.name.as_str()
}
// fn handle_irq(&self, cause: usize) {
// info!("intc handle irq, cause {}", cause);
// self.with_handler(cause, |opt| {
// if let Some(h) = opt {
// h();
// } else {
// warn!("no registered handler for SCAUSE {}!", cause);
// }
// Ok(())
// })
// .unwrap();
// }
fn handle_irq(&self, cause: usize) {
info!("intc handle irq, cause {}", cause);
self.with_handler(cause, |opt| {
if let Some(h) = opt {
if let Some(h) = opt.get() {
h();
} else {
warn!("no registered handler for SCAUSE {}!", cause);
@ -110,23 +156,24 @@ impl IrqScheme for Intc {
fn register_handler(&self, cause: usize, handler: IrqHandler) -> DeviceResult {
self.with_handler(cause, |opt| {
if opt.is_some() {
if opt.is_completed() {
Err(DeviceError::AlreadyExists)
} else {
*opt = Some(handler);
opt.call_once(|| handler);
Ok(())
}
})
}
fn unregister(&self, cause: usize) -> DeviceResult {
self.with_handler(cause, |opt| {
if opt.is_some() {
*opt = None;
Ok(())
} else {
Err(DeviceError::InvalidParam)
}
})
fn unregister(&self, _cause: usize) -> DeviceResult {
panic!("unregister intc handler unsupported!");
// self.with_handler(cause, |opt| {
// if opt.is_some() {
// *opt = None;
// Ok(())
// } else {
// Err(DeviceError::InvalidParam)
// }
// })
}
}

View File

@ -62,6 +62,21 @@ pub(super) fn init() -> DeviceResult {
}
}
intc_init()?;
#[cfg(feature = "graphic")]
if let Some(display) = drivers::all_display().first() {
crate::console::init_graphic_console(display.clone());
if display.need_flush() {
// TODO: support nested interrupt to render in time
crate::thread::spawn(crate::common::future::DisplayFlushFuture::new(display, 30));
}
}
Ok(())
}
pub(super) fn intc_init() -> DeviceResult {
let irq = drivers::all_irq()
.find(format!("riscv-intc-cpu{}", crate::cpu::cpu_id()).as_str())
.expect("IRQ device 'riscv-intc' not initialized!");
@ -76,16 +91,6 @@ pub(super) fn init() -> DeviceResult {
Box::new(super::trap::super_timer),
)?;
irq.unmask(ScauseIntCode::SupervisorSoft as _)?;
irq.unmask(ScauseIntCode::SupervisorTimer as _)?;
#[cfg(feature = "graphic")]
if let Some(display) = drivers::all_display().first() {
crate::console::init_graphic_console(display.clone());
if display.need_flush() {
// TODO: support nested interrupt to render in time
crate::thread::spawn(crate::common::future::DisplayFlushFuture::new(display, 30));
}
}
irq.unmask(ScauseIntCode::SupervisorTimer as _)?;
Ok(())
}
}

View File

@ -17,6 +17,7 @@ hal_fn_impl! {
fn handle_irq(cause: usize) {
trace!("Handle irq cause: {}", cause);
warn!("Handle irq cause: {}", cause);
crate::drivers::all_irq().first_unwrap().handle_irq(cause)
}

View File

@ -9,9 +9,8 @@ pub mod sbi;
pub mod timer;
pub mod vm;
use alloc::{boxed::Box, format, string::String, vec::Vec};
use alloc::{string::String, vec::Vec};
use core::ops::Range;
use zcore_drivers::irq::riscv::ScauseIntCode;
use zcore_drivers::utils::devicetree::Devicetree;
use crate::{mem::phys_to_virt, utils::init_once::InitOnce, PhysAddr};
@ -53,33 +52,20 @@ pub fn primary_init_early() {
pub fn primary_init() {
vm::init();
drivers::init().unwrap();
// We should set first time interrupt before run into first user program
// timer::init();
}
pub fn timer_init() {
timer::init();
}
pub fn secondary_init() {
vm::init();
let intc = crate::drivers::all_irq()
.find(format!("riscv-intc-cpu{}", crate::cpu::cpu_id()).as_str())
.expect("IRQ device 'riscv-intc' not initialized!");
// register soft interrupts handler
intc.register_handler(
ScauseIntCode::SupervisorSoft as _,
Box::new(trap::super_soft),
)
.unwrap();
// register timer interrupts handler
intc.register_handler(
ScauseIntCode::SupervisorTimer as _,
Box::new(trap::super_timer),
)
.unwrap();
intc.unmask(ScauseIntCode::SupervisorSoft as _).unwrap();
intc.unmask(ScauseIntCode::SupervisorTimer as _).unwrap();
drivers::intc_init().unwrap();
let plic = crate::drivers::all_irq()
.find("riscv-plic")
.expect("IRQ device 'riscv-plic' not initialized!");
plic.init_hart();
timer::init();
// timer::init();
}

View File

@ -7,7 +7,7 @@ fn get_cycle() -> u64 {
pub(super) fn timer_set_next() {
let cycles =
super::cpu::cpu_frequency() as u64 * 1_000_000 / super::super::timer::TICKS_PER_SEC;
super::sbi::set_timer(get_cycle() + cycles * 20);
super::sbi::set_timer(get_cycle() + cycles);
}
pub(super) fn init() {

View File

@ -14,8 +14,7 @@ fn breakpoint(sepc: &mut usize) {
pub(super) fn super_timer() {
super::timer::timer_set_next();
crate::timer::timer_tick();
error!("time interrupt in kernel, runtime sched yield");
debug!("time interrupt in kernel, runtime sched yield");
executor::sched_yield();
//发生外界中断时epc的指令还没有执行故无需修改epc到下一条
}
@ -31,7 +30,6 @@ pub extern "C" fn trap_handler(tf: &mut TrapFrame) {
let scause = scause::read();
trace!("trap happened: {:?}", TrapReason::from(scause));
match TrapReason::from(scause) {
TrapReason::SoftwareBreakpoint => breakpoint(&mut tf.sepc),
TrapReason::PageFault(vaddr, flags) => {

View File

@ -52,6 +52,10 @@ pub fn primary_init() {
}
}
pub fn timer_init() {
// DO NOTHING
}
pub fn secondary_init() {
zcore_drivers::irq::x86::Apic::init_local_apic_ap();
}

View File

@ -4,3 +4,5 @@ pub fn timer_now() -> Duration {
let cycle = unsafe { core::arch::x86_64::_rdtsc() };
Duration::from_nanos(cycle * 1000 / super::cpu::cpu_frequency() as u64)
}
pub fn timer_init

View File

@ -6,16 +6,25 @@ use core::time::Duration;
use naive_timer::Timer;
// use spin::Mutex;
use lock::mutex::Mutex;
use core::sync::atomic::{AtomicBool, Ordering};
#[allow(dead_code)]
pub(super) const TICKS_PER_SEC: u64 = 100;
lazy_static! {
static ref NAIVE_TIMER: Mutex<Timer> = Mutex::new(Timer::default());
static ref FIRST: AtomicBool = AtomicBool::new(false);
}
hal_fn_impl! {
impl mod crate::hal_fn::timer {
fn timer_set_first() {
if FIRST.load(Ordering::Relaxed) == false {
FIRST.store(true, Ordering::Relaxed);
super::arch::timer_init();
}
}
fn timer_now() -> Duration {
super::arch::timer::timer_now()
}

View File

@ -157,6 +157,9 @@ hal_fn_def! {
/// Time and clock functions.
pub mod timer {
/// Set the first time interrupt
pub fn timer_set_first();
/// Get current time.
/// TODO: use `Instant` as return type.
pub fn timer_now() -> Duration;

View File

@ -46,25 +46,3 @@ pub use kernel_handler::KernelHandler;
#[cfg(any(feature = "smp", doc))]
#[doc(cfg(feature = "smp"))]
pub use imp::boot::{primary_init, primary_init_early, secondary_init};
mod interrupt_ffi {
#[no_mangle]
extern "C" fn intr_on() {
super::interrupt::intr_on();
}
#[no_mangle]
extern "C" fn intr_off() {
super::interrupt::intr_off();
}
#[no_mangle]
extern "C" fn intr_get() -> bool {
super::interrupt::intr_get()
}
#[no_mangle]
extern "C" fn cpu_id() -> u8 {
super::cpu::cpu_id()
}
}

View File

@ -110,7 +110,6 @@ impl INode for Stdin {
true
}
}));
info!("stdio poll intr = {}", kernel_hal::interrupt::intr_get());
Poll::Pending
}
}

View File

@ -199,7 +199,6 @@ impl Syscall<'_> {
// TODO: use right signal
// self.zircon_process().signal_set(Signal::SIGNALED);
// Workaround, the child process could NOT exit correctly
self.thread
.with_context(|ctx| ctx.setup_uspace(entry, sp, 0, 0))?;
Ok(0)

@ -1 +0,0 @@
Subproject commit 5f06314100c0a38fefa52a18c67de24c5945d0f9

View File

@ -61,11 +61,10 @@ async fn run_user(thread: CurrentThread) {
// run
trace!("go to user: {:#x?}", ctx);
info!("go to user");
kernel_hal::interrupt::intr_off(); // trapframe can't be interrupted
ctx.enter_uspace();
// info!("back form user");
kernel_hal::interrupt::intr_on();
trace!("back from user: {:#x?}", ctx);
// handle trap/interrupt/syscall
if let Err(err) = handle_user_trap(&thread, ctx).await {
thread.exit_linux(err as i32);
@ -75,7 +74,6 @@ async fn run_user(thread: CurrentThread) {
async fn handle_user_trap(thread: &CurrentThread, mut ctx: Box<UserContext>) -> ZxResult {
let reason = ctx.trap_reason();
info!("trap from user mode : {:?}", reason);
if let TrapReason::Syscall = reason {
let num = syscall_num(&ctx);
let args = syscall_args(&ctx);
@ -86,6 +84,7 @@ async fn handle_user_trap(thread: &CurrentThread, mut ctx: Box<UserContext>) ->
thread_fn,
syscall_entry: kernel_hal::context::syscall_entry as usize,
};
trace!("Syscall : {} {:x?}", num as u32, args);
let ret = syscall.syscall(num as u32, args).await as usize;
thread.with_context(|ctx| ctx.set_field(UserContextField::ReturnValue, ret))?;
return Ok(());

7
zCore/.gdbinit Normal file
View File

@ -0,0 +1,7 @@
set confirm off
set architecture riscv:rv64
target remote 127.0.0.1:15234
symbol-file ../target/riscv64/release/zcore
display/10i $pc
break *0x8020004a
break

View File

@ -1,9 +1,9 @@
################ Arguments ################
ARCH ?= riscv64
ARCH ?= x86_64
PLATFORM ?= qemu
MODE ?= release
LOG ?= debug
LOG ?= warn
LINUX ?= 1
LIBOS ?=
TEST ?=
@ -18,7 +18,8 @@ ZBI ?= bringup
SMP ?= 1
ACCEL ?=
OBJDUMP ?= rust-objdump --print-imm-hex --x86-asm-syntax=intel
# OBJDUMP ?= rust-objdump --print-imm-hex --x86-asm-syntax=intel
OBJDUMP ?= riscv64-linux-musl-objdump
OBJCOPY ?= rust-objcopy --binary-architecture=$(ARCH)
ifeq ($(LINUX), 1)
@ -210,11 +211,17 @@ ifeq ($(ARCH), x86_64)
endif
$(qemu) $(qemu_opts)
ifeq ($(ARCH), x86_64)
gdb := gdb
else
gdb := riscv64-unknown-elf-gdb
endif
.PHONY: debugrun
debugrun: $(qemu_disk)
$(qemu) $(qemu_opts) -s -S &
$(qemu) $(qemu_opts) -S -gdb tcp::15234 &
@sleep 1
gdb $(kernel_elf) -tui -x gdbinit
$(gdb)
.PHONY: kernel
kernel:
@ -223,7 +230,7 @@ kernel:
.PHONY: disasm
disasm:
$(OBJDUMP) -d $(kernel_elf) | less
$(OBJDUMP) -d $(kernel_elf) > kernel.asm
.PHONY: header
header:

View File

@ -1 +0,0 @@
target remote :1234

View File

@ -10,8 +10,9 @@ pub fn init() {
/// Reset max log level.
pub fn set_max_level(_level: &str) {
// log::set_max_level(level.parse().unwrap_or(LevelFilter::Warn));
log::set_max_level(LevelFilter::Info);
// log::set_max_level(LevelFilter::Off);
// log::set_max_level(LevelFilter::Info);
log::set_max_level(level.parse().unwrap_or(LevelFilter::Warn));
}
pub fn print(args: fmt::Arguments) {

View File

@ -60,8 +60,7 @@ pub fn boot_options() -> BootOptions {
cmdline: cmdline.clone(),
log_level: String::from(*options.get("LOG").unwrap_or(&"")),
#[cfg(feature = "linux")]
// root_proc: String::from(*options.get("ROOTPROC").unwrap_or(&"/bin/busybox?sh")),
root_proc: String::from(*options.get("ROOTPROC").unwrap_or(&"/linux-user/ucore/kernel_intr_test")),
root_proc: String::from(*options.get("ROOTPROC").unwrap_or(&"/bin/busybox?sh")),
}
}
}
@ -119,12 +118,13 @@ pub fn wait_for_exit(proc: Option<Arc<Process>>) -> ! {
#[cfg(not(feature = "libos"))]
pub fn wait_for_exit(proc: Option<Arc<Process>>) -> ! {
kernel_hal::timer::timer_set_first();
loop {
executor::run_until_idle();
// if cfg!(feature = "baremetal-test") && !has_task {
// proc.map(check_exit_code);
// kernel_hal::cpu::reset();
// }
if cfg!(feature = "baremetal-test") && !has_task {
proc.map(check_exit_code);
kernel_hal::cpu::reset();
}
kernel_hal::interrupt::wait_for_interrupt();
}
}

View File

@ -6,7 +6,7 @@ use {
kernel_hal::vm::{
GenericPageTable, IgnoreNotMappedErr, Page, PageSize, PageTable, PagingError, PagingResult,
},
lock::mutex::Mutex,
lock::mutex::Mutex,
// spin::Mutex,
};
@ -403,12 +403,12 @@ impl VmAddressRegion {
!self.is_dead()
}
/// get flags of vaddr
/// Get flags of vaddr
pub fn get_vaddr_flags(&self, vaddr: usize) -> PagingResult<MMUFlags> {
let guard = self.inner.lock();
let inner = guard.as_ref().unwrap();
if !self.contains(vaddr) {
return Err(PagingError::NoMemory);
return Err(PagingError::NotMapped);
}
if let Some(child) = inner.children.iter().find(|ch| ch.contains(vaddr)) {
return child.get_vaddr_flags(vaddr);