format files

This commit is contained in:
Yuke Peng
2022-11-10 18:14:42 -08:00
parent 7be7775f97
commit 40cbd93ae8
23 changed files with 450 additions and 426 deletions

View File

@ -1,6 +1,9 @@
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::quote; use quote::quote;
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Fields, DataEnum, punctuated::Punctuated, token::Comma, Field}; use syn::{
parse_macro_input, punctuated::Punctuated, token::Comma, Data, DataEnum, DataStruct,
DeriveInput, Field, Fields,
};
#[proc_macro_derive(Pod)] #[proc_macro_derive(Pod)]
pub fn derive_pod(input_token: proc_macro::TokenStream) -> proc_macro::TokenStream { pub fn derive_pod(input_token: proc_macro::TokenStream) -> proc_macro::TokenStream {
@ -16,9 +19,9 @@ fn expand_derive_pod(input: DeriveInput) -> TokenStream {
Fields::Unnamed(fields_unnamed) => fields_unnamed.unnamed, Fields::Unnamed(fields_unnamed) => fields_unnamed.unnamed,
Fields::Unit => Punctuated::new(), Fields::Unit => Punctuated::new(),
}, },
Data::Enum(DataEnum{variants,..})=>{ Data::Enum(DataEnum { variants, .. }) => {
let mut fields : Punctuated<Field,Comma> = Punctuated::new(); let mut fields: Punctuated<Field, Comma> = Punctuated::new();
for var in variants{ for var in variants {
fields.extend(match var.fields { fields.extend(match var.fields {
Fields::Named(fields_named) => fields_named.named, Fields::Named(fields_named) => fields_named.named,
Fields::Unnamed(fields_unnamed) => fields_unnamed.unnamed, Fields::Unnamed(fields_unnamed) => fields_unnamed.unnamed,

View File

@ -3,12 +3,12 @@
pub mod framebuffer; pub mod framebuffer;
mod io_port; mod io_port;
pub mod pci; pub mod pci;
pub mod serial;
mod pic; mod pic;
pub mod serial;
pub use pic::{TimerCallback, TIMER_FREQ};
pub(crate) use pic::{add_timeout_list,TICK};
pub use self::io_port::IoPort; pub use self::io_port::IoPort;
pub(crate) use pic::{add_timeout_list, TICK};
pub use pic::{TimerCallback, TIMER_FREQ};
pub(crate) fn init(framebuffer: &'static mut bootloader::boot_info::FrameBuffer) { pub(crate) fn init(framebuffer: &'static mut bootloader::boot_info::FrameBuffer) {
framebuffer::init(framebuffer); framebuffer::init(framebuffer);

View File

@ -78,7 +78,7 @@ fn timer_callback(trap_frame: &TrapFrame) {
TICK += 1; TICK += 1;
} }
let timeout_list = TIMEOUT_LIST.get(); let timeout_list = TIMEOUT_LIST.get();
let mut callbacks : Vec<Arc<TimerCallback>>= Vec::new(); let mut callbacks: Vec<Arc<TimerCallback>> = Vec::new();
while let Some(t) = timeout_list.peek() { while let Some(t) = timeout_list.peek() {
if t.expire_ms <= current_ms { if t.expire_ms <= current_ms {
callbacks.push(timeout_list.pop().unwrap()); callbacks.push(timeout_list.pop().unwrap());
@ -86,8 +86,8 @@ fn timer_callback(trap_frame: &TrapFrame) {
break; break;
} }
} }
for callback in callbacks{ for callback in callbacks {
if callback.is_enable(){ if callback.is_enable() {
callback.callback.call((&callback,)); callback.callback.call((&callback,));
} }
} }
@ -95,7 +95,7 @@ fn timer_callback(trap_frame: &TrapFrame) {
} }
lazy_static! { lazy_static! {
static ref TIMEOUT_LIST: Cell<BinaryHeap<Arc<TimerCallback>>> = Cell::new(BinaryHeap::new()) ; static ref TIMEOUT_LIST: Cell<BinaryHeap<Arc<TimerCallback>>> = Cell::new(BinaryHeap::new());
} }
pub struct TimerCallback { pub struct TimerCallback {
@ -115,7 +115,7 @@ impl TimerCallback {
expire_ms: timeout_ms, expire_ms: timeout_ms,
data, data,
callback, callback,
enable:Cell::new(true), enable: Cell::new(true),
} }
} }
@ -124,19 +124,18 @@ impl TimerCallback {
} }
/// disable this timeout /// disable this timeout
pub fn disable(&self){ pub fn disable(&self) {
*self.enable.get() = false; *self.enable.get() = false;
} }
/// enable this timeout /// enable this timeout
pub fn enable(&self){ pub fn enable(&self) {
*self.enable.get() = true; *self.enable.get() = true;
} }
pub fn is_enable(&self) -> bool{ pub fn is_enable(&self) -> bool {
*self.enable *self.enable
} }
} }
impl PartialEq for TimerCallback { impl PartialEq for TimerCallback {
@ -166,15 +165,10 @@ impl Ord for TimerCallback {
pub fn add_timeout_list<F, T>(timeout: u64, data: T, callback: F) -> Arc<TimerCallback> pub fn add_timeout_list<F, T>(timeout: u64, data: T, callback: F) -> Arc<TimerCallback>
where where
F: Fn(&TimerCallback) + Send + Sync + 'static, F: Fn(&TimerCallback) + Send + Sync + 'static,
T: Any + Send + Sync, T: Any + Send + Sync,
{ {
unsafe { unsafe {
let timer_callback = TimerCallback::new( let timer_callback = TimerCallback::new(TICK + timeout, Arc::new(data), Box::new(callback));
TICK + timeout,
Arc::new(data),
Box::new(callback),
);
let arc = Arc::new(timer_callback); let arc = Arc::new(timer_callback);
TIMEOUT_LIST.get().push(arc.clone()); TIMEOUT_LIST.get().push(arc.clone());
arc arc

View File

@ -1,8 +1,11 @@
//! Timer. //! Timer.
use crate::{prelude::*, device::{TimerCallback, TICK,TIMER_FREQ}}; use crate::{
use spin::Mutex; device::{TimerCallback, TICK, TIMER_FREQ},
prelude::*,
};
use core::time::Duration; use core::time::Duration;
use spin::Mutex;
/// A timer invokes a callback function after a specified span of time elapsed. /// A timer invokes a callback function after a specified span of time elapsed.
/// ///
@ -13,57 +16,67 @@ use core::time::Duration;
/// Timers are one-shot. If the time is out, one has to set the timer again /// Timers are one-shot. If the time is out, one has to set the timer again
/// in order to trigger the callback again. /// in order to trigger the callback again.
pub struct Timer { pub struct Timer {
function: Arc<dyn Fn(Arc<Self>)+Send+Sync>, function: Arc<dyn Fn(Arc<Self>) + Send + Sync>,
inner: Mutex<TimerInner>, inner: Mutex<TimerInner>,
} }
#[derive(Default)] #[derive(Default)]
struct TimerInner{ struct TimerInner {
start_tick: u64, start_tick: u64,
timeout_tick:u64, timeout_tick: u64,
timer_callback:Option<Arc<TimerCallback>>, timer_callback: Option<Arc<TimerCallback>>,
} }
fn timer_callback(callback:&TimerCallback){ fn timer_callback(callback: &TimerCallback) {
let data = callback.data(); let data = callback.data();
if data.is::<Arc<Timer>>(){ if data.is::<Arc<Timer>>() {
let timer = data.downcast_ref::<Arc<Timer>>().unwrap(); let timer = data.downcast_ref::<Arc<Timer>>().unwrap();
timer.function.call((timer.clone(),)); timer.function.call((timer.clone(),));
}else{ } else {
panic!("the timer callback is not Timer structure"); panic!("the timer callback is not Timer structure");
} }
} }
const NANOS_DIVIDE : u64 = 1_000_000_000/TIMER_FREQ; const NANOS_DIVIDE: u64 = 1_000_000_000 / TIMER_FREQ;
impl Timer { impl Timer {
/// Creates a new instance, given a callback function. /// Creates a new instance, given a callback function.
pub fn new<F>(f: F) -> Result<Arc<Self>> pub fn new<F>(f: F) -> Result<Arc<Self>>
where where
F: Fn(Arc<Timer>) +Send+Sync+'static, F: Fn(Arc<Timer>) + Send + Sync + 'static,
{ {
Ok(Arc::new(Self { function: Arc::new(f),inner:Mutex::new(TimerInner::default()) })) Ok(Arc::new(Self {
function: Arc::new(f),
inner: Mutex::new(TimerInner::default()),
}))
} }
/// Set a timeout value. /// Set a timeout value.
/// ///
/// If a timeout value is already set, the timeout value will be refreshed. /// If a timeout value is already set, the timeout value will be refreshed.
/// ///
pub fn set(self : Arc<Self>, timeout: Duration) { pub fn set(self: Arc<Self>, timeout: Duration) {
let mut lock = self.inner.lock(); let mut lock = self.inner.lock();
match &lock.timer_callback{ match &lock.timer_callback {
Some(callback) => { Some(callback) => {
callback.disable(); callback.disable();
}, }
None => {}, None => {}
} }
let tick_count = timeout.as_secs()*TIMER_FREQ let tick_count = timeout.as_secs() * TIMER_FREQ
+ if timeout.subsec_nanos() !=0{(timeout.subsec_nanos() as u64 - 1)/NANOS_DIVIDE + 1} else {0}; + if timeout.subsec_nanos() != 0 {
unsafe{ (timeout.subsec_nanos() as u64 - 1) / NANOS_DIVIDE + 1
} else {
0
};
unsafe {
lock.start_tick = TICK; lock.start_tick = TICK;
lock.timeout_tick = TICK+tick_count; lock.timeout_tick = TICK + tick_count;
} }
lock.timer_callback = Some(crate::device::add_timeout_list(tick_count, self.clone(), timer_callback)); lock.timer_callback = Some(crate::device::add_timeout_list(
tick_count,
self.clone(),
timer_callback,
));
} }
/// Returns the remaining timeout value. /// Returns the remaining timeout value.
@ -72,22 +85,22 @@ impl Timer {
pub fn remain(&self) -> Duration { pub fn remain(&self) -> Duration {
let lock = self.inner.lock(); let lock = self.inner.lock();
let tick_remain; let tick_remain;
unsafe{ unsafe {
tick_remain = lock.timeout_tick as i64-TICK as i64; tick_remain = lock.timeout_tick as i64 - TICK as i64;
} }
if tick_remain<=0{ if tick_remain <= 0 {
Duration::new(0,0) Duration::new(0, 0)
}else{ } else {
let second_count = tick_remain as u64/TIMER_FREQ; let second_count = tick_remain as u64 / TIMER_FREQ;
let remain_count = tick_remain as u64 % TIMER_FREQ; let remain_count = tick_remain as u64 % TIMER_FREQ;
Duration::new(second_count,(remain_count * NANOS_DIVIDE) as u32) Duration::new(second_count, (remain_count * NANOS_DIVIDE) as u32)
} }
} }
/// Clear the timeout value. /// Clear the timeout value.
pub fn clear(&self) { pub fn clear(&self) {
let mut lock = self.inner.lock(); let mut lock = self.inner.lock();
if let Some(callback) = &lock.timer_callback{ if let Some(callback) = &lock.timer_callback {
callback.disable(); callback.disable();
} }
lock.timeout_tick = 0; lock.timeout_tick = 0;

View File

@ -41,7 +41,7 @@ pub(crate) extern "C" fn trap_handler(f: &mut TrapFrame) {
} }
} }
} else { } else {
if is_cpu_fault(f){ if is_cpu_fault(f) {
panic!("cannot handle kernel cpu fault now"); panic!("cannot handle kernel cpu fault now");
} }
let irq_line = IRQ_LIST.get(f.id as usize).unwrap(); let irq_line = IRQ_LIST.get(f.id as usize).unwrap();

View File

@ -22,7 +22,7 @@ pub struct MSIXEntry {
pub irq_handle: IrqAllocateHandle, pub irq_handle: IrqAllocateHandle,
} }
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq,Pod)] #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Pod)]
#[repr(C)] #[repr(C)]
pub struct MSIXTableEntry { pub struct MSIXTableEntry {
pub msg_addr: u32, pub msg_addr: u32,

View File

@ -4,9 +4,9 @@ use crate::process::Process;
use alloc::sync::Arc; use alloc::sync::Arc;
use alloc::vec::Vec; use alloc::vec::Vec;
use kxos_frame::info; use kxos_frame::info;
use kxos_frame_pod_derive::Pod;
use kxos_pci::PCIDevice; use kxos_pci::PCIDevice;
use kxos_virtio::PCIVirtioDevice; use kxos_virtio::PCIVirtioDevice;
use kxos_frame_pod_derive::Pod;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use spin::mutex::Mutex; use spin::mutex::Mutex;
@ -19,7 +19,7 @@ pub struct VirtioBlockDevice {
} }
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone,Pod)] #[derive(Debug, Copy, Clone, Pod)]
pub struct BlkReq { pub struct BlkReq {
pub type_: ReqType, pub type_: ReqType,
pub reserved: u32, pub reserved: u32,
@ -28,13 +28,13 @@ pub struct BlkReq {
/// Response of a VirtIOBlk request. /// Response of a VirtIOBlk request.
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone,Pod)] #[derive(Debug, Copy, Clone, Pod)]
pub struct BlkResp { pub struct BlkResp {
pub status: RespStatus, pub status: RespStatus,
} }
#[repr(u32)] #[repr(u32)]
#[derive(Debug, Copy, Clone,Pod)] #[derive(Debug, Copy, Clone, Pod)]
pub enum ReqType { pub enum ReqType {
In = 0, In = 0,
Out = 1, Out = 1,
@ -44,7 +44,7 @@ pub enum ReqType {
} }
#[repr(u8)] #[repr(u8)]
#[derive(Debug, Eq, PartialEq, Copy, Clone,Pod)] #[derive(Debug, Eq, PartialEq, Copy, Clone, Pod)]
pub enum RespStatus { pub enum RespStatus {
/// Ok. /// Ok.
Ok = 0, Ok = 0,

View File

@ -23,11 +23,11 @@ pub mod fs;
mod memory; mod memory;
pub mod prelude; pub mod prelude;
mod process; mod process;
pub mod rights;
pub mod syscall; pub mod syscall;
mod user_apps; mod user_apps;
mod util; mod util;
pub mod vm; pub mod vm;
pub mod rights;
#[macro_use] #[macro_use]
extern crate kxos_frame_pod_derive; extern crate kxos_frame_pod_derive;

View File

@ -1,11 +1,11 @@
use kxos_typeflags::type_flags;
use bitflags::bitflags; use bitflags::bitflags;
use kxos_typeflags::type_flags;
bitflags! { bitflags! {
/// Value-based access rights. /// Value-based access rights.
/// ///
/// These access rights are provided to cover a wide range of use cases. /// These access rights are provided to cover a wide range of use cases.
/// The access rights' semantics and how they would restrict the behaviors /// The access rights' semantics and how they would restrict the behaviors
/// of a capability are decided by the capability's designer. /// of a capability are decided by the capability's designer.
/// Here, we give some sensible semantics for each access right. /// Here, we give some sensible semantics for each access right.
pub struct Rights: u32 { pub struct Rights: u32 {
@ -24,10 +24,10 @@ bitflags! {
} }
} }
/// Type-based access rights. /// Type-based access rights.
/// ///
/// Similar to value-based access rights (`Rights`), but represented in /// Similar to value-based access rights (`Rights`), but represented in
/// types. /// types.
/// ///
/// pub trait TRights: u32 { /// pub trait TRights: u32 {
/// /// Allows duplicating a capability. /// /// Allows duplicating a capability.
/// struct Dup: u32 = Rights::DUP; /// struct Dup: u32 = Rights::DUP;
@ -42,7 +42,7 @@ bitflags! {
/// /// Allows sending notifications or signals. /// /// Allows sending notifications or signals.
/// struct Signal: u32 = Rights::SIGNAL; /// struct Signal: u32 = Rights::SIGNAL;
/// } /// }
/// ///
type_flags! { type_flags! {
pub trait TRights: u32 { pub trait TRights: u32 {
pub struct Dup = 1 <<0; pub struct Dup = 1 <<0;
@ -54,10 +54,4 @@ type_flags! {
} }
/// The full set of access rights. /// The full set of access rights.
pub type Full = TRights![ pub type Full = TRights![Dup, Read, Write, Exec, Signal];
Dup,
Read,
Write,
Exec,
Signal
];

View File

@ -1,18 +1,18 @@
//! Virtual memory (VM). //! Virtual memory (VM).
//! //!
//! There are two primary VM abstractions: //! There are two primary VM abstractions:
//! * Virtual Memory Address Regions (VMARs) a type of capability that manages //! * 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 //! * Virtual Memory Objects (VMOs) are are a type of capability that
//! represents a set of memory pages. //! represents a set of memory pages.
//! //!
//! The concepts of VMARs and VMOs are originally introduced by //! The concepts of VMARs and VMOs are originally introduced by
//! [Zircon](https://fuchsia.dev/fuchsia-src/reference/kernel_objects/vm_object). //! [Zircon](https://fuchsia.dev/fuchsia-src/reference/kernel_objects/vm_object).
//! As capabilities, the two abstractions are aligned with our goal //! As capabilities, the two abstractions are aligned with our goal
//! of everything-is-a-capability, although their specifications and //! of everything-is-a-capability, although their specifications and
//! implementations in C/C++ cannot apply directly to KxOS. //! implementations in C/C++ cannot apply directly to KxOS.
//! In KxOS, VMARs and VMOs, as well as other capabilities, are implemented //! In KxOS, VMARs and VMOs, as well as other capabilities, are implemented
//! as zero-cost capabilities. //! as zero-cost capabilities.
mod vmar; mod vmar;
mod vmo; mod vmo;

View File

@ -1,12 +1,15 @@
use core::ops::Range; use core::ops::Range;
use alloc::sync::Arc; use alloc::sync::Arc;
use kxos_frame::{vm::VmIo, Error};
use kxos_frame::prelude::Result; use kxos_frame::prelude::Result;
use kxos_frame::{vm::VmIo, Error};
use crate::{rights::Rights, vm::vmo::Vmo}; use crate::{rights::Rights, vm::vmo::Vmo};
use super::{Vmar, VmPerms, options::{VmarChildOptions, VmarMapOptions}, Vmar_}; use super::{
options::{VmarChildOptions, VmarMapOptions},
VmPerms, Vmar, Vmar_,
};
impl Vmar<Rights> { impl Vmar<Rights> {
/// Creates a root VMAR. /// Creates a root VMAR.
@ -18,13 +21,13 @@ impl Vmar<Rights> {
} }
/// Maps the given VMO into the VMAR through a set of VMAR mapping options. /// Maps the given VMO into the VMAR through a set of VMAR mapping options.
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use kxos_std::prelude::*; /// use kxos_std::prelude::*;
/// use kxos_std::vm::{PAGE_SIZE, Vmar, VmoOptions}; /// use kxos_std::vm::{PAGE_SIZE, Vmar, VmoOptions};
/// ///
/// let vmar = Vmar::new().unwrap(); /// let vmar = Vmar::new().unwrap();
/// let vmo = VmoOptions::new(PAGE_SIZE).alloc().unwrap(); /// let vmo = VmoOptions::new(PAGE_SIZE).alloc().unwrap();
/// let target_vaddr = 0x1234000; /// let target_vaddr = 0x1234000;
@ -37,44 +40,48 @@ impl Vmar<Rights> {
/// .unwrap(); /// .unwrap();
/// assert!(real_vaddr == target_vaddr); /// assert!(real_vaddr == target_vaddr);
/// ``` /// ```
/// ///
/// For more details on the available options, see `VmarMapOptions`. /// For more details on the available options, see `VmarMapOptions`.
/// ///
/// # Access rights /// # Access rights
/// ///
/// This method requires the following access rights: /// This method requires the following access rights:
/// 1. The VMAR contains the rights corresponding to the memory permissions of /// 1. The VMAR contains the rights corresponding to the memory permissions of
/// the mapping. For example, if `perms` contains `VmPerm::WRITE`, /// the mapping. For example, if `perms` contains `VmPerm::WRITE`,
/// then the VMAR must have the Write right. /// then the VMAR must have the Write right.
/// 2. Similarly, the VMO contains the rights corresponding to the memory /// 2. Similarly, the VMO contains the rights corresponding to the memory
/// permissions of the mapping. /// permissions of the mapping.
/// ///
/// Memory permissions may be changed through the `protect` method, /// Memory permissions may be changed through the `protect` method,
/// which ensures that any updated memory permissions do not go beyond /// which ensures that any updated memory permissions do not go beyond
/// the access rights of the underlying VMOs. /// the access rights of the underlying VMOs.
pub fn new_map(&self, vmo: Vmo<Rights>, perms: VmPerms) -> Result<VmarMapOptions<Rights,Rights>> { pub fn new_map(
&self,
vmo: Vmo<Rights>,
perms: VmPerms,
) -> Result<VmarMapOptions<Rights, Rights>> {
let dup_self = self.dup()?; let dup_self = self.dup()?;
Ok(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. /// Creates a new child VMAR through a set of VMAR child options.
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// let parent = Vmar::new().unwrap(); /// let parent = Vmar::new().unwrap();
/// let child_size = 10 * PAGE_SIZE; /// let child_size = 10 * PAGE_SIZE;
/// let child = parent.new_child(child_size).alloc().unwrap(); /// let child = parent.new_child(child_size).alloc().unwrap();
/// assert!(child.size() == child_size); /// assert!(child.size() == child_size);
/// ``` /// ```
/// ///
/// For more details on the available options, see `VmarChildOptions`. /// For more details on the available options, see `VmarChildOptions`.
/// ///
/// # Access rights /// # Access rights
/// ///
/// This method requires the Dup right. /// This method requires the Dup right.
/// ///
/// The new VMAR child will be of the same capability class and /// The new VMAR child will be of the same capability class and
/// access rights as the parent. /// access rights as the parent.
pub fn new_child(&self, size: usize) -> Result<VmarChildOptions<Rights>> { pub fn new_child(&self, size: usize) -> Result<VmarChildOptions<Rights>> {
let dup_self = self.dup()?; let dup_self = self.dup()?;
@ -82,25 +89,25 @@ impl Vmar<Rights> {
} }
/// Change the permissions of the memory mappings in the specified range. /// Change the permissions of the memory mappings in the specified range.
/// ///
/// The range's start and end addresses must be page-aligned. /// The range's start and end addresses must be page-aligned.
/// Also, the range must be completely mapped. /// Also, the range must be completely mapped.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The VMAR must have the rights corresponding to the specified memory /// The VMAR must have the rights corresponding to the specified memory
/// permissions. /// permissions.
/// ///
/// The mappings overlapped with the specified range must be backed by /// The mappings overlapped with the specified range must be backed by
/// VMOs whose rights contain the rights corresponding to the specified /// VMOs whose rights contain the rights corresponding to the specified
/// memory permissions. /// memory permissions.
pub fn protect(&self, perms: VmPerms, range: Range<usize>) -> Result<()> { pub fn protect(&self, perms: VmPerms, range: Range<usize>) -> Result<()> {
self.check_rights(perms.into())?; self.check_rights(perms.into())?;
self.0.protect(perms, range) self.0.protect(perms, range)
} }
/// Destroy a VMAR, including all its mappings and children VMARs. /// Destroy a VMAR, including all its mappings and children VMARs.
/// ///
/// After being destroyed, the VMAR becomes useless and returns errors /// After being destroyed, the VMAR becomes useless and returns errors
/// for most of its methods. /// for most of its methods.
pub fn destroy_all(&self) -> Result<()> { pub fn destroy_all(&self) -> Result<()> {
@ -109,10 +116,10 @@ impl Vmar<Rights> {
/// Destroy all mappings and children VMARs that fall within the specified /// Destroy all mappings and children VMARs that fall within the specified
/// range in bytes. /// range in bytes.
/// ///
/// The range's start and end addresses must be page-aligned. /// The range's start and end addresses must be page-aligned.
/// ///
/// Mappings may fall partially within the range; only the overlapped /// Mappings may fall partially within the range; only the overlapped
/// portions of the mappings are unmapped. /// portions of the mappings are unmapped.
/// As for children VMARs, they must be fully within the range. /// As for children VMARs, they must be fully within the range.
/// All children VMARs that fall within the range get their `destroy` methods /// All children VMARs that fall within the range get their `destroy` methods
@ -122,10 +129,10 @@ impl Vmar<Rights> {
} }
/// Duplicates the capability. /// Duplicates the capability.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The method requires the Dup right. /// The method requires the Dup right.
pub fn dup(&self) -> Result<Self> { pub fn dup(&self) -> Result<Self> {
self.check_rights(Rights::DUP)?; self.check_rights(Rights::DUP)?;
todo!() todo!()
@ -143,7 +150,6 @@ impl Vmar<Rights> {
Err(Error::AccessDenied) Err(Error::AccessDenied)
} }
} }
} }
impl VmIo for Vmar<Rights> { impl VmIo for Vmar<Rights> {
@ -156,4 +162,4 @@ impl VmIo for Vmar<Rights> {
self.check_rights(Rights::WRITE)?; self.check_rights(Rights::WRITE)?;
self.0.write(offset, buf) self.0.write(offset, buf)
} }
} }

View File

@ -1,46 +1,46 @@
//! Virtual Memory Address Regions (VMARs). //! Virtual Memory Address Regions (VMARs).
mod static_cap;
mod dyn_cap; mod dyn_cap;
mod options; mod options;
mod static_cap;
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 crate::rights::Rights;
use alloc::sync::Arc;
use bitflags::bitflags; use bitflags::bitflags;
use core::ops::Range;
use kxos_frame::prelude::Result;
use kxos_frame::vm::Vaddr;
use kxos_frame::vm::VmSpace;
use kxos_frame::Error;
use spin::Mutex;
/// 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.
/// ///
/// # Capabilities /// # Capabilities
/// ///
/// As a capability, each VMAR is associated with a set of access rights, /// As a capability, each VMAR is associated with a set of access rights,
/// whose semantics are explained below. /// whose semantics are explained below.
/// ///
/// The semantics of each access rights for VMARs are described below: /// The semantics of each access rights for VMARs are described below:
/// * The Dup right allows duplicating a VMAR and creating children out of /// * The Dup right allows duplicating a VMAR and creating children out of
/// a VMAR. /// a VMAR.
/// * The Read, Write, Exec rights allow creating memory mappings with /// * The Read, Write, Exec rights allow creating memory mappings with
/// readable, writable, and executable access permissions, respectively. /// readable, writable, and executable access permissions, respectively.
/// * The Read and Write rights allow the VMAR to be read from and written to /// * The Read and Write rights allow the VMAR to be read from and written to
/// directly. /// directly.
/// ///
/// VMARs are implemented with two flavors of capabilities: /// VMARs are implemented with two flavors of capabilities:
/// the dynamic one (`Vmar<Rights>`) and the static one (`Vmar<R: TRights>). /// the dynamic one (`Vmar<Rights>`) and the static one (`Vmar<R: TRights>).
/// ///
/// # Implementation /// # Implementation
/// ///
/// `Vmar` provides high-level APIs for address space management by wrapping /// `Vmar` provides high-level APIs for address space management by wrapping
/// around its low-level counterpart `kx_frame::vm::VmFrames`. /// around its low-level counterpart `kx_frame::vm::VmFrames`.
/// Compared with `VmFrames`, /// Compared with `VmFrames`,
/// `Vmar` is easier to use (by offering more powerful APIs) and /// `Vmar` is easier to use (by offering more powerful APIs) and
/// harder to misuse (thanks to its nature of being capability). /// harder to misuse (thanks to its nature of being capability).
/// ///
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.
@ -86,13 +86,11 @@ impl Vmar_ {
impl<R> Vmar<R> { impl<R> Vmar<R> {
/// The base address, i.e., the offset relative to the root VMAR. /// The base address, i.e., the offset relative to the root VMAR.
/// ///
/// The base address of a root VMAR is zero. /// The base address of a root VMAR is zero.
pub fn base(&self) -> Vaddr { pub fn base(&self) -> Vaddr {
self.0.base self.0.base
} }
} }
bitflags! { bitflags! {

View File

@ -1,23 +1,23 @@
//! Options for allocating child VMARs and creating mappings. //! Options for allocating child VMARs and creating mappings.
use kxos_frame::{config::PAGE_SIZE, vm::Vaddr};
use kxos_frame::prelude::Result; use kxos_frame::prelude::Result;
use kxos_frame::{config::PAGE_SIZE, vm::Vaddr};
use crate::vm::vmo::Vmo; use crate::vm::vmo::Vmo;
use super::{Vmar, VmPerms}; use super::{VmPerms, Vmar};
/// Options for allocating a child VMAR, which must not overlap with any /// Options for allocating a child VMAR, which must not overlap with any
/// existing mappings or child VMARs. /// existing mappings or child VMARs.
/// ///
/// # Examples /// # Examples
/// ///
/// A child VMAR created from a parent VMAR of _dynamic_ capability is also a /// A child VMAR created from a parent VMAR of _dynamic_ capability is also a
/// _dynamic_ capability. /// _dynamic_ capability.
/// ``` /// ```
/// use kxo_std::vm::{PAGE_SIZE, Vmar}; /// use kxo_std::vm::{PAGE_SIZE, Vmar};
/// ///
/// let parent_vmar = Vmar::new(); /// let parent_vmar = Vmar::new();
/// let child_size = 10 * PAGE_SIZE; /// let child_size = 10 * PAGE_SIZE;
/// let child_vmar = parent_vmar /// let child_vmar = parent_vmar
/// .new_child(child_size) /// .new_child(child_size)
@ -26,14 +26,14 @@ use super::{Vmar, VmPerms};
/// assert!(child_vmar.rights() == parent_vmo.rights()); /// assert!(child_vmar.rights() == parent_vmo.rights());
/// assert!(child_vmar.size() == child_size); /// assert!(child_vmar.size() == child_size);
/// ``` /// ```
/// ///
/// A child VMO created from a parent VMO of _static_ capability is also a /// A child VMO created from a parent VMO of _static_ capability is also a
/// _static_ capability. /// _static_ capability.
/// ``` /// ```
/// use kxos_std::prelude::*; /// use kxos_std::prelude::*;
/// use kxos_std::vm::{PAGE_SIZE, Vmar}; /// use kxos_std::vm::{PAGE_SIZE, Vmar};
/// ///
/// let parent_vmar: Vmar<Full> = Vmar::new(); /// let parent_vmar: Vmar<Full> = Vmar::new();
/// let child_size = 10 * PAGE_SIZE; /// let child_size = 10 * PAGE_SIZE;
/// let child_vmar = parent_vmar /// let child_vmar = parent_vmar
/// .new_child(child_size) /// .new_child(child_size)
@ -46,13 +46,13 @@ pub struct VmarChildOptions<R> {
parent: Vmar<R>, parent: Vmar<R>,
size: usize, size: usize,
offset: usize, offset: usize,
align:usize, align: usize,
} }
impl<R> VmarChildOptions<R> { impl<R> VmarChildOptions<R> {
/// Creates a default set of options with the specified size of the VMAR /// Creates a default set of options with the specified size of the VMAR
/// (in bytes). /// (in bytes).
/// ///
/// The size of the VMAR will be rounded up to align with the page size. /// The size of the VMAR will be rounded up to align with the page size.
pub fn new(parent: Vmar<R>, size: usize) -> Self { pub fn new(parent: Vmar<R>, size: usize) -> Self {
Self { Self {
@ -64,9 +64,9 @@ impl<R> VmarChildOptions<R> {
} }
/// Set the alignment of the child VMAR. /// Set the alignment of the child VMAR.
/// ///
/// By default, the alignment is the page size. /// By default, the alignment is the page size.
/// ///
/// The alignment must be a power of two and a multiple of the page size. /// The alignment must be a power of two and a multiple of the page size.
pub fn align(mut self, align: usize) -> Self { pub fn align(mut self, align: usize) -> Self {
todo!() todo!()
@ -75,34 +75,34 @@ impl<R> VmarChildOptions<R> {
/// Sets the offset of the child VMAR. /// Sets the offset of the child VMAR.
/// ///
/// If not set, the system will choose an offset automatically. /// If not set, the system will choose an offset automatically.
/// ///
/// The offset must satisfy the alignment requirement. /// The offset must satisfy the alignment requirement.
/// Also, the child VMAR's range `[offset, offset + size)` must be within /// Also, the child VMAR's range `[offset, offset + size)` must be within
/// the VMAR. /// the VMAR.
/// ///
/// If not specified, /// If not specified,
/// ///
/// The offset must be page-aligned. /// The offset must be page-aligned.
pub fn offset(mut self, offset: usize) -> Self { pub fn offset(mut self, offset: usize) -> Self {
todo!() todo!()
} }
/// Allocates the child VMAR according to the specified options. /// Allocates the child VMAR according to the specified options.
/// ///
/// The new child VMAR /// The new child VMAR
/// ///
/// # Access rights /// # Access rights
/// ///
/// The child VMAR is initially assigned all the parent's access rights. /// The child VMAR is initially assigned all the parent's access rights.
pub fn alloc(mut self) -> Result<Vmar<R>> { pub fn alloc(mut self) -> Result<Vmar<R>> {
todo!() todo!()
} }
} }
/// 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
/// with any child VMARs. And unless specified otherwise, it is not allowed /// with any child VMARs. And unless specified otherwise, it is not allowed
/// to overlap with any existing mapping, either. /// to overlap with any existing mapping, either.
pub struct VmarMapOptions<R1,R2> { pub struct VmarMapOptions<R1, R2> {
parent: Vmar<R1>, parent: Vmar<R1>,
vmo: Vmo<R2>, vmo: Vmo<R2>,
perms: VmPerms, perms: VmPerms,
@ -113,10 +113,10 @@ pub struct VmarMapOptions<R1,R2> {
can_overwrite: bool, can_overwrite: bool,
} }
impl<R1,R2> VmarMapOptions<R1,R2> { impl<R1, R2> VmarMapOptions<R1, R2> {
/// Creates a default set of options with the VMO and the memory access /// Creates a default set of options with the VMO and the memory access
/// permissions. /// permissions.
/// ///
/// The VMO must have access rights that correspond to the memory /// The VMO must have access rights that correspond to the memory
/// access permissions. For example, if `perms` contains `VmPerm::Write`, /// access permissions. For example, if `perms` contains `VmPerm::Write`,
/// then `vmo.rights()` should contain `Rights::WRITE`. /// then `vmo.rights()` should contain `Rights::WRITE`.
@ -136,9 +136,9 @@ impl<R1,R2> VmarMapOptions<R1,R2> {
/// Sets the offset of the first memory page in the VMO that is to be /// Sets the offset of the first memory page in the VMO that is to be
/// mapped into the VMAR. /// mapped into the VMAR.
/// ///
/// The offset must be page-aligned and within the VMO. /// The offset must be page-aligned and within the VMO.
/// ///
/// The default value is zero. /// The default value is zero.
pub fn vmo_offset(mut self, offset: usize) -> Self { pub fn vmo_offset(mut self, offset: usize) -> Self {
self.vmo_offset = offset; self.vmo_offset = offset;
@ -146,12 +146,12 @@ impl<R1,R2> VmarMapOptions<R1,R2> {
} }
/// Sets the size of the mapping. /// Sets the size of the mapping.
/// ///
/// The size of a mapping may not be equal to that of the VMO. /// The size of a mapping may not be equal to that of the VMO.
/// For example, it is ok to create a mapping whose size is larger than /// For example, it is ok to create a mapping whose size is larger than
/// that of the VMO, although one cannot read from or write to the /// that of the VMO, although one cannot read from or write to the
/// part of the mapping that is not backed by the VMO. /// part of the mapping that is not backed by the VMO.
/// So you may wonder: what is the point of supporting such _oversized_ /// So you may wonder: what is the point of supporting such _oversized_
/// mappings? The reason is two-fold. /// mappings? The reason is two-fold.
/// 1. VMOs are resizable. So even if a mapping is backed by a VMO whose /// 1. VMOs are resizable. So even if a mapping is backed by a VMO whose
/// size is equal to that of the mapping initially, we cannot prevent /// size is equal to that of the mapping initially, we cannot prevent
@ -159,7 +159,7 @@ impl<R1,R2> VmarMapOptions<R1,R2> {
/// 2. Mappings are not allowed to overlap by default. As a result, /// 2. Mappings are not allowed to overlap by default. As a result,
/// oversized mappings can serve as a placeholder to prevent future /// oversized mappings can serve as a placeholder to prevent future
/// mappings from occupying some particular address ranges accidentally. /// mappings from occupying some particular address ranges accidentally.
/// ///
/// The default value is the size of the VMO. /// The default value is the size of the VMO.
pub fn size(mut self, size: usize) -> Self { pub fn size(mut self, size: usize) -> Self {
self.size = size; self.size = size;
@ -167,9 +167,9 @@ impl<R1,R2> VmarMapOptions<R1,R2> {
} }
/// Sets the mapping's alignment. /// Sets the mapping's alignment.
/// ///
/// The default value is the page size. /// The default value is the page size.
/// ///
/// The provided alignment must be a power of two and a multiple of the /// The provided alignment must be a power of two and a multiple of the
/// page size. /// page size.
pub fn align(mut self, align: usize) -> Self { pub fn align(mut self, align: usize) -> Self {
@ -178,11 +178,11 @@ impl<R1,R2> VmarMapOptions<R1,R2> {
} }
/// Sets the mapping's offset inside the VMAR. /// Sets the mapping's offset inside the VMAR.
/// ///
/// The offset must satisfy the alignment requirement. /// The offset must satisfy the alignment requirement.
/// Also, the mapping's range `[offset, offset + size)` must be within /// Also, the mapping's range `[offset, offset + size)` must be within
/// the VMAR. /// the VMAR.
/// ///
/// If not set, the system will choose an offset automatically. /// If not set, the system will choose an offset automatically.
pub fn offset(mut self, offset: usize) -> Self { pub fn offset(mut self, offset: usize) -> Self {
self.offset = Some(offset); self.offset = Some(offset);
@ -190,9 +190,9 @@ impl<R1,R2> VmarMapOptions<R1,R2> {
} }
/// Sets whether the mapping can overwrite existing mappings. /// Sets whether the mapping can overwrite existing mappings.
/// ///
/// The default value is false. /// The default value is false.
/// ///
/// If this option is set to true, then the `offset` option must be /// If this option is set to true, then the `offset` option must be
/// set. /// set.
pub fn can_overwrite(mut self, can_overwrite: bool) -> Self { pub fn can_overwrite(mut self, can_overwrite: bool) -> Self {
@ -201,9 +201,9 @@ impl<R1,R2> VmarMapOptions<R1,R2> {
} }
/// Creates the mapping. /// Creates the mapping.
/// ///
/// All options will be checked at this point. /// All options will be checked at this point.
/// ///
/// On success, the virtual address of the new mapping is returned. /// On success, the virtual address of the new mapping is returned.
pub fn build(mut self) -> Result<Vaddr> { pub fn build(mut self) -> Result<Vaddr> {
todo!() todo!()

View File

@ -1,19 +1,22 @@
use core::ops::Range; use core::ops::Range;
use alloc::sync::Arc; use alloc::sync::Arc;
use kxos_frame::prelude::Result;
use kxos_frame::{vm::VmIo, Error}; use kxos_frame::{vm::VmIo, Error};
use kxos_rights_proc::require; use kxos_rights_proc::require;
use kxos_frame::prelude::Result;
use crate::{rights::*, vm::vmo::Vmo}; use crate::{rights::*, vm::vmo::Vmo};
use super::{Vmar, Vmar_, VmPerms, options::{VmarMapOptions, VmarChildOptions}}; use super::{
options::{VmarChildOptions, VmarMapOptions},
VmPerms, Vmar, Vmar_,
};
impl<R: TRights> Vmar<R> { impl<R: TRights> Vmar<R> {
/// Creates a root VMAR. /// Creates a root VMAR.
/// ///
/// # Access rights /// # Access rights
/// ///
/// A root VMAR is initially given full access rights. /// A root VMAR is initially given full access rights.
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let inner = Arc::new(Vmar_::new()?); let inner = Arc::new(Vmar_::new()?);
@ -23,13 +26,13 @@ impl<R: TRights> Vmar<R> {
} }
/// Maps the given VMO into the VMAR through a set of VMAR mapping options. /// Maps the given VMO into the VMAR through a set of VMAR mapping options.
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use kxos_std::prelude::*; /// use kxos_std::prelude::*;
/// use kxos_std::vm::{PAGE_SIZE, Vmar, VmoOptions}; /// use kxos_std::vm::{PAGE_SIZE, Vmar, VmoOptions};
/// ///
/// let vmar = Vmar::<Full>::new().unwrap(); /// let vmar = Vmar::<Full>::new().unwrap();
/// let vmo = VmoOptions::new(PAGE_SIZE).alloc().unwrap(); /// let vmo = VmoOptions::new(PAGE_SIZE).alloc().unwrap();
/// let target_vaddr = 0x1234000; /// let target_vaddr = 0x1234000;
@ -42,45 +45,45 @@ impl<R: TRights> Vmar<R> {
/// .unwrap(); /// .unwrap();
/// assert!(real_vaddr == target_vaddr); /// assert!(real_vaddr == target_vaddr);
/// ``` /// ```
/// ///
/// For more details on the available options, see `VmarMapOptions`. /// For more details on the available options, see `VmarMapOptions`.
/// ///
/// # Access rights /// # Access rights
/// ///
/// This method requires the following access rights: /// This method requires the following access rights:
/// 1. The VMAR contains the rights corresponding to the memory permissions of /// 1. The VMAR contains the rights corresponding to the memory permissions of
/// the mapping. For example, if `perms` contains `VmPerm::WRITE`, /// the mapping. For example, if `perms` contains `VmPerm::WRITE`,
/// then the VMAR must have the Write right. /// then the VMAR must have the Write right.
/// 2. Similarly, the VMO contains the rights corresponding to the memory /// 2. Similarly, the VMO contains the rights corresponding to the memory
/// permissions of the mapping. /// permissions of the mapping.
/// ///
/// Memory permissions may be changed through the `protect` method, /// Memory permissions may be changed through the `protect` method,
/// which ensures that any updated memory permissions do not go beyond /// which ensures that any updated memory permissions do not go beyond
/// the access rights of the underlying VMOs. /// the access rights of the underlying VMOs.
#[require(R > Dup)] #[require(R > Dup)]
pub fn new_map(&self, vmo: Vmo<Rights>, perms: VmPerms) -> Result<VmarMapOptions<R,Rights>> { pub fn new_map(&self, vmo: Vmo<Rights>, perms: VmPerms) -> Result<VmarMapOptions<R, Rights>> {
let dup_self = self.dup()?; let dup_self = self.dup()?;
Ok(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. /// Creates a new child VMAR through a set of VMAR child options.
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// let parent = Vmar::new().unwrap(); /// let parent = Vmar::new().unwrap();
/// let child_size = 10 * PAGE_SIZE; /// let child_size = 10 * PAGE_SIZE;
/// let child = parent.new_child(child_size).alloc().unwrap(); /// let child = parent.new_child(child_size).alloc().unwrap();
/// assert!(child.size() == child_size); /// assert!(child.size() == child_size);
/// ``` /// ```
/// ///
/// For more details on the available options, see `VmarChildOptions`. /// For more details on the available options, see `VmarChildOptions`.
/// ///
/// # Access rights /// # Access rights
/// ///
/// This method requires the Dup right. /// This method requires the Dup right.
/// ///
/// The new VMAR child will be of the same capability class and /// The new VMAR child will be of the same capability class and
/// access rights as the parent. /// access rights as the parent.
#[require(R > Dup)] #[require(R > Dup)]
pub fn new_child(&self, size: usize) -> Result<VmarChildOptions<R>> { pub fn new_child(&self, size: usize) -> Result<VmarChildOptions<R>> {
@ -89,25 +92,25 @@ impl<R: TRights> Vmar<R> {
} }
/// Change the permissions of the memory mappings in the specified range. /// Change the permissions of the memory mappings in the specified range.
/// ///
/// The range's start and end addresses must be page-aligned. /// The range's start and end addresses must be page-aligned.
/// Also, the range must be completely mapped. /// Also, the range must be completely mapped.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The VMAR must have the rights corresponding to the specified memory /// The VMAR must have the rights corresponding to the specified memory
/// permissions. /// permissions.
/// ///
/// The mappings overlapped with the specified range must be backed by /// The mappings overlapped with the specified range must be backed by
/// VMOs whose rights contain the rights corresponding to the specified /// VMOs whose rights contain the rights corresponding to the specified
/// memory permissions. /// memory permissions.
pub fn protect(&self, perms: VmPerms, range: Range<usize>) -> Result<()> { pub fn protect(&self, perms: VmPerms, range: Range<usize>) -> Result<()> {
self.check_rights(perms.into())?; self.check_rights(perms.into())?;
self.0.protect(perms, range) self.0.protect(perms, range)
} }
/// Destroy a VMAR, including all its mappings and children VMARs. /// Destroy a VMAR, including all its mappings and children VMARs.
/// ///
/// After being destroyed, the VMAR becomes useless and returns errors /// After being destroyed, the VMAR becomes useless and returns errors
/// for most of its methods. /// for most of its methods.
pub fn destroy_all(&self) -> Result<()> { pub fn destroy_all(&self) -> Result<()> {
@ -116,10 +119,10 @@ impl<R: TRights> Vmar<R> {
/// Destroy all mappings and children VMARs that fall within the specified /// Destroy all mappings and children VMARs that fall within the specified
/// range in bytes. /// range in bytes.
/// ///
/// The range's start and end addresses must be page-aligned. /// The range's start and end addresses must be page-aligned.
/// ///
/// Mappings may fall partially within the range; only the overlapped /// Mappings may fall partially within the range; only the overlapped
/// portions of the mappings are unmapped. /// portions of the mappings are unmapped.
/// As for children VMARs, they must be fully within the range. /// As for children VMARs, they must be fully within the range.
/// All children VMARs that fall within the range get their `destroy` methods /// All children VMARs that fall within the range get their `destroy` methods
@ -129,10 +132,10 @@ impl<R: TRights> Vmar<R> {
} }
/// Duplicate the capability. /// Duplicate the capability.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The method requires the Dup right. /// The method requires the Dup right.
#[require(R > Dup)] #[require(R > Dup)]
pub fn dup(&self) -> Result<Self> { pub fn dup(&self) -> Result<Self> {
todo!() todo!()
@ -156,10 +159,9 @@ impl<R: TRights> Vmar<R> {
Err(Error::AccessDenied) Err(Error::AccessDenied)
} }
} }
} }
impl<R:TRights> VmIo for Vmar<R> { impl<R: TRights> VmIo for Vmar<R> {
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)?;
self.0.read(offset, buf) self.0.read(offset, buf)
@ -169,4 +171,4 @@ impl<R:TRights> VmIo for Vmar<R> {
// self.check_rights!(Rights::WRITE)?; // self.check_rights!(Rights::WRITE)?;
self.0.write(offset, buf) self.0.write(offset, buf)
} }
} }

View File

@ -1,119 +1,128 @@
use core::ops::Range; use core::ops::Range;
use kxos_frame::{vm::VmIo, Error};
use kxos_frame::prelude::Result; use kxos_frame::prelude::Result;
use kxos_frame::{vm::VmIo, Error};
use crate::rights::{Rights, TRights}; use crate::rights::{Rights, TRights};
use super::{VmoChildOptions, options::{VmoSliceChild, VmoCowChild}, Vmo}; use super::{
options::{VmoCowChild, VmoSliceChild},
Vmo, VmoChildOptions,
};
impl Vmo<Rights> { impl Vmo<Rights> {
/// Creates a new slice VMO through a set of VMO child options. /// Creates a new slice VMO through a set of VMO child options.
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// let parent = VmoOptions::new(PAGE_SIZE).alloc().unwrap(); /// let parent = VmoOptions::new(PAGE_SIZE).alloc().unwrap();
/// let child_size = parent.size(); /// let child_size = parent.size();
/// let child = parent.new_slice_child(0..child_size).alloc().unwrap(); /// let child = parent.new_slice_child(0..child_size).alloc().unwrap();
/// assert!(child.size() == child_size); /// assert!(child.size() == child_size);
/// ``` /// ```
/// ///
/// For more details on the available options, see `VmoChildOptions`. /// For more details on the available options, see `VmoChildOptions`.
/// ///
/// # Access rights /// # Access rights
/// ///
/// This method requires the Dup right. /// This method requires the Dup right.
/// ///
/// The new VMO child will be of the same capability flavor as the parent; /// The new VMO child will be of the same capability flavor as the parent;
/// so are the access rights. /// so are the access rights.
pub fn new_slice_child(&self, range: Range<usize>) -> Result<VmoChildOptions<Rights, VmoSliceChild>> { pub fn new_slice_child(
&self,
range: Range<usize>,
) -> Result<VmoChildOptions<Rights, VmoSliceChild>> {
let dup_self = self.dup()?; let dup_self = self.dup()?;
Ok(VmoChildOptions::new_slice_rights(dup_self, range)) Ok(VmoChildOptions::new_slice_rights(dup_self, range))
} }
/// Creates a new COW VMO through a set of VMO child options. /// Creates a new COW VMO through a set of VMO child options.
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// let parent = VmoOptions::new(PAGE_SIZE).alloc().unwrap(); /// let parent = VmoOptions::new(PAGE_SIZE).alloc().unwrap();
/// let child_size = 2 * parent.size(); /// let child_size = 2 * parent.size();
/// let child = parent.new_cow_child(0..child_size).alloc().unwrap(); /// let child = parent.new_cow_child(0..child_size).alloc().unwrap();
/// assert!(child.size() == child_size); /// assert!(child.size() == child_size);
/// ``` /// ```
/// ///
/// For more details on the available options, see `VmoChildOptions`. /// For more details on the available options, see `VmoChildOptions`.
/// ///
/// # Access rights /// # Access rights
/// ///
/// This method requires the Dup right. /// This method requires the Dup right.
/// ///
/// The new VMO child will be of the same capability flavor as the parent. /// 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 /// The child will be given the access rights of the parent
/// plus the Write right. /// plus the Write right.
pub fn new_cow_child(&self, range: Range<usize>) -> Result<VmoChildOptions<Rights, VmoCowChild>> { pub fn new_cow_child(
&self,
range: Range<usize>,
) -> Result<VmoChildOptions<Rights, VmoCowChild>> {
let dup_self = self.dup()?; let dup_self = self.dup()?;
Ok(VmoChildOptions::new_cow(dup_self, range)) Ok(VmoChildOptions::new_cow(dup_self, range))
} }
/// Commits the pages specified in the range (in bytes). /// Commits the pages specified in the range (in bytes).
/// ///
/// The range must be within the size of the VMO. /// The range must be within the size of the VMO.
/// ///
/// The start and end addresses will be rounded down and up to page boundaries. /// The start and end addresses will be rounded down and up to page boundaries.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The method requires the Write right. /// The method requires the Write right.
pub fn commit(&self, range: Range<usize>) -> Result<()> { pub fn commit(&self, range: Range<usize>) -> Result<()> {
self.check_rights(Rights::WRITE)?; self.check_rights(Rights::WRITE)?;
self.0.commit(range) self.0.commit(range)
} }
/// Decommits the pages specified in the range (in bytes). /// Decommits the pages specified in the range (in bytes).
/// ///
/// The range must be within the size of the VMO. /// The range must be within the size of the VMO.
/// ///
/// The start and end addresses will be rounded down and up to page boundaries. /// The start and end addresses will be rounded down and up to page boundaries.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The method requires the Write right. /// The method requires the Write right.
pub fn decommit(&self, range: Range<usize>) -> Result<()> { pub fn decommit(&self, range: Range<usize>) -> Result<()> {
self.check_rights(Rights::WRITE)?; self.check_rights(Rights::WRITE)?;
self.0.decommit(range) self.0.decommit(range)
} }
/// Resizes the VMO by giving a new size. /// Resizes the VMO by giving a new size.
/// ///
/// The VMO must be resizable. /// The VMO must be resizable.
/// ///
/// The new size will be rounded up to page boundaries. /// The new size will be rounded up to page boundaries.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The method requires the Write right. /// The method requires the Write right.
pub fn resize(&self, new_size: usize) -> Result<()> { pub fn resize(&self, new_size: usize) -> Result<()> {
self.check_rights(Rights::WRITE)?; self.check_rights(Rights::WRITE)?;
self.0.resize(new_size) self.0.resize(new_size)
} }
/// Clears the specified range by writing zeros. /// Clears the specified range by writing zeros.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The method requires the Write right. /// The method requires the Write right.
pub fn clear(&self, range: Range<usize>) -> Result<()> { pub fn clear(&self, range: Range<usize>) -> Result<()> {
self.check_rights(Rights::WRITE)?; self.check_rights(Rights::WRITE)?;
self.0.clear(range) self.0.clear(range)
} }
/// Duplicates the capability. /// Duplicates the capability.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The method requires the Dup right. /// The method requires the Dup right.
pub fn dup(&self) -> Result<Self> { pub fn dup(&self) -> Result<Self> {
self.check_rights(Rights::DUP)?; self.check_rights(Rights::DUP)?;
todo!() todo!()
@ -137,7 +146,7 @@ impl Vmo<Rights> {
pub fn check_rights(&self, rights: Rights) -> Result<()> { pub fn check_rights(&self, rights: Rights) -> Result<()> {
if self.rights().contains(rights) { if self.rights().contains(rights) {
Ok(()) Ok(())
} else { } else {
Err(Error::AccessDenied) Err(Error::AccessDenied)
} }
@ -154,4 +163,4 @@ impl VmIo for Vmo<Rights> {
self.check_rights(Rights::WRITE)?; self.check_rights(Rights::WRITE)?;
self.0.write_bytes(offset, buf) self.0.write_bytes(offset, buf)
} }
} }

View File

@ -2,30 +2,28 @@
use core::ops::Range; use core::ops::Range;
use kxos_frame::{prelude::Result, vm::Paddr, Error};
use crate::rights::Rights; use crate::rights::Rights;
use alloc::sync::Arc; use alloc::sync::Arc;
use bitflags::bitflags; use bitflags::bitflags;
use kxos_frame::{prelude::Result, vm::Paddr, Error};
mod static_cap;
mod dyn_cap; mod dyn_cap;
mod options; mod options;
mod pager; mod pager;
mod static_cap;
pub use options::{VmoOptions, VmoChildOptions}; pub use options::{VmoChildOptions, VmoOptions};
pub use pager::Pager; pub use pager::Pager;
use spin::Mutex; use spin::Mutex;
/// 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.
/// ///
/// # Features /// # Features
/// ///
/// * **I/O interface.** A VMO provides read and write methods to access the /// * **I/O interface.** A VMO provides read and write methods to access the
/// memory pages that it contain. /// memory pages that it contain.
/// * **On-demand paging.** The memory pages of a VMO (except for _contiguous_ /// * **On-demand paging.** The memory pages of a VMO (except for _contiguous_
/// VMOs) are allocated lazily when the page is first accessed. /// VMOs) are allocated lazily when the page is first accessed.
/// * **Tree structure.** Given a VMO, one can create a child VMO from it. /// * **Tree structure.** Given a VMO, one can create a child VMO from it.
/// The child VMO can only access a subset of the parent's memory, /// The child VMO can only access a subset of the parent's memory,
@ -33,46 +31,46 @@ use spin::Mutex;
/// * **Copy-on-write (COW).** A child VMO may be created with COW semantics, /// * **Copy-on-write (COW).** A child VMO may be created with COW semantics,
/// which prevents any writes on the child from affecting the parent /// which prevents any writes on the child from affecting the parent
/// by duplicating memory pages only upon the first writes. /// by duplicating memory pages only upon the first writes.
/// * **Access control.** As capabilities, VMOs restrict the /// * **Access control.** As capabilities, VMOs restrict the
/// accessible range of memory and the allowed I/O operations. /// accessible range of memory and the allowed I/O operations.
/// * **Device driver support.** If specified upon creation, VMOs will be /// * **Device driver support.** If specified upon creation, VMOs will be
/// backed by physically contiguous memory pages starting at a target address. /// backed by physically contiguous memory pages starting at a target address.
/// * **File system support.** By default, a VMO's memory pages are initially /// * **File system support.** By default, a VMO's memory pages are initially
/// all zeros. But if a VMO is attached to a pager (`Pager`) upon creation, /// all zeros. But if a VMO is attached to a pager (`Pager`) upon creation,
/// then its memory pages will be populated by the pager. /// then its memory pages will be populated by the pager.
/// With this pager mechanism, file systems can easily implement page caches /// With this pager mechanism, file systems can easily implement page caches
/// with VMOs by attaching the VMOs to pagers backed by inodes. /// with VMOs by attaching the VMOs to pagers backed by inodes.
/// ///
/// # Capabilities /// # Capabilities
/// ///
/// As a capability, each VMO is associated with a set of access rights, /// As a capability, each VMO is associated with a set of access rights,
/// whose semantics are explained below. /// whose semantics are explained below.
/// ///
/// * The Dup right allows duplicating a VMO and creating children out of /// * The Dup right allows duplicating a VMO and creating children out of
/// a VMO. /// a VMO.
/// * The Read, Write, Exec rights allow creating memory mappings with /// * The Read, Write, Exec rights allow creating memory mappings with
/// readable, writable, and executable access permissions, respectively. /// readable, writable, and executable access permissions, respectively.
/// * The Read and Write rights allow the VMO to be read from and written to /// * The Read and Write rights allow the VMO to be read from and written to
/// directly. /// directly.
/// * The Write right allows resizing a resizable VMO. /// * The Write right allows resizing a resizable VMO.
/// ///
/// VMOs are implemented with two flavors of capabilities: /// VMOs are implemented with two flavors of capabilities:
/// the dynamic one (`Vmo<Rights>`) and the static one (`Vmo<R: TRights>). /// the dynamic one (`Vmo<Rights>`) and the static one (`Vmo<R: TRights>).
/// ///
/// # Examples /// # Examples
/// ///
/// For creating root VMOs, see `VmoOptions`.` /// For creating root VMOs, see `VmoOptions`.`
/// ///
/// For creating child VMOs, see `VmoChildOptions`. /// For creating child VMOs, see `VmoChildOptions`.
/// ///
/// # Implementation /// # Implementation
/// ///
/// `Vmo` provides high-level APIs for address space management by wrapping /// `Vmo` provides high-level APIs for address space management by wrapping
/// around its low-level counterpart `kx_frame::vm::VmFrames`. /// around its low-level counterpart `kx_frame::vm::VmFrames`.
/// Compared with `VmFrames`, /// Compared with `VmFrames`,
/// `Vmo` is easier to use (by offering more powerful APIs) and /// `Vmo` is easier to use (by offering more powerful APIs) and
/// harder to misuse (thanks to its nature of being capability). /// harder to misuse (thanks to its nature of being capability).
/// ///
pub struct Vmo<R>(Arc<Vmo_>, R); pub struct Vmo<R>(Arc<Vmo_>, R);
bitflags! { bitflags! {
@ -80,13 +78,13 @@ bitflags! {
pub struct VmoFlags: u32 { pub struct VmoFlags: u32 {
/// Set this flag if a VMO is resizable. /// Set this flag if a VMO is resizable.
const RESIZABLE = 1 << 0; const RESIZABLE = 1 << 0;
/// Set this flags if a VMO is backed by physically contiguous memory /// Set this flags if a VMO is backed by physically contiguous memory
/// pages. /// pages.
/// ///
/// To ensure the memory pages to be contiguous, these pages /// To ensure the memory pages to be contiguous, these pages
/// are allocated upon the creation of the VMO, rather than on demands. /// are allocated upon the creation of the VMO, rather than on demands.
const CONTIGUOUS = 1 << 1; const CONTIGUOUS = 1 << 1;
/// Set this flag if a VMO is backed by memory pages that supports /// Set this flag if a VMO is backed by memory pages that supports
/// Direct Memory Access (DMA) by devices. /// Direct Memory Access (DMA) by devices.
const DMA = 1 << 2; const DMA = 1 << 2;
} }
@ -94,7 +92,7 @@ bitflags! {
struct Vmo_ { struct Vmo_ {
flags: VmoFlags, flags: VmoFlags,
inner: Mutex<VmoInner>, inner: Mutex<VmoInner>,
parent: Option<Arc<Vmo_>>, parent: Option<Arc<Vmo_>>,
} }
@ -148,7 +146,6 @@ impl Vmo_ {
} }
} }
impl<R> Vmo<R> { impl<R> Vmo<R> {
/// Returns the size (in bytes) of a VMO. /// Returns the size (in bytes) of a VMO.
pub fn size(&self) -> usize { pub fn size(&self) -> usize {
@ -165,5 +162,4 @@ impl<R> Vmo<R> {
pub fn flags(&self) -> VmoFlags { pub fn flags(&self) -> VmoFlags {
self.0.flags() self.0.flags()
} }
}
}

View File

@ -4,43 +4,43 @@ use core::marker::PhantomData;
use core::ops::Range; use core::ops::Range;
use alloc::sync::Arc; use alloc::sync::Arc;
use kxos_frame::vm::Paddr;
use kxos_frame::prelude::Result; use kxos_frame::prelude::Result;
use kxos_frame::vm::Paddr;
use kxos_rights_proc::require; use kxos_rights_proc::require;
use crate::rights::{Dup,TRights,Rights}; use crate::rights::{Dup, Rights, TRights};
use super::{Vmo, VmoFlags, Pager}; use super::{Pager, Vmo, VmoFlags};
/// Options for allocating a root VMO. /// Options for allocating a root VMO.
/// ///
/// # Examples /// # Examples
/// ///
/// Creating a VMO as a _dynamic_ capability with full access rights: /// Creating a VMO as a _dynamic_ capability with full access rights:
/// ``` /// ```
/// use kxo_std::vm::{PAGE_SIZE, VmoOptions}; /// use kxo_std::vm::{PAGE_SIZE, VmoOptions};
/// ///
/// let vmo = VmoOptions::new(PAGE_SIZE) /// let vmo = VmoOptions::new(PAGE_SIZE)
/// .alloc() /// .alloc()
/// .unwrap(); /// .unwrap();
/// ``` /// ```
/// ///
/// Creating a VMO as a _static_ capability with all access rights: /// Creating a VMO as a _static_ capability with all access rights:
/// ``` /// ```
/// use kxos_std::prelude::*; /// use kxos_std::prelude::*;
/// use kxo_std::vm::{PAGE_SIZE, VmoOptions}; /// use kxo_std::vm::{PAGE_SIZE, VmoOptions};
/// ///
/// let vmo = VmoOptions::<Full>::new(PAGE_SIZE) /// let vmo = VmoOptions::<Full>::new(PAGE_SIZE)
/// .alloc() /// .alloc()
/// .unwrap(); /// .unwrap();
/// ``` /// ```
/// ///
/// Creating a resizable VMO backed by 10 memory pages that may not be /// Creating a resizable VMO backed by 10 memory pages that may not be
/// physically contiguous: /// physically contiguous:
/// ///
/// ``` /// ```
/// use kxos_std::vm::{PAGE_SIZE, VmoOptions, VmoFlags}; /// use kxos_std::vm::{PAGE_SIZE, VmoOptions, VmoFlags};
/// ///
/// let vmo = VmoOptions::new(10 * PAGE_SIZE) /// let vmo = VmoOptions::new(10 * PAGE_SIZE)
/// .flags(VmoFlags::RESIZABLE) /// .flags(VmoFlags::RESIZABLE)
/// .alloc() /// .alloc()
@ -55,18 +55,18 @@ pub struct VmoOptions<R = Rights> {
} }
impl<R> VmoOptions<R> { impl<R> VmoOptions<R> {
/// Creates a default set of options with the specified size of the VMO /// Creates a default set of options with the specified size of the VMO
/// (in bytes). /// (in bytes).
/// ///
/// The size of the VMO will be rounded up to align with the page size. /// The size of the VMO will be rounded up to align with the page size.
pub fn new(size: usize) -> Self { pub fn new(size: usize) -> Self {
todo!() todo!()
} }
/// Sets the starting physical address of the VMO. /// Sets the starting physical address of the VMO.
/// ///
/// By default, this option is not set. /// By default, this option is not set.
/// ///
/// If this option is set, then the underlying pages of VMO must be contiguous. /// If this option is set, then the underlying pages of VMO must be contiguous.
/// So `VmoFlags::IS_CONTIGUOUS` will be set automatically. /// So `VmoFlags::IS_CONTIGUOUS` will be set automatically.
pub fn paddr(mut self, paddr: Paddr) -> Self { pub fn paddr(mut self, paddr: Paddr) -> Self {
@ -74,9 +74,9 @@ impl<R> VmoOptions<R> {
} }
/// Sets the VMO flags. /// Sets the VMO flags.
/// ///
/// The default value is `VmoFlags::empty()`. /// The default value is `VmoFlags::empty()`.
/// ///
/// For more information about the flags, see `VmoFlags`. /// For more information about the flags, see `VmoFlags`.
pub fn flags(mut self, flags: VmoFlags) -> Self { pub fn flags(mut self, flags: VmoFlags) -> Self {
todo!() todo!()
@ -90,10 +90,10 @@ impl<R> VmoOptions<R> {
impl VmoOptions<Rights> { impl VmoOptions<Rights> {
/// Allocates the VMO according to the specified options. /// Allocates the VMO according to the specified options.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The VMO is initially assigned full access rights. /// The VMO is initially assigned full access rights.
pub fn alloc(mut self) -> Result<Vmo<Rights>> { pub fn alloc(mut self) -> Result<Vmo<Rights>> {
todo!() todo!()
} }
@ -101,10 +101,10 @@ impl VmoOptions<Rights> {
impl<R: TRights> VmoOptions<R> { impl<R: TRights> VmoOptions<R> {
/// Allocates the VMO according to the specified options. /// Allocates the VMO according to the specified options.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The VMO is initially assigned the access rights represented /// The VMO is initially assigned the access rights represented
/// by `R: TRights`. /// by `R: TRights`.
pub fn alloc(mut self) -> Result<Vmo<R>> { pub fn alloc(mut self) -> Result<Vmo<R>> {
todo!() todo!()
@ -112,14 +112,14 @@ impl<R: TRights> VmoOptions<R> {
} }
/// Options for allocating a child VMO out of a parent VMO. /// Options for allocating a child VMO out of a parent VMO.
/// ///
/// # Examples /// # Examples
/// ///
/// A child VMO created from a parent VMO of _dynamic_ capability is also a /// A child VMO created from a parent VMO of _dynamic_ capability is also a
/// _dynamic_ capability. /// _dynamic_ capability.
/// ``` /// ```
/// use kxo_std::vm::{PAGE_SIZE, VmoOptions}; /// use kxo_std::vm::{PAGE_SIZE, VmoOptions};
/// ///
/// let parent_vmo = VmoOptions::new(PAGE_SIZE) /// let parent_vmo = VmoOptions::new(PAGE_SIZE)
/// .alloc() /// .alloc()
/// .unwrap(); /// .unwrap();
@ -128,13 +128,13 @@ impl<R: TRights> VmoOptions<R> {
/// .unwrap(); /// .unwrap();
/// assert!(parent_vmo.rights() == child_vmo.rights()); /// assert!(parent_vmo.rights() == child_vmo.rights());
/// ``` /// ```
/// ///
/// A child VMO created from a parent VMO of _static_ capability is also a /// A child VMO created from a parent VMO of _static_ capability is also a
/// _static_ capability. /// _static_ capability.
/// ``` /// ```
/// use kxos_std::prelude::*; /// use kxos_std::prelude::*;
/// use kxos_std::vm::{PAGE_SIZE, VmoOptions, VmoChildOptions}; /// use kxos_std::vm::{PAGE_SIZE, VmoOptions, VmoChildOptions};
/// ///
/// let parent_vmo: Vmo<Full> = VmoOptions::new(PAGE_SIZE) /// let parent_vmo: Vmo<Full> = VmoOptions::new(PAGE_SIZE)
/// .alloc() /// .alloc()
/// .unwrap(); /// .unwrap();
@ -143,15 +143,15 @@ impl<R: TRights> VmoOptions<R> {
/// .unwrap(); /// .unwrap();
/// assert!(parent_vmo.rights() == child_vmo.rights()); /// assert!(parent_vmo.rights() == child_vmo.rights());
/// ``` /// ```
/// ///
/// Normally, a child VMO is initially given the same set of access rights /// Normally, a child VMO is initially given the same set of access rights
/// as its parent (as shown above). But there is one exception: /// as its parent (as shown above). But there is one exception:
/// if the child VMO is created as a COW child, then it is granted the Write /// if the child VMO is created as a COW child, then it is granted the Write
/// right regardless of whether the parent is writable or not. /// right regardless of whether the parent is writable or not.
/// ///
/// ``` /// ```
/// use kxo_std::vm::{PAGE_SIZE, VmoOptions, VmoChildOptions}; /// use kxo_std::vm::{PAGE_SIZE, VmoOptions, VmoChildOptions};
/// ///
/// let parent_vmo = VmoOptions::new(PAGE_SIZE) /// let parent_vmo = VmoOptions::new(PAGE_SIZE)
/// .alloc() /// .alloc()
/// .unwrap() /// .unwrap()
@ -162,11 +162,11 @@ impl<R: TRights> VmoOptions<R> {
/// assert!(child_vmo.rights().contains(Rights::WRITE)); /// assert!(child_vmo.rights().contains(Rights::WRITE));
/// ``` /// ```
/// ///
/// The above rule for COW VMO children also applies to static capabilities. /// The above rule for COW VMO children also applies to static capabilities.
/// ///
/// ``` /// ```
/// use kxos_std::vm::{PAGE_SIZE, VmoOptions, VmoChildOptions}; /// use kxos_std::vm::{PAGE_SIZE, VmoOptions, VmoChildOptions};
/// ///
/// let parent_vmo = VmoOptions::<TRights![Read, Dup]>::new(PAGE_SIZE) /// let parent_vmo = VmoOptions::<TRights![Read, Dup]>::new(PAGE_SIZE)
/// .alloc() /// .alloc()
/// .unwrap(); /// .unwrap();
@ -175,14 +175,14 @@ impl<R: TRights> VmoOptions<R> {
/// .unwrap(); /// .unwrap();
/// assert!(child_vmo.rights().contains(Rights::WRITE)); /// assert!(child_vmo.rights().contains(Rights::WRITE));
/// ``` /// ```
/// ///
/// One can set VMO flags for a child VMO. Currently, the only flag that is /// One can set VMO flags for a child VMO. Currently, the only flag that is
/// valid when creating VMO children is `VmoFlags::RESIZABLE`. /// valid when creating VMO children is `VmoFlags::RESIZABLE`.
/// Note that a slice VMO child and its parent cannot not be resizable. /// Note that a slice VMO child and its parent cannot not be resizable.
/// ///
/// ```rust /// ```rust
/// use kxo_std::vm::{PAGE_SIZE, VmoOptions}; /// use kxo_std::vm::{PAGE_SIZE, VmoOptions};
/// ///
/// let parent_vmo = VmoOptions::new(PAGE_SIZE) /// let parent_vmo = VmoOptions::new(PAGE_SIZE)
/// .alloc() /// .alloc()
/// .unwrap(); /// .unwrap();
@ -201,13 +201,13 @@ pub struct VmoChildOptions<R, C> {
marker: PhantomData<C>, marker: PhantomData<C>,
} }
impl<R:TRights> VmoChildOptions<R, VmoSliceChild> { impl<R: TRights> VmoChildOptions<R, VmoSliceChild> {
/// Creates a default set of options for creating a slice VMO child. /// 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 /// 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 /// pages in the parent VMO. In other words, any updates of the parent will
/// reflect on the child, and vice versa. /// reflect on the child, and vice versa.
/// ///
/// The range of a child must be within that of the parent. /// The range of a child must be within that of the parent.
#[require(R > Dup)] #[require(R > Dup)]
pub fn new_slice(parent: Vmo<R>, range: Range<usize>) -> Self { pub fn new_slice(parent: Vmo<R>, range: Range<usize>) -> Self {
@ -222,16 +222,18 @@ impl<R:TRights> VmoChildOptions<R, VmoSliceChild> {
impl VmoChildOptions<Rights, VmoSliceChild> { impl VmoChildOptions<Rights, VmoSliceChild> {
/// Creates a default set of options for creating a slice VMO child. /// Creates a default set of options for creating a slice VMO child.
/// ///
/// User should ensure parent have dup rights, otherwise this function will panic /// 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 /// 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 /// pages in the parent VMO. In other words, any updates of the parent will
/// reflect on the child, and vice versa. /// reflect on the child, and vice versa.
/// ///
/// The range of a child must be within that of the parent. /// The range of a child must be within that of the parent.
pub fn new_slice_rights(parent: Vmo<Rights>, range: Range<usize>) -> Self { 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"); parent
.check_rights(Rights::DUP)
.expect("function new_slice_rights should called with rights Dup");
Self { Self {
flags: parent.flags() & Self::PARENT_FLAGS_MASK, flags: parent.flags() & Self::PARENT_FLAGS_MASK,
parent, parent,
@ -242,38 +244,39 @@ impl VmoChildOptions<Rights, VmoSliceChild> {
} }
impl<R> VmoChildOptions<R, VmoCowChild> { impl<R> VmoChildOptions<R, VmoCowChild> {
/// Creates a default set of options for creating a copy-on-write (COW) /// Creates a default set of options for creating a copy-on-write (COW)
/// VMO child. /// VMO child.
/// ///
/// A COW VMO child behaves as if all its /// A COW VMO child behaves as if all its
/// memory pages are copied from the parent VMO upon creation, although /// memory pages are copied from the parent VMO upon creation, although
/// the copying is done lazily when the parent's memory pages are updated. /// the copying is done lazily when the parent's memory pages are updated.
/// ///
/// The range of a child may go beyond that of the parent. /// The range of a child may go beyond that of the parent.
/// Any pages that are beyond the parent's range are initially all zeros. /// Any pages that are beyond the parent's range are initially all zeros.
pub fn new_cow(parent: Vmo<R>, range: Range<usize>) -> Self { pub fn new_cow(parent: Vmo<R>, range: Range<usize>) -> Self {
Self { Self {
flags: parent.flags() & Self::PARENT_FLAGS_MASK, flags: parent.flags() & Self::PARENT_FLAGS_MASK,
parent, parent,
range, range,
marker: PhantomData, marker: PhantomData,
} }
} }
} }
impl<R, C> VmoChildOptions<R, C> { impl<R, C> VmoChildOptions<R, C> {
/// Flags that a VMO child inherits from its parent. /// Flags that a VMO child inherits from its parent.
pub const PARENT_FLAGS_MASK: VmoFlags = VmoFlags::from_bits(VmoFlags::CONTIGUOUS.bits | VmoFlags::DMA.bits).unwrap(); 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. /// Flags that a VMO child may differ from its parent.
pub const CHILD_FLAGS_MASK: VmoFlags = VmoFlags::RESIZABLE; pub const CHILD_FLAGS_MASK: VmoFlags = VmoFlags::RESIZABLE;
/// Sets the VMO flags. /// Sets the VMO flags.
/// ///
/// Only the flags among `Self::CHILD_FLAGS_MASK` may be set through this /// Only the flags among `Self::CHILD_FLAGS_MASK` may be set through this
/// method. /// method.
/// ///
/// To set `VmoFlags::RESIZABLE`, the child must be COW. /// To set `VmoFlags::RESIZABLE`, the child must be COW.
/// ///
/// The default value is `VmoFlags::empty()`. /// The default value is `VmoFlags::empty()`.
pub fn flags(mut self, flags: VmoFlags) -> Self { pub fn flags(mut self, flags: VmoFlags) -> Self {
self.flags = flags & Self::CHILD_FLAGS_MASK; self.flags = flags & Self::CHILD_FLAGS_MASK;
@ -283,7 +286,7 @@ impl<R, C> VmoChildOptions<R, C> {
impl<C> VmoChildOptions<Rights, C> { impl<C> VmoChildOptions<Rights, C> {
/// Allocates the child VMO. /// Allocates the child VMO.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The child VMO is initially assigned all the parent's access rights. /// The child VMO is initially assigned all the parent's access rights.
@ -294,7 +297,7 @@ impl<C> VmoChildOptions<Rights, C> {
impl<R: TRights> VmoChildOptions<R, VmoSliceChild> { impl<R: TRights> VmoChildOptions<R, VmoSliceChild> {
/// Allocates the child VMO. /// Allocates the child VMO.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The child VMO is initially assigned all the parent's access rights. /// The child VMO is initially assigned all the parent's access rights.
@ -305,14 +308,13 @@ impl<R: TRights> VmoChildOptions<R, VmoSliceChild> {
impl<R: TRights> VmoChildOptions<R, VmoCowChild> { impl<R: TRights> VmoChildOptions<R, VmoCowChild> {
/// Allocates the child VMO. /// Allocates the child VMO.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The child VMO is initially assigned all the parent's access rights /// The child VMO is initially assigned all the parent's access rights
/// plus the Write right. /// plus the Write right.
pub fn alloc<TRights>(mut self) -> Result<Vmo<TRights>> pub fn alloc<TRights>(mut self) -> Result<Vmo<TRights>>
where // TODO: R1 must contain the Write right. To do so at the type level,
// TODO: R1 must contain the Write right. To do so at the type level,
// we need to implement a type-level operator // we need to implement a type-level operator
// (say, `TRightsExtend(L, F)`) // (say, `TRightsExtend(L, F)`)
// that may extend a list (`L`) of type-level flags with an extra flag `F`. // that may extend a list (`L`) of type-level flags with an extra flag `F`.
@ -323,7 +325,7 @@ impl<R: TRights> VmoChildOptions<R, VmoCowChild> {
// original: // original:
// pub fn alloc<R1>(mut self) -> Result<Vmo<R1>> // pub fn alloc<R1>(mut self) -> Result<Vmo<R1>>
// where // where
// // TODO: R1 must contain the Write right. To do so at the type level, // // TODO: R1 must contain the Write right. To do so at the type level,
// // we need to implement a type-level operator // // we need to implement a type-level operator
// // (say, `TRightsExtend(L, F)`) // // (say, `TRightsExtend(L, F)`)

View File

@ -1,58 +1,58 @@
use kxos_frame::vm::VmFrame;
use kxos_frame::prelude::Result; use kxos_frame::prelude::Result;
use kxos_frame::vm::VmFrame;
/// Pagers provide frame to a VMO. /// Pagers provide frame to a VMO.
/// ///
/// A `Pager` object can be attached to a VMO. Whenever the /// A `Pager` object can be attached to a VMO. Whenever the
/// VMO needs more frames (i.e., on commits), it will turn to the pager, /// VMO needs more frames (i.e., on commits), it will turn to the pager,
/// which should then provide frames whose data have been initialized properly. /// which should then provide frames whose data have been initialized properly.
/// Any time a frame is updated through the VMO, the VMO will /// Any time a frame is updated through the VMO, the VMO will
/// notify the attached pager that the frame has been updated. /// notify the attached pager that the frame has been updated.
/// Finally, when a frame is no longer needed (i.e., on decommits), /// Finally, when a frame is no longer needed (i.e., on decommits),
/// the frame pager will also be notified. /// the frame pager will also be notified.
pub trait Pager { pub trait Pager {
/// Ask the pager to provide a frame at a specified offset (in bytes). /// Ask the pager to provide a frame at a specified offset (in bytes).
/// ///
/// After a page of a VMO is committed, the VMO shall not call this method /// After a page of a VMO is committed, the VMO shall not call this method
/// again until the page is decommitted. But a robust implementation of /// again until the page is decommitted. But a robust implementation of
/// `Pager` should not rely on this behavior for its correctness; /// `Pager` should not rely on this behavior for its correctness;
/// instead, it should returns the _same_ frame. /// instead, it should returns the _same_ frame.
/// ///
/// If a VMO page has been previously committed and decommited, /// If a VMO page has been previously committed and decommited,
/// and is to be committed again, then the pager is free to return /// and is to be committed again, then the pager is free to return
/// whatever frame that may or may not be the same as the last time. /// whatever frame that may or may not be the same as the last time.
/// ///
/// It is up to the pager to decide the range of valid offsets. /// It is up to the pager to decide the range of valid offsets.
/// ///
/// The offset will be rounded down to page boundary. /// The offset will be rounded down to page boundary.
fn commit_page(&self, offset: usize) -> Result<VmFrame>; fn commit_page(&self, offset: usize) -> Result<VmFrame>;
/// Notify the pager that the frame at a specified offset (in bytes) /// Notify the pager that the frame at a specified offset (in bytes)
/// has been updated. /// has been updated.
/// ///
/// Being aware of the updates allow the pager (e.g., an inode) to /// Being aware of the updates allow the pager (e.g., an inode) to
/// know which pages are dirty and only write back the _dirty_ pages back /// know which pages are dirty and only write back the _dirty_ pages back
/// to disk. /// to disk.
/// ///
/// The VMO will not call this method for an uncommitted page. /// The VMO will not call this method for an uncommitted page.
/// But a robust implementation of `Pager` should not make /// But a robust implementation of `Pager` should not make
/// such an assumption for its correctness; instead, it should simply ignore the /// such an assumption for its correctness; instead, it should simply ignore the
/// call or return an error. /// call or return an error.
/// ///
/// The offset will be rounded down to page boundary. /// The offset will be rounded down to page boundary.
fn update_page(&self, offset: usize) -> Result<()>; fn update_page(&self, offset: usize) -> Result<()>;
/// Notify the pager that the frame at the specified offset (in bytes) /// Notify the pager that the frame at the specified offset (in bytes)
/// has been decommitted. /// has been decommitted.
/// ///
/// Knowing that a frame is no longer needed, the pager (e.g., an inode) /// Knowing that a frame is no longer needed, the pager (e.g., an inode)
/// can free the frame after writing back its data to the disk. /// can free the frame after writing back its data to the disk.
/// ///
/// The VMO will not call this method for an uncommitted page. /// The VMO will not call this method for an uncommitted page.
/// But a robust implementation of `Pager` should not make /// But a robust implementation of `Pager` should not make
/// such an assumption for its correctness; instead, it should simply ignore the /// such an assumption for its correctness; instead, it should simply ignore the
/// call or return an error. /// call or return an error.
/// ///
/// The offset will be rounded down to page boundary. /// The offset will be rounded down to page boundary.
fn decommit_page(&self, offset: usize) -> Result<()>; fn decommit_page(&self, offset: usize) -> Result<()>;
} }

View File

@ -1,56 +1,62 @@
use core::ops::Range; use core::ops::Range;
use kxos_frame::{vm::VmIo, Error};
use kxos_frame::prelude::Result; use kxos_frame::prelude::Result;
use kxos_frame::{vm::VmIo, Error};
use kxos_rights_proc::require; use kxos_rights_proc::require;
use crate::rights::*; use crate::rights::*;
use super::{Vmo, VmoChildOptions, options::{VmoSliceChild, VmoCowChild}}; use super::{
options::{VmoCowChild, VmoSliceChild},
Vmo, VmoChildOptions,
};
impl<R: TRights> Vmo<R> { impl<R: TRights> Vmo<R> {
/// Creates a new slice VMO through a set of VMO child options. /// Creates a new slice VMO through a set of VMO child options.
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// let parent = VmoOptions::new(PAGE_SIZE).alloc().unwrap(); /// let parent = VmoOptions::new(PAGE_SIZE).alloc().unwrap();
/// let child_size = parent.size(); /// let child_size = parent.size();
/// let child = parent.new_slice_child(0..child_size).alloc().unwrap(); /// let child = parent.new_slice_child(0..child_size).alloc().unwrap();
/// assert!(child.size() == child_size); /// assert!(child.size() == child_size);
/// ``` /// ```
/// ///
/// For more details on the available options, see `VmoChildOptions`. /// For more details on the available options, see `VmoChildOptions`.
/// ///
/// # Access rights /// # Access rights
/// ///
/// This method requires the Dup right. /// This method requires the Dup right.
/// ///
/// The new VMO child will be of the same capability flavor as the parent; /// The new VMO child will be of the same capability flavor as the parent;
/// so are the access rights. /// so are the access rights.
#[require(R > Dup)] #[require(R > Dup)]
pub fn new_slice_child(&self, range: Range<usize>) -> Result<VmoChildOptions<R, VmoSliceChild>> { pub fn new_slice_child(
&self,
range: Range<usize>,
) -> Result<VmoChildOptions<R, VmoSliceChild>> {
let dup_self = self.dup()?; let dup_self = self.dup()?;
Ok(VmoChildOptions::new_slice(dup_self, range)) Ok(VmoChildOptions::new_slice(dup_self, range))
} }
/// Creates a new COW VMO through a set of VMO child options. /// Creates a new COW VMO through a set of VMO child options.
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// let parent = VmoOptions::new(PAGE_SIZE).alloc().unwrap(); /// let parent = VmoOptions::new(PAGE_SIZE).alloc().unwrap();
/// let child_size = 2 * parent.size(); /// let child_size = 2 * parent.size();
/// let child = parent.new_cow_child(0..child_size).alloc().unwrap(); /// let child = parent.new_cow_child(0..child_size).alloc().unwrap();
/// assert!(child.size() == child_size); /// assert!(child.size() == child_size);
/// ``` /// ```
/// ///
/// For more details on the available options, see `VmoChildOptions`. /// For more details on the available options, see `VmoChildOptions`.
/// ///
/// # Access rights /// # Access rights
/// ///
/// This method requires the Dup right. /// This method requires the Dup right.
/// ///
/// The new VMO child will be of the same capability flavor as the parent. /// 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 /// The child will be given the access rights of the parent
/// plus the Write right. /// plus the Write right.
@ -61,62 +67,62 @@ impl<R: TRights> Vmo<R> {
} }
/// Commit the pages specified in the range (in bytes). /// Commit the pages specified in the range (in bytes).
/// ///
/// The range must be within the size of the VMO. /// The range must be within the size of the VMO.
/// ///
/// The start and end addresses will be rounded down and up to page boundaries. /// The start and end addresses will be rounded down and up to page boundaries.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The method requires the Write right. /// The method requires the Write right.
#[require(R > Write)] #[require(R > Write)]
pub fn commit(&self, range: Range<usize>) -> Result<()> { pub fn commit(&self, range: Range<usize>) -> Result<()> {
self.0.commit(range) self.0.commit(range)
} }
/// Decommit the pages specified in the range (in bytes). /// Decommit the pages specified in the range (in bytes).
/// ///
/// The range must be within the size of the VMO. /// The range must be within the size of the VMO.
/// ///
/// The start and end addresses will be rounded down and up to page boundaries. /// The start and end addresses will be rounded down and up to page boundaries.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The method requires the Write right. /// The method requires the Write right.
#[require(R > Write)] #[require(R > Write)]
pub fn decommit(&self, range: Range<usize>) -> Result<()> { pub fn decommit(&self, range: Range<usize>) -> Result<()> {
self.0.decommit(range) self.0.decommit(range)
} }
/// Resize the VMO by giving a new size. /// Resize the VMO by giving a new size.
/// ///
/// The VMO must be resizable. /// The VMO must be resizable.
/// ///
/// The new size will be rounded up to page boundaries. /// The new size will be rounded up to page boundaries.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The method requires the Write right. /// The method requires the Write right.
#[require(R > Write)] #[require(R > Write)]
pub fn resize(&self, new_size: usize) -> Result<()> { pub fn resize(&self, new_size: usize) -> Result<()> {
self.0.resize(new_size) self.0.resize(new_size)
} }
/// Clear the specified range by writing zeros. /// Clear the specified range by writing zeros.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The method requires the Write right. /// The method requires the Write right.
#[require(R > Write)] #[require(R > Write)]
pub fn clear(&self, range: Range<usize>) -> Result<()> { pub fn clear(&self, range: Range<usize>) -> Result<()> {
self.0.clear(range) self.0.clear(range)
} }
/// Duplicate the capability. /// Duplicate the capability.
/// ///
/// # Access rights /// # Access rights
/// ///
/// The method requires the Dup right. /// The method requires the Dup right.
#[require(R > Dup)] #[require(R > Dup)]
pub fn dup(&self) -> Result<Self> { pub fn dup(&self) -> Result<Self> {
todo!() todo!()
@ -140,7 +146,7 @@ impl<R: TRights> Vmo<R> {
fn check_rights(&self, rights: Rights) -> Result<()> { fn check_rights(&self, rights: Rights) -> Result<()> {
if self.rights().contains(rights) { if self.rights().contains(rights) {
Ok(()) Ok(())
} else { } else {
Err(Error::AccessDenied) Err(Error::AccessDenied)
} }
@ -157,4 +163,4 @@ impl<R: TRights> VmIo for Vmo<R> {
self.check_rights(Rights::WRITE)?; self.check_rights(Rights::WRITE)?;
self.0.write_bytes(offset, buf) self.0.write_bytes(offset, buf)
} }
} }

View File

@ -1,12 +1,12 @@
use kxos_frame::Pod; use kxos_frame::Pod;
use kxos_frame_pod_derive::Pod;
use kxos_pci::capability::vendor::virtio::CapabilityVirtioData; use kxos_pci::capability::vendor::virtio::CapabilityVirtioData;
use kxos_pci::util::BAR; use kxos_pci::util::BAR;
use kxos_util::frame_ptr::InFramePtr; use kxos_util::frame_ptr::InFramePtr;
use kxos_frame_pod_derive::Pod;
pub const BLK_SIZE: usize = 512; pub const BLK_SIZE: usize = 512;
#[derive(Debug, Copy, Clone,Pod)] #[derive(Debug, Copy, Clone, Pod)]
#[repr(C)] #[repr(C)]
pub struct VirtioBLKConfig { pub struct VirtioBLKConfig {
capacity: u64, capacity: u64,
@ -25,7 +25,7 @@ pub struct VirtioBLKConfig {
unused1: [u8; 3], unused1: [u8; 3],
} }
#[derive(Debug, Copy, Clone,Pod)] #[derive(Debug, Copy, Clone, Pod)]
#[repr(C)] #[repr(C)]
pub struct VirtioBLKGeometry { pub struct VirtioBLKGeometry {
cylinders: u16, cylinders: u16,
@ -33,7 +33,7 @@ pub struct VirtioBLKGeometry {
sectors: u8, sectors: u8,
} }
#[derive(Debug, Copy, Clone,Pod)] #[derive(Debug, Copy, Clone, Pod)]
#[repr(C)] #[repr(C)]
pub struct VirtioBLKTopology { pub struct VirtioBLKTopology {
physical_block_exp: u8, physical_block_exp: u8,

View File

@ -7,13 +7,12 @@ extern crate alloc;
use alloc::{sync::Arc, vec::Vec}; use alloc::{sync::Arc, vec::Vec};
use bitflags::bitflags; use bitflags::bitflags;
use kxos_frame::{info, offset_of, TrapFrame}; use kxos_frame::{info, offset_of, TrapFrame};
use kxos_frame_pod_derive::Pod;
use kxos_pci::util::{PCIDevice, BAR}; use kxos_pci::util::{PCIDevice, BAR};
use kxos_util::frame_ptr::InFramePtr; use kxos_util::frame_ptr::InFramePtr;
use kxos_frame_pod_derive::Pod;
use spin::{mutex::Mutex, MutexGuard}; use spin::{mutex::Mutex, MutexGuard};
use self::{block::VirtioBLKConfig, queue::VirtQueue}; use self::{block::VirtioBLKConfig, queue::VirtQueue};
use kxos_frame::Pod; use kxos_frame::Pod;
@ -57,7 +56,7 @@ bitflags! {
} }
} }
#[derive(Debug, Default, Copy, Clone,Pod)] #[derive(Debug, Default, Copy, Clone, Pod)]
#[repr(C)] #[repr(C)]
pub struct VitrioPciCommonCfg { pub struct VitrioPciCommonCfg {
device_feature_select: u32, device_feature_select: u32,

View File

@ -6,8 +6,8 @@ use bitflags::bitflags;
use core::sync::atomic::{fence, Ordering}; use core::sync::atomic::{fence, Ordering};
use kxos_frame::offset_of; use kxos_frame::offset_of;
use kxos_frame::Pod; use kxos_frame::Pod;
use kxos_util::frame_ptr::InFramePtr;
use kxos_frame_pod_derive::Pod; use kxos_frame_pod_derive::Pod;
use kxos_util::frame_ptr::InFramePtr;
#[derive(Debug)] #[derive(Debug)]
pub enum QueueError { pub enum QueueError {
InvalidArgs, InvalidArgs,
@ -231,7 +231,7 @@ impl VirtQueue {
} }
#[repr(C, align(16))] #[repr(C, align(16))]
#[derive(Debug, Default, Copy, Clone,Pod)] #[derive(Debug, Default, Copy, Clone, Pod)]
struct Descriptor { struct Descriptor {
addr: u64, addr: u64,
len: u32, len: u32,
@ -274,7 +274,7 @@ impl Default for DescFlags {
/// each ring entry refers to the head of a descriptor chain. /// each ring entry refers to the head of a descriptor chain.
/// It is only written by the driver and read by the device. /// It is only written by the driver and read by the device.
#[repr(C)] #[repr(C)]
#[derive(Debug, Default, Copy, Clone,Pod)] #[derive(Debug, Default, Copy, Clone, Pod)]
struct AvailRing { struct AvailRing {
flags: u16, flags: u16,
/// A driver MUST NOT decrement the idx. /// A driver MUST NOT decrement the idx.
@ -286,7 +286,7 @@ struct AvailRing {
/// The used ring is where the device returns buffers once it is done with them: /// The used ring is where the device returns buffers once it is done with them:
/// it is only written to by the device, and read by the driver. /// it is only written to by the device, and read by the driver.
#[repr(C)] #[repr(C)]
#[derive(Debug, Default, Copy, Clone,Pod)] #[derive(Debug, Default, Copy, Clone, Pod)]
struct UsedRing { struct UsedRing {
flags: u16, flags: u16,
idx: u16, idx: u16,
@ -295,7 +295,7 @@ struct UsedRing {
} }
#[repr(C)] #[repr(C)]
#[derive(Debug, Default, Copy, Clone,Pod)] #[derive(Debug, Default, Copy, Clone, Pod)]
struct UsedElem { struct UsedElem {
id: u32, id: u32,
len: u32, len: u32,

View File

@ -7,8 +7,8 @@ use bootloader::{entry_point, BootInfo};
use kxos_frame::timer::Timer; use kxos_frame::timer::Timer;
extern crate alloc; extern crate alloc;
use alloc::sync::Arc; use alloc::sync::Arc;
use core::time::Duration;
use core::panic::PanicInfo; use core::panic::PanicInfo;
use core::time::Duration;
use kxos_frame::println; use kxos_frame::println;
static mut TICK: usize = 0; static mut TICK: usize = 0;
@ -28,7 +28,9 @@ fn panic(info: &PanicInfo) -> ! {
#[test_case] #[test_case]
fn test_timer() { fn test_timer() {
println!("If you want to pass this test, you may need to enable the interrupt in kxos_frame/lib.rs"); println!(
"If you want to pass this test, you may need to enable the interrupt in kxos_frame/lib.rs"
);
println!("make sure the Timer irq number 32 handler won't panic"); println!("make sure the Timer irq number 32 handler won't panic");
unsafe { unsafe {
let timer = Timer::new(timer_callback).unwrap(); let timer = Timer::new(timer_callback).unwrap();
@ -39,8 +41,8 @@ fn test_timer() {
pub fn timer_callback(timer: Arc<Timer>) { pub fn timer_callback(timer: Arc<Timer>) {
unsafe { unsafe {
TICK+=1; TICK += 1;
println!("TICK:{}",TICK); println!("TICK:{}", TICK);
timer.set(Duration::from_secs(1)); timer.set(Duration::from_secs(1));
} }
} }