mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-11 06:16:49 +00:00
add page fault handler
This commit is contained in:
parent
429341caa6
commit
52531c6cb6
@ -20,8 +20,9 @@ pub fn handle_exception(context: &mut CpuContext) {
|
|||||||
|
|
||||||
fn handle_page_fault(trap_info: &TrapInformation) {
|
fn handle_page_fault(trap_info: &TrapInformation) {
|
||||||
const PAGE_NOT_PRESENT_ERROR_MASK: u64 = 0x1 << 0;
|
const PAGE_NOT_PRESENT_ERROR_MASK: u64 = 0x1 << 0;
|
||||||
|
const WRITE_ACCESS_MASK: u64 = 0x1 << 1;
|
||||||
if trap_info.err & PAGE_NOT_PRESENT_ERROR_MASK == 0 {
|
if trap_info.err & PAGE_NOT_PRESENT_ERROR_MASK == 0 {
|
||||||
// If page is not present, we should ask the vmar try to commit this page
|
// TODO: If page is not present, we should ask the vmar try to commit this page
|
||||||
generate_fault_signal(trap_info)
|
generate_fault_signal(trap_info)
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, the page fault is caused by page protection error.
|
// Otherwise, the page fault is caused by page protection error.
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
//! In Jinux, VMARs and VMOs, as well as other capabilities, are implemented
|
//! In Jinux, VMARs and VMOs, as well as other capabilities, are implemented
|
||||||
//! as zero-cost capabilities.
|
//! as zero-cost capabilities.
|
||||||
|
|
||||||
|
mod page_fault_handler;
|
||||||
mod perms;
|
mod perms;
|
||||||
mod vmar;
|
mod vmar;
|
||||||
mod vmo;
|
mod vmo;
|
||||||
|
12
src/services/libs/jinux-std/src/vm/page_fault_handler.rs
Normal file
12
src/services/libs/jinux-std/src/vm/page_fault_handler.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use jinux_frame::vm::Vaddr;
|
||||||
|
use jinux_frame::Result;
|
||||||
|
|
||||||
|
/// This trait is implemented by structs which can handle a user space page fault.
|
||||||
|
/// In current implementation, they are vmars and vmos.
|
||||||
|
pub trait PageFaultHandler {
|
||||||
|
/// Handle a page fault at a specific addr. if write is true, means the page fault is caused by a write access,
|
||||||
|
/// otherwise, the page fault is caused by a read access.
|
||||||
|
/// If the page fault can be handled successfully, this function will return Ok(()).
|
||||||
|
/// Otherwise, this function will return Err.
|
||||||
|
fn handle_page_fault(&self, page_fault_addr: Vaddr, write: bool) -> Result<()>;
|
||||||
|
}
|
@ -1,8 +1,14 @@
|
|||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use core::ops::Range;
|
use core::ops::Range;
|
||||||
use jinux_frame::{vm::VmIo, Error, Result};
|
use jinux_frame::{
|
||||||
|
vm::{Vaddr, VmIo},
|
||||||
|
Error, Result,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{rights::Rights, vm::vmo::Vmo};
|
use crate::{
|
||||||
|
rights::Rights,
|
||||||
|
vm::{page_fault_handler::PageFaultHandler, vmo::Vmo},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{options::VmarChildOptions, vm_mapping::VmarMapOptions, VmPerms, Vmar, Vmar_};
|
use super::{options::VmarChildOptions, vm_mapping::VmarMapOptions, VmPerms, Vmar, Vmar_};
|
||||||
|
|
||||||
@ -158,3 +164,14 @@ impl VmIo for Vmar<Rights> {
|
|||||||
self.0.write(offset, buf)
|
self.0.write(offset, buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PageFaultHandler for Vmar<Rights> {
|
||||||
|
fn handle_page_fault(&self, page_fault_addr: Vaddr, write: bool) -> Result<()> {
|
||||||
|
if write {
|
||||||
|
self.check_rights(Rights::WRITE)?;
|
||||||
|
} else {
|
||||||
|
self.check_rights(Rights::READ)?;
|
||||||
|
}
|
||||||
|
self.0.handle_page_fault(page_fault_addr, write)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -21,6 +21,8 @@ use spin::Mutex;
|
|||||||
|
|
||||||
use self::vm_mapping::VmMapping;
|
use self::vm_mapping::VmMapping;
|
||||||
|
|
||||||
|
use super::page_fault_handler::PageFaultHandler;
|
||||||
|
|
||||||
/// Virtual Memory Address Regions (VMARs) are a type of capability that manages
|
/// Virtual Memory Address Regions (VMARs) are a type of capability that manages
|
||||||
/// user address spaces.
|
/// user address spaces.
|
||||||
///
|
///
|
||||||
@ -51,6 +53,11 @@ use self::vm_mapping::VmMapping;
|
|||||||
pub struct Vmar<R = Rights>(Arc<Vmar_>, R);
|
pub struct Vmar<R = Rights>(Arc<Vmar_>, R);
|
||||||
|
|
||||||
// TODO: how page faults can be delivered to and handled by the current VMAR.
|
// TODO: how page faults can be delivered to and handled by the current VMAR.
|
||||||
|
impl<R> PageFaultHandler for Vmar<R> {
|
||||||
|
default fn handle_page_fault(&self, page_fault_addr: Vaddr, write: bool) -> Result<()> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) struct Vmar_ {
|
pub(super) struct Vmar_ {
|
||||||
/// vmar inner
|
/// vmar inner
|
||||||
@ -77,12 +84,16 @@ struct VmarInner {
|
|||||||
free_regions: BTreeMap<Vaddr, FreeRegion>,
|
free_regions: BTreeMap<Vaddr, FreeRegion>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: How to set the correct root vmar range?
|
||||||
|
// We should not include addr 0 here(is this right?), since the 0 addr means the null pointer.
|
||||||
|
// We should include addr 0x0040_0000, since non-pie executables typically are put on 0x0040_0000.
|
||||||
|
pub const ROOT_VMAR_LOWEST_ADDR: Vaddr = 0x0010_0000;
|
||||||
pub const ROOT_VMAR_HIGHEST_ADDR: Vaddr = 0x1000_0000_0000;
|
pub const ROOT_VMAR_HIGHEST_ADDR: Vaddr = 0x1000_0000_0000;
|
||||||
|
|
||||||
impl Vmar_ {
|
impl Vmar_ {
|
||||||
pub fn new_root() -> Result<Self> {
|
pub fn new_root() -> Result<Self> {
|
||||||
let mut free_regions = BTreeMap::new();
|
let mut free_regions = BTreeMap::new();
|
||||||
let root_region = FreeRegion::new(0..ROOT_VMAR_HIGHEST_ADDR);
|
let root_region = FreeRegion::new(ROOT_VMAR_LOWEST_ADDR..ROOT_VMAR_HIGHEST_ADDR);
|
||||||
free_regions.insert(root_region.start(), root_region);
|
free_regions.insert(root_region.start(), root_region);
|
||||||
let vmar_inner = VmarInner {
|
let vmar_inner = VmarInner {
|
||||||
is_destroyed: false,
|
is_destroyed: false,
|
||||||
@ -156,6 +167,34 @@ impl Vmar_ {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handle user space page fault, if the page fault is successfully handled ,return Ok(()).
|
||||||
|
pub fn handle_page_fault(&self, page_fault_addr: Vaddr, write: bool) -> Result<()> {
|
||||||
|
if page_fault_addr < self.base || page_fault_addr >= self.base + self.size {
|
||||||
|
return Err(Error::AccessDenied);
|
||||||
|
}
|
||||||
|
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
for (child_vmar_base, child_vmar) in &inner.child_vmar_s {
|
||||||
|
if *child_vmar_base <= page_fault_addr
|
||||||
|
&& page_fault_addr < *child_vmar_base + child_vmar.size
|
||||||
|
{
|
||||||
|
return child_vmar.handle_page_fault(page_fault_addr, write);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: If multiple vmos are mapped to the addr, should we allow all vmos to handle page fault?
|
||||||
|
for (vm_mapping_base, vm_mapping) in &inner.mapped_vmos {
|
||||||
|
if *vm_mapping_base <= page_fault_addr
|
||||||
|
&& page_fault_addr <= *vm_mapping_base + vm_mapping.size()
|
||||||
|
{
|
||||||
|
return vm_mapping.handle_page_fault(page_fault_addr, write);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(Error::AccessDenied);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn destroy_all(&self) -> Result<()> {
|
pub fn destroy_all(&self) -> Result<()> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
use core::ops::Range;
|
use core::ops::Range;
|
||||||
|
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use jinux_frame::{vm::VmIo, Error, Result};
|
use jinux_frame::{
|
||||||
|
vm::{Vaddr, VmIo},
|
||||||
|
Error, Result,
|
||||||
|
};
|
||||||
use jinux_rights_proc::require;
|
use jinux_rights_proc::require;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
rights::{Dup, Rights, TRights},
|
rights::{Dup, Rights, TRights},
|
||||||
vm::vmo::Vmo,
|
vm::{page_fault_handler::PageFaultHandler, vmo::Vmo},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{options::VmarChildOptions, vm_mapping::VmarMapOptions, VmPerms, Vmar, Vmar_};
|
use super::{options::VmarChildOptions, vm_mapping::VmarMapOptions, VmPerms, Vmar, Vmar_};
|
||||||
@ -171,3 +174,14 @@ impl<R: TRights> VmIo for Vmar<R> {
|
|||||||
self.0.write(offset, buf)
|
self.0.write(offset, buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<R: TRights> PageFaultHandler for Vmar<R> {
|
||||||
|
fn handle_page_fault(&self, page_fault_addr: Vaddr, write: bool) -> Result<()> {
|
||||||
|
if write {
|
||||||
|
self.check_rights(Rights::WRITE)?;
|
||||||
|
} else {
|
||||||
|
self.check_rights(Rights::READ)?;
|
||||||
|
}
|
||||||
|
self.0.handle_page_fault(page_fault_addr, write)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,18 +4,18 @@ use alloc::{
|
|||||||
};
|
};
|
||||||
use jinux_frame::{
|
use jinux_frame::{
|
||||||
config::PAGE_SIZE,
|
config::PAGE_SIZE,
|
||||||
vm::{Vaddr, VmFrameVec, VmPerm},
|
vm::{Vaddr, VmFrameVec, VmIo, VmPerm},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
use jinux_frame::{vm::VmMapOptions, Result};
|
use jinux_frame::{vm::VmMapOptions, Result};
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
|
||||||
use crate::vm::vmo::{Pager, Vmo, Vmo_};
|
use crate::vm::{page_fault_handler::PageFaultHandler, vmo::Vmo};
|
||||||
|
|
||||||
use super::{Vmar, Vmar_};
|
use super::{Vmar, Vmar_};
|
||||||
use crate::vm::perms::VmPerms;
|
use crate::vm::perms::VmPerms;
|
||||||
use crate::vm::vmar::Rights;
|
use crate::vm::vmar::Rights;
|
||||||
use crate::vm::vmo::VmoRights;
|
use crate::vm::vmo::VmoRightsOp;
|
||||||
|
|
||||||
/// A VmMapping represents mapping a vmo into a vmar.
|
/// A VmMapping represents mapping a vmo into a vmar.
|
||||||
/// A vmar can has multiple VmMappings, which means multiple vmos are mapped to a vmar.
|
/// A vmar can has multiple VmMappings, which means multiple vmos are mapped to a vmar.
|
||||||
@ -24,8 +24,8 @@ use crate::vm::vmo::VmoRights;
|
|||||||
pub struct VmMapping {
|
pub struct VmMapping {
|
||||||
/// The parent vmar. The parent should always point to a valid vmar.
|
/// The parent vmar. The parent should always point to a valid vmar.
|
||||||
parent: Weak<Vmar_>,
|
parent: Weak<Vmar_>,
|
||||||
/// The mapped vmo.
|
/// The mapped vmo. The mapped vmo is with dynamic capability.
|
||||||
vmo: Arc<Vmo_>,
|
vmo: Vmo<Rights>,
|
||||||
/// The mao offset of the vmo, in bytes.
|
/// The mao offset of the vmo, in bytes.
|
||||||
vmo_offset: usize,
|
vmo_offset: usize,
|
||||||
/// The size of mapping, in bytes. The map size can even be larger than the size of backup vmo.
|
/// The size of mapping, in bytes. The map size can even be larger than the size of backup vmo.
|
||||||
@ -54,8 +54,8 @@ impl VmMapping {
|
|||||||
can_overwrite,
|
can_overwrite,
|
||||||
} = option;
|
} = option;
|
||||||
let Vmar(parent_vmar, _) = parent;
|
let Vmar(parent_vmar, _) = parent;
|
||||||
let vmo_ = vmo.0;
|
let vmo = vmo.to_dyn();
|
||||||
let vmo_size = vmo_.size();
|
let vmo_size = vmo.size();
|
||||||
let map_to_addr = parent_vmar.allocate_free_region_for_vmo(
|
let map_to_addr = parent_vmar.allocate_free_region_for_vmo(
|
||||||
vmo_size,
|
vmo_size,
|
||||||
size,
|
size,
|
||||||
@ -79,8 +79,8 @@ impl VmMapping {
|
|||||||
vm_map_options.perm(perm);
|
vm_map_options.perm(perm);
|
||||||
vm_map_options.can_overwrite(can_overwrite);
|
vm_map_options.can_overwrite(can_overwrite);
|
||||||
vm_map_options.align(align);
|
vm_map_options.align(align);
|
||||||
if vmo_.page_commited(page_idx) {
|
if vmo.page_commited(page_idx) {
|
||||||
vmo_.map_page(page_idx, &vm_space, vm_map_options)?;
|
vmo.map_page(page_idx, &vm_space, vm_map_options)?;
|
||||||
mapped_pages.insert(page_idx);
|
mapped_pages.insert(page_idx);
|
||||||
} else {
|
} else {
|
||||||
// The page is not committed. We simple record the map options for further mapping.
|
// The page is not committed. We simple record the map options for further mapping.
|
||||||
@ -89,7 +89,7 @@ impl VmMapping {
|
|||||||
}
|
}
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
parent: Arc::downgrade(&parent_vmar),
|
parent: Arc::downgrade(&parent_vmar),
|
||||||
vmo: vmo_,
|
vmo,
|
||||||
vmo_offset,
|
vmo_offset,
|
||||||
map_size: size,
|
map_size: size,
|
||||||
map_to_addr,
|
map_to_addr,
|
||||||
@ -137,6 +137,11 @@ impl VmMapping {
|
|||||||
let vmo_write_offset = self.vmo_offset + offset;
|
let vmo_write_offset = self.vmo_offset + offset;
|
||||||
self.vmo.write_bytes(vmo_write_offset, buf)
|
self.vmo.write_bytes(vmo_write_offset, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_page_fault(&self, page_fault_addr: Vaddr, write: bool) -> Result<()> {
|
||||||
|
let vmo_offset = self.vmo_offset + page_fault_addr - self.map_to_addr;
|
||||||
|
self.vmo.handle_page_fault(vmo_offset, write)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Options for creating a new mapping. The mapping is not allowed to overlap
|
/// Options for creating a new mapping. The mapping is not allowed to overlap
|
||||||
|
@ -5,7 +5,7 @@ use jinux_frame::{vm::VmIo, Error};
|
|||||||
|
|
||||||
use crate::rights::{Rights, TRights};
|
use crate::rights::{Rights, TRights};
|
||||||
|
|
||||||
use super::VmoRights;
|
use super::VmoRightsOp;
|
||||||
use super::{
|
use super::{
|
||||||
options::{VmoCowChild, VmoSliceChild},
|
options::{VmoCowChild, VmoSliceChild},
|
||||||
Vmo, VmoChildOptions,
|
Vmo, VmoChildOptions,
|
||||||
@ -142,12 +142,6 @@ impl Vmo<Rights> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VmoRights for Vmo<Rights> {
|
|
||||||
fn rights(&self) -> Rights {
|
|
||||||
self.1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VmIo for Vmo<Rights> {
|
impl VmIo for Vmo<Rights> {
|
||||||
fn read_bytes(&self, offset: usize, buf: &mut [u8]) -> Result<()> {
|
fn read_bytes(&self, offset: usize, buf: &mut [u8]) -> Result<()> {
|
||||||
self.check_rights(Rights::READ)?;
|
self.check_rights(Rights::READ)?;
|
||||||
@ -159,3 +153,15 @@ impl VmIo for Vmo<Rights> {
|
|||||||
self.0.write_bytes(offset, buf)
|
self.0.write_bytes(offset, buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl VmoRightsOp for Vmo<Rights> {
|
||||||
|
fn rights(&self) -> Rights {
|
||||||
|
self.1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts to a dynamic capability.
|
||||||
|
fn to_dyn(self) -> Vmo<Rights> {
|
||||||
|
let rights = self.rights();
|
||||||
|
Vmo(self.0, rights)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -22,7 +22,8 @@ pub use options::{VmoChildOptions, VmoOptions};
|
|||||||
pub use pager::Pager;
|
pub use pager::Pager;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
|
||||||
use super::vmar::vm_mapping::{self, VmMapping};
|
use super::page_fault_handler::PageFaultHandler;
|
||||||
|
use super::vmar::vm_mapping::VmMapping;
|
||||||
|
|
||||||
/// Virtual Memory Objects (VMOs) are a type of capability that represents a
|
/// Virtual Memory Objects (VMOs) are a type of capability that represents a
|
||||||
/// range of memory pages.
|
/// range of memory pages.
|
||||||
@ -82,7 +83,7 @@ use super::vmar::vm_mapping::{self, VmMapping};
|
|||||||
pub struct Vmo<R = Rights>(pub(super) Arc<Vmo_>, R);
|
pub struct Vmo<R = Rights>(pub(super) Arc<Vmo_>, R);
|
||||||
|
|
||||||
/// Functions exist both for static capbility and dynamic capibility
|
/// Functions exist both for static capbility and dynamic capibility
|
||||||
pub trait VmoRights {
|
pub trait VmoRightsOp {
|
||||||
/// Returns the access rights.
|
/// Returns the access rights.
|
||||||
fn rights(&self) -> Rights;
|
fn rights(&self) -> Rights;
|
||||||
|
|
||||||
@ -94,14 +95,37 @@ pub trait VmoRights {
|
|||||||
Err(Error::AccessDenied)
|
Err(Error::AccessDenied)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts to a dynamic capability.
|
||||||
|
fn to_dyn(self) -> Vmo<Rights>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We implement this trait for Vmo, so we can use functions on type like Vmo<R> without trait bounds.
|
// We implement this trait for Vmo, so we can use functions on type like Vmo<R> without trait bounds.
|
||||||
// FIXME: This requires the imcomplete feature specialization, which should be fixed further.
|
// FIXME: This requires the imcomplete feature specialization, which should be fixed further.
|
||||||
impl<R> VmoRights for Vmo<R> {
|
impl<R> VmoRightsOp for Vmo<R> {
|
||||||
default fn rights(&self) -> Rights {
|
default fn rights(&self) -> Rights {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default fn to_dyn(self) -> Vmo<Rights>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R> PageFaultHandler for Vmo<R> {
|
||||||
|
default fn handle_page_fault(&self, page_fault_addr: Vaddr, write: bool) -> Result<()> {
|
||||||
|
if write {
|
||||||
|
self.check_rights(Rights::WRITE)?;
|
||||||
|
} else {
|
||||||
|
self.check_rights(Rights::READ)?;
|
||||||
|
}
|
||||||
|
self.0.handle_page_fault(page_fault_addr, write)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
@ -155,10 +179,6 @@ struct VmoInner {
|
|||||||
inherited_pages: InheritedPages,
|
inherited_pages: InheritedPages,
|
||||||
/// The current mapping on this vmo. The vmo can be mapped to multiple vmars.
|
/// The current mapping on this vmo. The vmo can be mapped to multiple vmars.
|
||||||
mappings: Vec<Weak<VmMapping>>,
|
mappings: Vec<Weak<VmMapping>>,
|
||||||
// Pages should be filled with zeros when committed. When create COW child, the pages exceed the range of parent vmo
|
|
||||||
// should be in this set. According to the on demand requirement, when read or write these pages for the first time,
|
|
||||||
// we should commit these pages and zeroed these pages.
|
|
||||||
// pages_should_fill_zeros: BTreeSet<usize>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pages inherited from parent
|
/// Pages inherited from parent
|
||||||
@ -273,6 +293,16 @@ impl Vmo_ {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handle page fault.
|
||||||
|
pub fn handle_page_fault(&self, offset: usize, write: bool) -> Result<()> {
|
||||||
|
if offset >= self.size() {
|
||||||
|
return Err(Error::AccessDenied);
|
||||||
|
}
|
||||||
|
let page_idx = offset / PAGE_SIZE;
|
||||||
|
self.ensure_page_exists(page_idx, write)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// determine whether a page is commited
|
/// determine whether a page is commited
|
||||||
pub fn page_commited(&self, page_idx: usize) -> bool {
|
pub fn page_commited(&self, page_idx: usize) -> bool {
|
||||||
self.inner.lock().committed_pages.contains_key(&page_idx)
|
self.inner.lock().committed_pages.contains_key(&page_idx)
|
||||||
@ -283,7 +313,7 @@ impl Vmo_ {
|
|||||||
&self,
|
&self,
|
||||||
page_idx: usize,
|
page_idx: usize,
|
||||||
vm_space: &VmSpace,
|
vm_space: &VmSpace,
|
||||||
options: VmMapOptions,
|
map_options: VmMapOptions,
|
||||||
) -> Result<Vaddr> {
|
) -> Result<Vaddr> {
|
||||||
debug_assert!(self.page_commited(page_idx));
|
debug_assert!(self.page_commited(page_idx));
|
||||||
if !self.page_commited(page_idx) {
|
if !self.page_commited(page_idx) {
|
||||||
@ -296,7 +326,7 @@ impl Vmo_ {
|
|||||||
.get(&page_idx)
|
.get(&page_idx)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone();
|
.clone();
|
||||||
vm_space.map(frames, &options)
|
vm_space.map(frames, &map_options)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_mapping(&self, mapping: Weak<VmMapping>) {
|
pub fn add_mapping(&self, mapping: Weak<VmMapping>) {
|
||||||
@ -440,4 +470,19 @@ impl<R> Vmo<R> {
|
|||||||
pub fn flags(&self) -> VmoFlags {
|
pub fn flags(&self) -> VmoFlags {
|
||||||
self.0.flags()
|
self.0.flags()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// return whether a page is already committed
|
||||||
|
pub fn page_commited(&self, page_idx: usize) -> bool {
|
||||||
|
self.0.page_commited(page_idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// map a committed page, returns the map address
|
||||||
|
pub fn map_page(
|
||||||
|
&self,
|
||||||
|
page_idx: usize,
|
||||||
|
vm_space: &VmSpace,
|
||||||
|
map_options: VmMapOptions,
|
||||||
|
) -> Result<Vaddr> {
|
||||||
|
self.0.map_page(page_idx, vm_space, map_options)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ use crate::vm::vmo::InheritedPages;
|
|||||||
use crate::vm::vmo::VmoType;
|
use crate::vm::vmo::VmoType;
|
||||||
use crate::vm::vmo::{VmoInner, Vmo_};
|
use crate::vm::vmo::{VmoInner, Vmo_};
|
||||||
|
|
||||||
use super::VmoRights;
|
use super::VmoRightsOp;
|
||||||
use super::{Pager, Vmo, VmoFlags};
|
use super::{Pager, Vmo, VmoFlags};
|
||||||
|
|
||||||
/// Options for allocating a root VMO.
|
/// Options for allocating a root VMO.
|
||||||
|
@ -6,7 +6,7 @@ use jinux_rights_proc::require;
|
|||||||
|
|
||||||
use crate::rights::*;
|
use crate::rights::*;
|
||||||
|
|
||||||
use super::VmoRights;
|
use super::VmoRightsOp;
|
||||||
use super::{
|
use super::{
|
||||||
options::{VmoCowChild, VmoSliceChild},
|
options::{VmoCowChild, VmoSliceChild},
|
||||||
Vmo, VmoChildOptions,
|
Vmo, VmoChildOptions,
|
||||||
@ -134,12 +134,6 @@ impl<R: TRights> Vmo<R> {
|
|||||||
pub fn restrict<R1: TRights>(self) -> Vmo<R1> {
|
pub fn restrict<R1: TRights>(self) -> Vmo<R1> {
|
||||||
Vmo(self.0, R1::new())
|
Vmo(self.0, R1::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts to a dynamic capability.
|
|
||||||
pub fn to_dyn(self) -> Vmo<Rights> {
|
|
||||||
let rights = self.rights();
|
|
||||||
Vmo(self.0, rights)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: TRights> VmIo for Vmo<R> {
|
impl<R: TRights> VmIo for Vmo<R> {
|
||||||
@ -154,8 +148,14 @@ impl<R: TRights> VmIo for Vmo<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: TRights> VmoRights for Vmo<R> {
|
impl<R: TRights> VmoRightsOp for Vmo<R> {
|
||||||
fn rights(&self) -> Rights {
|
fn rights(&self) -> Rights {
|
||||||
Rights::from_bits(R::BITS).unwrap()
|
Rights::from_bits(R::BITS).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts to a dynamic capability.
|
||||||
|
fn to_dyn(self) -> Vmo<Rights> {
|
||||||
|
let rights = self.rights();
|
||||||
|
Vmo(self.0, rights)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user