mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-30 10:23:29 +00:00
VMO and VMAR passed the compilation
This commit is contained in:
3
src/Cargo.lock
generated
3
src/Cargo.lock
generated
@ -150,6 +150,9 @@ dependencies = [
|
||||
"kxos-frame",
|
||||
"kxos-frame-pod-derive",
|
||||
"kxos-pci",
|
||||
"kxos-rights-proc",
|
||||
"kxos-typeflags",
|
||||
"kxos-typeflags-util",
|
||||
"kxos-virtio",
|
||||
"lazy_static",
|
||||
"spin 0.9.4",
|
||||
|
@ -10,6 +10,9 @@ kxos-frame = {path = "../kxos-frame"}
|
||||
kxos-frame-pod-derive = {path = "../kxos-frame-pod-derive"}
|
||||
kxos-pci = {path="../kxos-pci"}
|
||||
kxos-virtio = {path="../kxos-virtio"}
|
||||
kxos-typeflags = {path="../kxos-typeflags"}
|
||||
kxos-typeflags-util = {path="../kxos-typeflags-util"}
|
||||
kxos-rights-proc = {path="../kxos-rights-proc"}
|
||||
|
||||
# parse elf file
|
||||
xmas-elf = "0.8.0"
|
||||
|
@ -8,6 +8,7 @@
|
||||
#![feature(half_open_range_patterns)]
|
||||
#![feature(exclusive_range_pattern)]
|
||||
#![feature(btree_drain_filter)]
|
||||
#![feature(const_option)]
|
||||
|
||||
use kxos_frame::{debug, info, println};
|
||||
use process::Process;
|
||||
@ -25,6 +26,8 @@ mod process;
|
||||
pub mod syscall;
|
||||
mod user_apps;
|
||||
mod util;
|
||||
pub mod vm;
|
||||
pub mod rights;
|
||||
#[macro_use]
|
||||
extern crate kxos_frame_pod_derive;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use typeflags::typeflags;
|
||||
use kxos_typeflags::type_flags;
|
||||
use bitflags::bitflags;
|
||||
|
||||
bitflags! {
|
||||
@ -10,38 +10,46 @@ bitflags! {
|
||||
/// Here, we give some sensible semantics for each access right.
|
||||
pub struct Rights: u32 {
|
||||
/// Allows duplicating a capability.
|
||||
const DUP: u32 = 1 << 0;
|
||||
const DUP = 1 << 0;
|
||||
/// Allows reading data from a data source (files, VM objects, etc.) or
|
||||
/// creating readable memory mappings.
|
||||
const READ: u32 = 1 << 1;
|
||||
const READ = 1 << 1;
|
||||
/// Allows writing data to a data sink (files, VM objects, etc.) or
|
||||
/// creating writable memory mappings.
|
||||
const WRITE: u32 = 1 << 2;
|
||||
const WRITE = 1 << 2;
|
||||
/// Allows creating executable memory mappings.
|
||||
const EXEC: u32 = 1 << 3;
|
||||
const EXEC = 1 << 3;
|
||||
/// Allows sending notifications or signals.
|
||||
const SIGNAL: u32 = 1 << 7;
|
||||
const SIGNAL = 1 << 7;
|
||||
}
|
||||
}
|
||||
|
||||
typeflags! {
|
||||
/// Type-based access rights.
|
||||
///
|
||||
/// Similar to value-based access rights (`Rights`), but represented in
|
||||
/// types.
|
||||
/// Type-based access rights.
|
||||
///
|
||||
/// Similar to value-based access rights (`Rights`), but represented in
|
||||
/// types.
|
||||
///
|
||||
/// pub trait TRights: u32 {
|
||||
/// /// Allows duplicating a capability.
|
||||
/// struct Dup: u32 = Rights::DUP;
|
||||
/// /// Allows reading data from a data source (files, VM objects, etc.) or
|
||||
/// /// creating readable memory mappings.
|
||||
/// struct Read: u32 = Rights::READ;
|
||||
/// /// Allows writing data to a data sink (files, VM objects, etc.) or
|
||||
/// /// creating writable memory mappings.
|
||||
/// struct Write: u32 = Rights::WRITE;
|
||||
/// /// Allows creating executable memory mappings.
|
||||
/// struct Exec: u32 = Rights::EXEC;
|
||||
/// /// Allows sending notifications or signals.
|
||||
/// struct Signal: u32 = Rights::SIGNAL;
|
||||
/// }
|
||||
///
|
||||
type_flags! {
|
||||
pub trait TRights: u32 {
|
||||
/// Allows duplicating a capability.
|
||||
struct Dup: u32 = Rights::DUP;
|
||||
/// Allows reading data from a data source (files, VM objects, etc.) or
|
||||
/// creating readable memory mappings.
|
||||
struct Read: u32 = Rights::READ;
|
||||
/// Allows writing data to a data sink (files, VM objects, etc.) or
|
||||
/// creating writable memory mappings.
|
||||
struct Write: u32 = Rights::WRITE;
|
||||
/// Allows creating executable memory mappings.
|
||||
struct Exec: u32 = Rights::EXEC;
|
||||
/// Allows sending notifications or signals.
|
||||
struct Signal: u32 = Rights::SIGNAL;
|
||||
pub struct Dup = 1 <<0;
|
||||
pub struct Read = 1 <<1;
|
||||
pub struct Write = 1 <<2;
|
||||
pub struct Exec = 1 <<3;
|
||||
pub struct Signal = 1 <<7;
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,5 +59,5 @@ pub type Full = TRights![
|
||||
Read,
|
||||
Write,
|
||||
Exec,
|
||||
Signal,
|
||||
Signal
|
||||
];
|
||||
|
@ -2,7 +2,7 @@
|
||||
//!
|
||||
//! There are two primary VM abstractions:
|
||||
//! * Virtual Memory Address Regions (VMARs) a type of capability that manages
|
||||
/// user address spaces.
|
||||
//! user address spaces.
|
||||
//! * Virtual Memory Objects (VMOs) are are a type of capability that
|
||||
//! represents a set of memory pages.
|
||||
//!
|
||||
|
@ -1,7 +1,17 @@
|
||||
use core::ops::Range;
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use kxos_frame::{vm::VmIo, Error};
|
||||
use kxos_frame::prelude::Result;
|
||||
|
||||
use crate::{rights::Rights, vm::vmo::Vmo};
|
||||
|
||||
use super::{Vmar, VmPerms, options::{VmarChildOptions, VmarMapOptions}, Vmar_};
|
||||
|
||||
impl Vmar<Rights> {
|
||||
/// Creates a root VMAR.
|
||||
pub fn new() -> Result<Self> {
|
||||
let inner = Arc::new(Vmar_::new());
|
||||
let inner = Arc::new(Vmar_::new()?);
|
||||
let rights = Rights::all();
|
||||
let new_self = Self(inner, rights);
|
||||
Ok(new_self)
|
||||
@ -42,9 +52,9 @@ impl Vmar<Rights> {
|
||||
/// Memory permissions may be changed through the `protect` method,
|
||||
/// which ensures that any updated memory permissions do not go beyond
|
||||
/// the access rights of the underlying VMOs.
|
||||
pub fn new_map(&self, vmo: Vmo, perms: VmPerms) -> VmarMapOptions<'_, Rights> {
|
||||
pub fn new_map(&self, vmo: Vmo<Rights>, perms: VmPerms) -> Result<VmarMapOptions<Rights,Rights>> {
|
||||
let dup_self = self.dup()?;
|
||||
VmarMapOptions::new(dup_self, vmo, perms)
|
||||
Ok(VmarMapOptions::new(dup_self, vmo, perms))
|
||||
}
|
||||
|
||||
/// Creates a new child VMAR through a set of VMAR child options.
|
||||
@ -66,9 +76,9 @@ impl Vmar<Rights> {
|
||||
///
|
||||
/// The new VMAR child will be of the same capability class and
|
||||
/// access rights as the parent.
|
||||
pub fn new_child(&self, size: usize) -> VmarChildOptions<'a, Rights> {
|
||||
pub fn new_child(&self, size: usize) -> Result<VmarChildOptions<Rights>> {
|
||||
let dup_self = self.dup()?;
|
||||
VmarChildOptions::new(dup_self, size)
|
||||
Ok(VmarChildOptions::new(dup_self, size))
|
||||
}
|
||||
|
||||
/// Change the permissions of the memory mappings in the specified range.
|
||||
@ -107,24 +117,43 @@ impl Vmar<Rights> {
|
||||
/// As for children VMARs, they must be fully within the range.
|
||||
/// All children VMARs that fall within the range get their `destroy` methods
|
||||
/// called.
|
||||
pub fn destroy(&self, range: &Range<usize>) -> Result<()> {
|
||||
pub fn destroy(&self, range: Range<usize>) -> Result<()> {
|
||||
self.0.destroy(range)
|
||||
}
|
||||
|
||||
/// Duplicates the capability.
|
||||
///
|
||||
/// # Access rights
|
||||
///
|
||||
/// The method requires the Dup right.
|
||||
pub fn dup(&self) -> Result<Self> {
|
||||
self.check_rights(Rights::DUP)?;
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Returns the access rights.
|
||||
pub fn rights(&self) -> Rights {
|
||||
self.1
|
||||
}
|
||||
|
||||
fn check_rights(&self, rights: Rights) -> Result<()> {
|
||||
if self.1.contains(rights) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::AccessDenied)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<R> VmIo for Vmar<Rights> {
|
||||
impl VmIo for Vmar<Rights> {
|
||||
fn read_bytes(&self, offset: usize, buf: &mut [u8]) -> Result<()> {
|
||||
self.check_rights!(Rights::READ)?;
|
||||
self.check_rights(Rights::READ)?;
|
||||
self.0.read(offset, buf)
|
||||
}
|
||||
|
||||
fn write_bytes(&self, offset: usize, buf: &[u8]) -> Result<()> {
|
||||
self.check_rights!(Rights::WRITE)?;
|
||||
self.check_rights(Rights::WRITE)?;
|
||||
self.0.write(offset, buf)
|
||||
}
|
||||
}
|
@ -4,6 +4,16 @@ mod static_cap;
|
||||
mod dyn_cap;
|
||||
mod options;
|
||||
|
||||
use core::ops::Range;
|
||||
use kxos_frame::vm::VmSpace;
|
||||
use kxos_frame::vm::Vaddr;
|
||||
use spin::Mutex;
|
||||
use alloc::sync::Arc;
|
||||
use kxos_frame::prelude::Result;
|
||||
use kxos_frame::Error;
|
||||
use crate::rights::Rights;
|
||||
use bitflags::bitflags;
|
||||
|
||||
/// Virtual Memory Address Regions (VMARs) are a type of capability that manages
|
||||
/// user address spaces.
|
||||
///
|
||||
@ -79,32 +89,32 @@ impl<R> Vmar<R> {
|
||||
///
|
||||
/// The base address of a root VMAR is zero.
|
||||
pub fn base(&self) -> Vaddr {
|
||||
self.base
|
||||
self.0.base
|
||||
}
|
||||
|
||||
fn check_rights(&self, rights: Rights) -> Result<()> {
|
||||
if self.rights.contains(rights) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(EACCESS)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// The memory access permissions of memory mappings.
|
||||
pub struct VmPerms: u32 {
|
||||
/// Readable.
|
||||
const READ: u32 = 1 << 0;
|
||||
const READ = 1 << 0;
|
||||
/// Writable.
|
||||
const WRITE: u32 = 1 << 1;
|
||||
const WRITE = 1 << 1;
|
||||
/// Executable.
|
||||
const EXEC: u32 = 1 << 2;
|
||||
const EXEC = 1 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Rights> for VmPerms {
|
||||
fn from(perms: VmPerms) -> Rights {
|
||||
fn from(rights: Rights) -> VmPerms {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VmPerms> for Rights {
|
||||
fn from(vm_perms: VmPerms) -> Rights {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,12 @@
|
||||
//! Options for allocating child VMARs and creating mappings.
|
||||
|
||||
use kxos_frame::{config::PAGE_SIZE, vm::Vaddr};
|
||||
use kxos_frame::prelude::Result;
|
||||
|
||||
use crate::vm::vmo::Vmo;
|
||||
|
||||
use super::{Vmar, VmPerms};
|
||||
|
||||
/// Options for allocating a child VMAR, which must not overlap with any
|
||||
/// existing mappings or child VMARs.
|
||||
///
|
||||
@ -39,6 +46,7 @@ pub struct VmarChildOptions<R> {
|
||||
parent: Vmar<R>,
|
||||
size: usize,
|
||||
offset: usize,
|
||||
align:usize,
|
||||
}
|
||||
|
||||
impl<R> VmarChildOptions<R> {
|
||||
@ -94,9 +102,9 @@ impl<R> VmarChildOptions<R> {
|
||||
/// Options for creating a new mapping. The mapping is not allowed to overlap
|
||||
/// with any child VMARs. And unless specified otherwise, it is not allowed
|
||||
/// to overlap with any existing mapping, either.
|
||||
pub struct VmarMapOptions<R> {
|
||||
parent: Vmar<R>,
|
||||
vmo: Vmo,
|
||||
pub struct VmarMapOptions<R1,R2> {
|
||||
parent: Vmar<R1>,
|
||||
vmo: Vmo<R2>,
|
||||
perms: VmPerms,
|
||||
vmo_offset: usize,
|
||||
size: usize,
|
||||
@ -105,20 +113,21 @@ pub struct VmarMapOptions<R> {
|
||||
can_overwrite: bool,
|
||||
}
|
||||
|
||||
impl<R> VmarMapOptions<'a, R> {
|
||||
impl<R1,R2> VmarMapOptions<R1,R2> {
|
||||
/// Creates a default set of options with the VMO and the memory access
|
||||
/// permissions.
|
||||
///
|
||||
/// The VMO must have access rights that correspond to the memory
|
||||
/// access permissions. For example, if `perms` contains `VmPerm::Write`,
|
||||
/// then `vmo.rights()` should contain `Rights::WRITE`.
|
||||
pub fn new(parent: Vmar<R>, vmo: Vmo, perms: VmPerms) -> Self {
|
||||
pub fn new(parent: Vmar<R1>, vmo: Vmo<R2>, perms: VmPerms) -> Self {
|
||||
let size = vmo.size();
|
||||
Self {
|
||||
parent,
|
||||
vmo,
|
||||
perms,
|
||||
vmo_offset: 0,
|
||||
size: vmo.size(),
|
||||
size,
|
||||
offset: None,
|
||||
align: PAGE_SIZE,
|
||||
can_overwrite: false,
|
||||
@ -176,7 +185,7 @@ impl<R> VmarMapOptions<'a, R> {
|
||||
///
|
||||
/// If not set, the system will choose an offset automatically.
|
||||
pub fn offset(mut self, offset: usize) -> Self {
|
||||
self.offset = offset;
|
||||
self.offset = Some(offset);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,14 @@
|
||||
use core::ops::Range;
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use kxos_frame::{vm::VmIo, Error};
|
||||
use kxos_rights_proc::require;
|
||||
use kxos_frame::prelude::Result;
|
||||
|
||||
use crate::{rights::*, vm::vmo::Vmo};
|
||||
|
||||
use super::{Vmar, Vmar_, VmPerms, options::{VmarMapOptions, VmarChildOptions}};
|
||||
|
||||
impl<R: TRights> Vmar<R> {
|
||||
/// Creates a root VMAR.
|
||||
///
|
||||
@ -5,7 +16,7 @@ impl<R: TRights> Vmar<R> {
|
||||
///
|
||||
/// A root VMAR is initially given full access rights.
|
||||
pub fn new() -> Result<Self> {
|
||||
let inner = Arc::new(Vmar_::new());
|
||||
let inner = Arc::new(Vmar_::new()?);
|
||||
let rights = R::new();
|
||||
let new_self = Self(inner, rights);
|
||||
Ok(new_self)
|
||||
@ -46,9 +57,10 @@ impl<R: TRights> Vmar<R> {
|
||||
/// Memory permissions may be changed through the `protect` method,
|
||||
/// which ensures that any updated memory permissions do not go beyond
|
||||
/// the access rights of the underlying VMOs.
|
||||
pub fn new_map(&self, vmo: Vmo, perms: VmPerms) -> VmarMapOptions<'_, Rights> {
|
||||
let dup_self = self.dup();
|
||||
VmarMapOptions::new(dup_self, vmo_ref)
|
||||
#[require(R > Dup)]
|
||||
pub fn new_map(&self, vmo: Vmo<Rights>, perms: VmPerms) -> Result<VmarMapOptions<R,Rights>> {
|
||||
let dup_self = self.dup()?;
|
||||
Ok(VmarMapOptions::new(dup_self, vmo,perms))
|
||||
}
|
||||
|
||||
/// Creates a new child VMAR through a set of VMAR child options.
|
||||
@ -71,9 +83,9 @@ impl<R: TRights> Vmar<R> {
|
||||
/// The new VMAR child will be of the same capability class and
|
||||
/// access rights as the parent.
|
||||
#[require(R > Dup)]
|
||||
pub fn new_child(&self, size: usize) -> VmarChildOptions<'a, R> {
|
||||
let dup_self = self.dup();
|
||||
VmarChildOptions::new(dup_self, size)
|
||||
pub fn new_child(&self, size: usize) -> Result<VmarChildOptions<R>> {
|
||||
let dup_self = self.dup()?;
|
||||
Ok(VmarChildOptions::new(dup_self, size))
|
||||
}
|
||||
|
||||
/// Change the permissions of the memory mappings in the specified range.
|
||||
@ -112,24 +124,49 @@ impl<R: TRights> Vmar<R> {
|
||||
/// As for children VMARs, they must be fully within the range.
|
||||
/// All children VMARs that fall within the range get their `destroy` methods
|
||||
/// called.
|
||||
pub fn destroy(&self, range: &Range<usize>) -> Result<()> {
|
||||
pub fn destroy(&self, range: Range<usize>) -> Result<()> {
|
||||
self.0.destroy(range)
|
||||
}
|
||||
|
||||
/// Duplicate the capability.
|
||||
///
|
||||
/// # Access rights
|
||||
///
|
||||
/// The method requires the Dup right.
|
||||
#[require(R > Dup)]
|
||||
pub fn dup(&self) -> Result<Self> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Strict the access rights.
|
||||
#[require(R > R1)]
|
||||
pub fn restrict<R1>(mut self) -> Vmo<R1> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Returns the access rights.
|
||||
pub const fn rights(&self) -> Rights {
|
||||
R::BITS
|
||||
Rights::from_bits(R::BITS).unwrap()
|
||||
}
|
||||
|
||||
fn check_rights(&self, rights: Rights) -> Result<()> {
|
||||
if self.rights().contains(rights) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::AccessDenied)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<R> VmIo for Vmar<Rights> {
|
||||
impl<R:TRights> VmIo for Vmar<R> {
|
||||
fn read_bytes(&self, offset: usize, buf: &mut [u8]) -> Result<()> {
|
||||
self.check_rights!(Rights::READ)?;
|
||||
// self.check_rights!(Rights::READ)?;
|
||||
self.0.read(offset, buf)
|
||||
}
|
||||
|
||||
fn write_bytes(&self, offset: usize, buf: &[u8]) -> Result<()> {
|
||||
self.check_rights!(Rights::WRITE)?;
|
||||
// self.check_rights!(Rights::WRITE)?;
|
||||
self.0.write(offset, buf)
|
||||
}
|
||||
}
|
@ -1,3 +1,12 @@
|
||||
use core::ops::Range;
|
||||
|
||||
use kxos_frame::{vm::VmIo, Error};
|
||||
use kxos_frame::prelude::Result;
|
||||
|
||||
use crate::rights::{Rights, TRights};
|
||||
|
||||
use super::{VmoChildOptions, options::{VmoSliceChild, VmoCowChild}, Vmo};
|
||||
|
||||
impl Vmo<Rights> {
|
||||
/// Creates a new slice VMO through a set of VMO child options.
|
||||
///
|
||||
@ -18,9 +27,9 @@ impl Vmo<Rights> {
|
||||
///
|
||||
/// The new VMO child will be of the same capability flavor as the parent;
|
||||
/// so are the access rights.
|
||||
pub fn new_slice_child(&self, range: Range<usize>) -> VmoChildOptions<'_, Rights, VmoSliceChild> {
|
||||
pub fn new_slice_child(&self, range: Range<usize>) -> Result<VmoChildOptions<Rights, VmoSliceChild>> {
|
||||
let dup_self = self.dup()?;
|
||||
VmoChildOptions::new_slice(dup_self, range)
|
||||
Ok(VmoChildOptions::new_slice_rights(dup_self, range))
|
||||
}
|
||||
|
||||
/// Creates a new COW VMO through a set of VMO child options.
|
||||
@ -43,9 +52,9 @@ impl Vmo<Rights> {
|
||||
/// The new VMO child will be of the same capability flavor as the parent.
|
||||
/// The child will be given the access rights of the parent
|
||||
/// plus the Write right.
|
||||
pub fn new_cow_child(&self, range: Range<usize>) -> VmoChildOptions<'_, Rights, VmoCowChild> {
|
||||
pub fn new_cow_child(&self, range: Range<usize>) -> Result<VmoChildOptions<Rights, VmoCowChild>> {
|
||||
let dup_self = self.dup()?;
|
||||
VmoChildOptions::new_cow(dup_self, range)
|
||||
Ok(VmoChildOptions::new_cow(dup_self, range))
|
||||
}
|
||||
|
||||
/// Commits the pages specified in the range (in bytes).
|
||||
@ -117,7 +126,7 @@ impl Vmo<Rights> {
|
||||
|
||||
/// Converts to a static capability.
|
||||
pub fn to_static<R1: TRights>(self) -> Result<Vmo<R1>> {
|
||||
self.check_rights(R1::BITS)?;
|
||||
self.check_rights(Rights::from_bits(R1::BITS).ok_or(Error::InvalidArgs)?)?;
|
||||
todo!()
|
||||
}
|
||||
|
||||
@ -125,16 +134,24 @@ impl Vmo<Rights> {
|
||||
pub fn rights(&self) -> Rights {
|
||||
self.1
|
||||
}
|
||||
|
||||
pub fn check_rights(&self, rights: Rights) -> Result<()> {
|
||||
if self.rights().contains(rights) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::AccessDenied)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VmIo for Vmo<Rights> {
|
||||
fn read_bytes(&self, offset: usize, buf: &mut [u8]) -> Result<()> {
|
||||
self.check_rights(Rights::READ)?;
|
||||
self.0.read(offset, buf)
|
||||
self.0.read_bytes(offset, buf)
|
||||
}
|
||||
|
||||
fn write_bytes(&self, offset: usize, buf: &[u8]) -> Result<()> {
|
||||
self.check_rights(Rights::WRITE)?;
|
||||
self.0.write(offset, buf)
|
||||
self.0.write_bytes(offset, buf)
|
||||
}
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
//! Virtual Memory Objects (VMOs).
|
||||
|
||||
use kx_frame::vm::VmIo;
|
||||
use core::ops::Range;
|
||||
|
||||
use crate::rights::{Rights, TRights};
|
||||
use kxos_frame::{prelude::Result, vm::Paddr, Error};
|
||||
use crate::rights::Rights;
|
||||
use alloc::sync::Arc;
|
||||
use bitflags::bitflags;
|
||||
|
||||
mod static_cap;
|
||||
mod dyn_cap;
|
||||
@ -11,6 +14,9 @@ mod pager;
|
||||
|
||||
pub use options::{VmoOptions, VmoChildOptions};
|
||||
pub use pager::Pager;
|
||||
use spin::Mutex;
|
||||
|
||||
|
||||
|
||||
/// Virtual Memory Objects (VMOs) are a type of capability that represents a
|
||||
/// range of memory pages.
|
||||
@ -73,16 +79,16 @@ bitflags! {
|
||||
/// VMO flags.
|
||||
pub struct VmoFlags: u32 {
|
||||
/// Set this flag if a VMO is resizable.
|
||||
const RESIZABLE: u32 = 1 << 0;
|
||||
const RESIZABLE = 1 << 0;
|
||||
/// Set this flags if a VMO is backed by physically contiguous memory
|
||||
/// pages.
|
||||
///
|
||||
/// To ensure the memory pages to be contiguous, these pages
|
||||
/// are allocated upon the creation of the VMO, rather than on demands.
|
||||
const CONTIGUOUS: u32 = 1 << 1;
|
||||
const CONTIGUOUS = 1 << 1;
|
||||
/// Set this flag if a VMO is backed by memory pages that supports
|
||||
/// Direct Memory Access (DMA) by devices.
|
||||
const DMA: u32 = 1 << 2;
|
||||
const DMA = 1 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,7 +132,7 @@ impl Vmo_ {
|
||||
}
|
||||
|
||||
pub fn size(&self) -> usize {
|
||||
self.0.size()
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn resize(&self, new_size: usize) -> Result<()> {
|
||||
@ -160,11 +166,4 @@ impl<R> Vmo<R> {
|
||||
self.0.flags()
|
||||
}
|
||||
|
||||
fn check_rights(&self, rights: Rights) -> Result<()> {
|
||||
if self.rights().contains(rights) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::AccessDenied)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,17 @@
|
||||
//! Options for allocating root and child VMOs.
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use core::ops::Range;
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use kxos_frame::vm::Paddr;
|
||||
use kxos_frame::prelude::Result;
|
||||
use kxos_rights_proc::require;
|
||||
|
||||
use crate::rights::{Dup,TRights,Rights};
|
||||
|
||||
use super::{Vmo, VmoFlags, Pager};
|
||||
|
||||
/// Options for allocating a root VMO.
|
||||
///
|
||||
/// # Examples
|
||||
@ -38,7 +50,8 @@ pub struct VmoOptions<R = Rights> {
|
||||
size: usize,
|
||||
paddr: Option<Paddr>,
|
||||
flags: VmoFlags,
|
||||
supplier: Option<Arc<dyn FrameSupplier>>,
|
||||
rights: R,
|
||||
// supplier: Option<Arc<dyn FrameSupplier>>,
|
||||
}
|
||||
|
||||
impl<R> VmoOptions<R> {
|
||||
@ -81,7 +94,7 @@ impl VmoOptions<Rights> {
|
||||
/// # Access rights
|
||||
///
|
||||
/// The VMO is initially assigned full access rights.
|
||||
pub fn alloc(mut self) -> Result<Vmo<R>> {
|
||||
pub fn alloc(mut self) -> Result<Vmo<Rights>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@ -185,10 +198,10 @@ pub struct VmoChildOptions<R, C> {
|
||||
range: Range<usize>,
|
||||
flags: VmoFlags,
|
||||
// Specifies whether the child is a slice or a COW
|
||||
child_marker: PhantomData<C>,
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<R> VmoChildOptions<R, VmoSliceChild> {
|
||||
impl<R:TRights> VmoChildOptions<R, VmoSliceChild> {
|
||||
/// Creates a default set of options for creating a slice VMO child.
|
||||
///
|
||||
/// A slice child of a VMO, which has direct access to a range of memory
|
||||
@ -199,9 +212,30 @@ impl<R> VmoChildOptions<R, VmoSliceChild> {
|
||||
#[require(R > Dup)]
|
||||
pub fn new_slice(parent: Vmo<R>, range: Range<usize>) -> Self {
|
||||
Self {
|
||||
flags: parent.flags() & Self::PARENT_FLAGS_MASK,
|
||||
parent,
|
||||
range,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VmoChildOptions<Rights, VmoSliceChild> {
|
||||
/// Creates a default set of options for creating a slice VMO child.
|
||||
///
|
||||
/// User should ensure parent have dup rights, otherwise this function will panic
|
||||
///
|
||||
/// A slice child of a VMO, which has direct access to a range of memory
|
||||
/// pages in the parent VMO. In other words, any updates of the parent will
|
||||
/// reflect on the child, and vice versa.
|
||||
///
|
||||
/// The range of a child must be within that of the parent.
|
||||
pub fn new_slice_rights(parent: Vmo<Rights>, range: Range<usize>) -> Self {
|
||||
parent.check_rights(Rights::DUP).expect("function new_slice_rights should called with rights Dup");
|
||||
Self {
|
||||
flags: parent.flags() & Self::PARENT_FLAGS_MASK,
|
||||
parent,
|
||||
range,
|
||||
flags: parent.flags & Self::PARENT_FLAGS_MASK,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -219,9 +253,9 @@ impl<R> VmoChildOptions<R, VmoCowChild> {
|
||||
/// Any pages that are beyond the parent's range are initially all zeros.
|
||||
pub fn new_cow(parent: Vmo<R>, range: Range<usize>) -> Self {
|
||||
Self {
|
||||
flags: parent.flags() & Self::PARENT_FLAGS_MASK,
|
||||
parent,
|
||||
range,
|
||||
flags: parent.flags & Self::PARENT_FLAGS_MASK,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -229,10 +263,9 @@ impl<R> VmoChildOptions<R, VmoCowChild> {
|
||||
|
||||
impl<R, C> VmoChildOptions<R, C> {
|
||||
/// Flags that a VMO child inherits from its parent.
|
||||
pub const PARENT_FLAGS_MASK: VmoFlags = VmoFlags::CONTIGUOUS.bits |
|
||||
VmoFlags::DMA.bits;
|
||||
pub const PARENT_FLAGS_MASK: VmoFlags = VmoFlags::from_bits(VmoFlags::CONTIGUOUS.bits | VmoFlags::DMA.bits).unwrap();
|
||||
/// Flags that a VMO child may differ from its parent.
|
||||
pub const CHILD_FLAGS_MASK: VmoFlags = VmoFlags::RESIZABLE.bits;
|
||||
pub const CHILD_FLAGS_MASK: VmoFlags = VmoFlags::RESIZABLE;
|
||||
|
||||
/// Sets the VMO flags.
|
||||
///
|
||||
@ -248,7 +281,7 @@ impl<R, C> VmoChildOptions<R, C> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, C> VmoChildOptions<'a, Rights, C> {
|
||||
impl<C> VmoChildOptions<Rights, C> {
|
||||
/// Allocates the child VMO.
|
||||
///
|
||||
/// # Access rights
|
||||
@ -259,7 +292,7 @@ impl<'a, C> VmoChildOptions<'a, Rights, C> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, R: TRights> VmoChildOptions<'a, R, VmoSliceChild> {
|
||||
impl<R: TRights> VmoChildOptions<R, VmoSliceChild> {
|
||||
/// Allocates the child VMO.
|
||||
///
|
||||
/// # Access rights
|
||||
@ -270,23 +303,35 @@ impl<'a, R: TRights> VmoChildOptions<'a, R, VmoSliceChild> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, R: TRights> VmoChildOptions<'a, R, VmoCowChild> {
|
||||
impl<R: TRights> VmoChildOptions<R, VmoCowChild> {
|
||||
/// Allocates the child VMO.
|
||||
///
|
||||
/// # Access rights
|
||||
///
|
||||
/// The child VMO is initially assigned all the parent's access rights
|
||||
/// plus the Write right.
|
||||
pub fn alloc<R1>(mut self) -> Result<Vmo<R1>>
|
||||
pub fn alloc<TRights>(mut self) -> Result<Vmo<TRights>>
|
||||
where
|
||||
// TODO: R1 must contain the Write right. To do so at the type level,
|
||||
// we need to implement a type-level operator
|
||||
// (say, `TRightsExtend(L, F)`)
|
||||
// that may extend a list (`L`) of type-level flags with an extra flag `F`.
|
||||
R1: R // TRightsExtend<R, Write>
|
||||
// TRightsExtend<R, Write>
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
// original:
|
||||
// pub fn alloc<R1>(mut self) -> Result<Vmo<R1>>
|
||||
// where
|
||||
// // TODO: R1 must contain the Write right. To do so at the type level,
|
||||
// // we need to implement a type-level operator
|
||||
// // (say, `TRightsExtend(L, F)`)
|
||||
// // that may extend a list (`L`) of type-level flags with an extra flag `F`.
|
||||
// R1: R // TRightsExtend<R, Write>
|
||||
// {
|
||||
// todo!()
|
||||
// }
|
||||
}
|
||||
|
||||
/// A type to specify the "type" of a child, which is either a slice or a COW.
|
||||
@ -295,9 +340,9 @@ pub trait VmoChildType {}
|
||||
/// A type to mark a child is slice.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct VmoSliceChild;
|
||||
impl VmoChildType for VmoSliceChild {};
|
||||
impl VmoChildType for VmoSliceChild {}
|
||||
|
||||
/// A type to mark a child is COW.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct VmoCowChild;
|
||||
impl VmoChildType for VmoCowChild {};
|
||||
impl VmoChildType for VmoCowChild {}
|
||||
|
@ -1,3 +1,6 @@
|
||||
use kxos_frame::vm::VmFrame;
|
||||
use kxos_frame::prelude::Result;
|
||||
|
||||
/// Pagers provide frame to a VMO.
|
||||
///
|
||||
/// A `Pager` object can be attached to a VMO. Whenever the
|
||||
|
@ -1,3 +1,13 @@
|
||||
use core::ops::Range;
|
||||
|
||||
use kxos_frame::{vm::VmIo, Error};
|
||||
use kxos_frame::prelude::Result;
|
||||
use kxos_rights_proc::require;
|
||||
|
||||
use crate::rights::*;
|
||||
|
||||
use super::{Vmo, VmoChildOptions, options::{VmoSliceChild, VmoCowChild}};
|
||||
|
||||
impl<R: TRights> Vmo<R> {
|
||||
/// Creates a new slice VMO through a set of VMO child options.
|
||||
///
|
||||
@ -19,9 +29,9 @@ impl<R: TRights> Vmo<R> {
|
||||
/// The new VMO child will be of the same capability flavor as the parent;
|
||||
/// so are the access rights.
|
||||
#[require(R > Dup)]
|
||||
pub fn new_slice_child(&self, range: Range<usize>) -> VmoChildOptions<'_, R, VmoSliceChild> {
|
||||
let dup_self = self.dup();
|
||||
VmoChildOptions::new_slice(dup_self, range)
|
||||
pub fn new_slice_child(&self, range: Range<usize>) -> Result<VmoChildOptions<R, VmoSliceChild>> {
|
||||
let dup_self = self.dup()?;
|
||||
Ok(VmoChildOptions::new_slice(dup_self, range))
|
||||
}
|
||||
|
||||
/// Creates a new COW VMO through a set of VMO child options.
|
||||
@ -45,9 +55,9 @@ impl<R: TRights> Vmo<R> {
|
||||
/// The child will be given the access rights of the parent
|
||||
/// plus the Write right.
|
||||
#[require(R > Dup)]
|
||||
pub fn new_cow_child(&self, range: Range<usize>) -> VmoChildOptions<'_, R, VmoCowChild> {
|
||||
let dup_self = self.dup();
|
||||
VmoChildOptions::new_cow(dup_self, range)
|
||||
pub fn new_cow_child(&self, range: Range<usize>) -> Result<VmoChildOptions<R, VmoCowChild>> {
|
||||
let dup_self = self.dup()?;
|
||||
Ok(VmoChildOptions::new_cow(dup_self, range))
|
||||
}
|
||||
|
||||
/// Commit the pages specified in the range (in bytes).
|
||||
@ -102,11 +112,6 @@ impl<R: TRights> Vmo<R> {
|
||||
self.0.clear(range)
|
||||
}
|
||||
|
||||
/// Returns the size of the VMO in bytes.
|
||||
pub fn size(&self) -> usize {
|
||||
self.0.size()
|
||||
}
|
||||
|
||||
/// Duplicate the capability.
|
||||
///
|
||||
/// # Access rights
|
||||
@ -124,13 +129,21 @@ impl<R: TRights> Vmo<R> {
|
||||
}
|
||||
|
||||
/// Converts to a dynamic capability.
|
||||
pub fn to_dyn(self) -> Vmo {
|
||||
pub fn to_dyn(self) -> Vmo<Rights> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Returns the access rights.
|
||||
pub const fn rights(&self) -> Rights {
|
||||
R::BITS
|
||||
Rights::from_bits(R::BITS).unwrap()
|
||||
}
|
||||
|
||||
fn check_rights(&self, rights: Rights) -> Result<()> {
|
||||
if self.rights().contains(rights) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::AccessDenied)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
//! Type level bools
|
||||
|
||||
pub use std::ops::BitAnd as And;
|
||||
pub use std::ops::BitOr as Or;
|
||||
pub use std::ops::Not;
|
||||
pub use core::ops::BitAnd as And;
|
||||
pub use core::ops::BitOr as Or;
|
||||
pub use core::ops::Not;
|
||||
use core::unimplemented;
|
||||
|
||||
pub trait Bool {}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
//! This crate defines common type level operations, like SameAsOp, and Bool type operations.
|
||||
//! Besides, this crate defines operations to deal with type sets, like SetContain and SetInclude.
|
||||
//! When use kxos-typeflags or kxos-rights-poc, this crate should also be added as a dependency.
|
||||
|
||||
#![no_std]
|
||||
pub mod assert;
|
||||
pub mod bool;
|
||||
pub mod if_;
|
||||
|
@ -1,13 +1,13 @@
|
||||
//! Common types and traits to deal with type-level sets
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use crate::{
|
||||
if_::{If, IfOp},
|
||||
And, AndOp, False, OrOp, SameAs, SameAsOp, True,
|
||||
};
|
||||
|
||||
use std::ops::BitOr as Or;
|
||||
use core::ops::BitOr as Or;
|
||||
|
||||
/// A marker trait for type-level sets.
|
||||
pub trait Set {}
|
||||
|
@ -65,11 +65,12 @@ impl TypeFlagDef {
|
||||
let ident = self.ident.clone();
|
||||
let type_ = self.type_.clone();
|
||||
quote!(
|
||||
#vis trait #ident {
|
||||
#vis trait #ident : Sync + Send{
|
||||
const BITS: #type_;
|
||||
|
||||
fn new() -> Self;
|
||||
}
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user