pub struct VmSpace {
pt: PageTable<UserPtConfig>,
cpus: AtomicCpuSet,
}Expand description
A virtual address space for user-mode tasks, enabling safe manipulation of user-space memory.
The VmSpace type provides memory isolation guarantees between user-space and
kernel-space. For example, given an arbitrary user-space pointer, one can read and
write the memory location referred to by the user-space pointer without the risk of
breaking the memory safety of the kernel space.
§Task Association Semantics
As far as OSTD is concerned, a VmSpace is not necessarily associated with a task. Once a
VmSpace is activated (see VmSpace::activate), it remains activated until another
VmSpace is activated possibly by another task running on the same CPU.
This means that it’s up to the kernel to ensure that a task’s VmSpace is always activated
while the task is running. This can be done by using the injected post schedule handler
(see inject_post_schedule_handler) to always activate the correct VmSpace after each
context switch.
If the kernel otherwise decides not to ensure that the running task’s VmSpace is always
activated, the kernel must deal with race conditions when calling methods that require the
VmSpace to be activated, e.g., UserMode::execute, VmSpace::reader,
VmSpace::writer. Otherwise, the behavior is unspecified, though it’s guaranteed not to
compromise the kernel’s memory safety.
§Memory Backing
A newly-created VmSpace is not backed by any physical memory pages. To
provide memory pages for a VmSpace, one can allocate and map physical
memory (UFrames) to the VmSpace using the cursor.
A VmSpace can also attach a page fault handler, which will be invoked to
handle page faults generated from user space.
Fields§
§pt: PageTable<UserPtConfig>§cpus: AtomicCpuSetImplementations§
Source§impl VmSpace
impl VmSpace
Sourcepub fn cursor<'a, G: AsAtomicModeGuard>(
&'a self,
guard: &'a G,
va: &Range<Vaddr>,
) -> Result<Cursor<'a>>
pub fn cursor<'a, G: AsAtomicModeGuard>( &'a self, guard: &'a G, va: &Range<Vaddr>, ) -> Result<Cursor<'a>>
Gets an immutable cursor in the virtual address range.
The cursor behaves like a lock guard, exclusively owning a sub-tree of the page table, preventing others from creating a cursor in it. So be sure to drop the cursor as soon as possible.
The creation of the cursor may block if another cursor having an overlapping range is alive.
Sourcepub fn cursor_mut<'a, G: AsAtomicModeGuard>(
&'a self,
guard: &'a G,
va: &Range<Vaddr>,
) -> Result<CursorMut<'a>>
pub fn cursor_mut<'a, G: AsAtomicModeGuard>( &'a self, guard: &'a G, va: &Range<Vaddr>, ) -> Result<CursorMut<'a>>
Gets an mutable cursor in the virtual address range.
The same as Self::cursor, the cursor behaves like a lock guard,
exclusively owning a sub-tree of the page table, preventing others
from creating a cursor in it. So be sure to drop the cursor as soon as
possible.
The creation of the cursor may block if another cursor having an overlapping range is alive. The modification to the mapping by the cursor may also block or be overridden the mapping of another cursor.
Sourcepub fn reader(&self, vaddr: Vaddr, len: usize) -> Result<VmReader<'_, Fallible>>
pub fn reader(&self, vaddr: Vaddr, len: usize) -> Result<VmReader<'_, Fallible>>
Creates a reader to read data from the user space of the current task.
Returns Err if this VmSpace is not belonged to the user space of the current task
or the vaddr and len do not represent a user space memory range.
Users must ensure that no other page table is activated in the current task during the
lifetime of the created VmReader. This guarantees that the VmReader can operate correctly.
Sourcepub fn writer(&self, vaddr: Vaddr, len: usize) -> Result<VmWriter<'_, Fallible>>
pub fn writer(&self, vaddr: Vaddr, len: usize) -> Result<VmWriter<'_, Fallible>>
Creates a writer to write data into the user space.
Returns Err if this VmSpace is not belonged to the user space of the current task
or the vaddr and len do not represent a user space memory range.
Users must ensure that no other page table is activated in the current task during the
lifetime of the created VmWriter. This guarantees that the VmWriter can operate correctly.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for VmSpace
impl !RefUnwindSafe for VmSpace
impl Send for VmSpace
impl Sync for VmSpace
impl Unpin for VmSpace
impl !UnwindSafe for VmSpace
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.§impl<T> Pointee for T
impl<T> Pointee for T
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.