forked from rcore-os/zCore
remove Mutex in drivers::irq::intc::{xxx_handler}
This commit is contained in:
parent
682d274998
commit
3559a39b1f
|
@ -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
|
||||
|
|
5
Makefile
5
Makefile
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
// }
|
||||
// })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -110,7 +110,6 @@ impl INode for Stdin {
|
|||
true
|
||||
}
|
||||
}));
|
||||
info!("stdio poll intr = {}", kernel_hal::interrupt::intr_get());
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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(());
|
||||
|
|
|
@ -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
|
|
@ -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:
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
target remote :1234
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue