pub struct Stack { /* private fields */ }
Expand description
A range of mapped memory designated for use as a task’s stack.
There is an unmapped guard page beneath the stack, which is a standard approach to detect stack overflow.
A stack is backed by and auto-derefs into MappedPages
.
Implementations§
source§impl Stack
impl Stack
sourcepub fn top_unusable(&self) -> VirtualAddress
pub fn top_unusable(&self) -> VirtualAddress
Returns the address just beyond the top of this stack, which is necessary for some hardware registers to use.
This address is not dereferenceable, the one right below it is.
To get the highest usable address in this Stack, call top_usable()
sourcepub fn top_usable(&self) -> VirtualAddress
pub fn top_usable(&self) -> VirtualAddress
Returns the highest usable address of this Stack,
which is top_unusable() - sizeof(VirtualAddress)
sourcepub fn bottom(&self) -> VirtualAddress
pub fn bottom(&self) -> VirtualAddress
Returns the bottom of this stack, its lowest usable address.
sourcepub fn from_pages(
guard_page: AllocatedPages,
stack_pages: MappedPages
) -> Result<Stack, (AllocatedPages, MappedPages)>
pub fn from_pages( guard_page: AllocatedPages, stack_pages: MappedPages ) -> Result<Stack, (AllocatedPages, MappedPages)>
Creates a stack from its constituent parts: a guard page and a series of mapped pages.
Conditions
- The
guard_page
must be at least one page (which is unmapped) and must contiguously precede thestack_pages
. In other words, the beginning ofstack_pages
must come right after the end ofguard_page
. - The
stack_pages
must be mapped as writable.
If the conditions are not met,
an Err
containing the given guard_page
and stack_pages
is returned.
sourcepub fn guard_page(&self) -> &PageRange
pub fn guard_page(&self) -> &PageRange
Returns the guard page(s) for this stack.
Guard pages are virtual pages that are reserved/owned by this stack but are not mapped, causing any access to them to result in a page fault.
Methods from Deref<Target = MappedPages>§
pub fn flags(&self) -> PteFlagsX86_64
pub fn flags(&self) -> PteFlagsX86_64
Returns the flags that describe this MappedPages
page table permissions.
pub fn merge(
&mut self,
mp: MappedPages
) -> Result<(), (&'static str, MappedPages)>
pub fn merge( &mut self, mp: MappedPages ) -> Result<(), (&'static str, MappedPages)>
Merges the given MappedPages
object mp
into this MappedPages
object (self
).
For example, if you have the following MappedPages
objects:
- this mapping, with a page range including one page at 0x2000
mp
, with a page range including two pages at 0x3000 and 0x4000 Then thisMappedPages
object will be updated to cover three pages from[0x2000:0x4000]
inclusive.
In addition, the MappedPages
objects must have the same flags and page table root frame
(i.e., they must have all been mapped using the same set of page tables).
If an error occurs, such as the mappings
not being contiguous or having different flags,
then a tuple including an error message and the original mp
will be returned,
which prevents the mp
from being dropped.
Note
No remapping actions or page reallocations will occur on either a failure or a success.
pub fn deep_copy<F>(
&self,
active_table_mapper: &mut Mapper,
new_flags: Option<F>
) -> Result<MappedPages, &'static str>where
F: Into<PteFlagsX86_64>,
pub fn deep_copy<F>( &self, active_table_mapper: &mut Mapper, new_flags: Option<F> ) -> Result<MappedPages, &'static str>where F: Into<PteFlagsX86_64>,
Creates a deep copy of this MappedPages
memory region,
by duplicating not only the virtual memory mapping
but also the underlying physical memory frames.
The caller can optionally specify new flags for the duplicated mapping,
otherwise, the same flags as the existing MappedPages
will be used.
This is useful for when you want to modify contents in the new pages,
since it avoids extra remap()
operations.
Returns a new MappedPages
object with the same in-memory contents
as this object, but at a completely new memory region.
pub fn remap<F>(
&mut self,
active_table_mapper: &mut Mapper,
new_flags: F
) -> Result<(), &'static str>where
F: Into<PteFlagsX86_64>,
pub fn remap<F>( &mut self, active_table_mapper: &mut Mapper, new_flags: F ) -> Result<(), &'static str>where F: Into<PteFlagsX86_64>,
Change the mapping flags of this MappedPages
’s page table entries.
Note that attempting to change certain “reserved” flags will have no effect.
For example, the EXCLUSIVE
flag cannot be changed beause arbitrarily setting it
would violate safety.
pub fn as_type<T>(&self, byte_offset: usize) -> Result<&T, &'static str>where
T: FromBytes,
pub fn as_type<T>(&self, byte_offset: usize) -> Result<&T, &'static str>where T: FromBytes,
Reinterprets this MappedPages
’s underlying memory region as a struct of the given type T
,
i.e., overlays a struct on top of this mapped memory region.
Requirements
The type T
must implement the FromBytes
trait, which is similar to the requirements
of a “plain old data” type, in that it cannot contain Rust references (&
or &mut
).
This makes sense because there is no valid way to reinterpret a region of untyped memory
as a Rust reference.
In addition, if we did permit that, a Rust reference created from unchecked memory contents
could never be valid, safe, or sound, as it could allow random memory access
(just like with an arbitrary pointer dereference) that could break isolation.
To satisfy this condition, you can use #[derive(FromBytes)]
on your struct type T
,
which will only compile correctly if the struct can be validly constructed
from “untyped” memory, i.e., an array of bytes.
Arguments
byte_offset
: the offset (in number of bytes) from the beginning of the memory region at which the struct is located (where it should start).- This offset must be properly aligned with respect to the alignment requirements
of type
T
, otherwise an error will be returned.
- This offset must be properly aligned with respect to the alignment requirements
of type
Returns a reference to the new struct (&T
) that is formed from the underlying memory region,
with a lifetime dependent upon the lifetime of this MappedPages
object.
This ensures safety by guaranteeing that the returned struct reference
cannot be used after this MappedPages
object is dropped and unmapped.
pub fn as_type_mut<T>(
&mut self,
byte_offset: usize
) -> Result<&mut T, &'static str>where
T: FromBytes,
pub fn as_type_mut<T>( &mut self, byte_offset: usize ) -> Result<&mut T, &'static str>where T: FromBytes,
Same as [MappedPages::as_type()
], but returns a mutable reference to the type T
.
Thus, it also checks that the underlying mapping is writable.
pub fn as_slice<T>(
&self,
byte_offset: usize,
length: usize
) -> Result<&[T], &'static str>where
T: FromBytes,
pub fn as_slice<T>( &self, byte_offset: usize, length: usize ) -> Result<&[T], &'static str>where T: FromBytes,
Reinterprets this MappedPages
’s underlying memory region as &[T]
, a length
-element slice of type T
.
It has similar requirements and behavior as [MappedPages::as_type()
].
Arguments
byte_offset
: the offset (in number of bytes) into the memory region at which the slice should start.- This offset must be properly aligned with respect to the alignment requirements
of type
T
, otherwise an error will be returned.
- This offset must be properly aligned with respect to the alignment requirements
of type
length
: the length of the slice, i.e., the number of elements of typeT
in the slice. Thus, the slice’s address bounds will span the range frombyte_offset
(inclusive) tobyte_offset + (size_of::<T>() * length)
(exclusive).
Returns a reference to the new slice that is formed from the underlying memory region,
with a lifetime dependent upon the lifetime of this MappedPages
object.
This ensures safety by guaranteeing that the returned slice
cannot be used after this MappedPages
object is dropped and unmapped.
Methods from Deref<Target = AllocatedPages<Page4K>>§
pub fn start_address(&self) -> VirtualAddress
pub fn start_address(&self) -> VirtualAddress
Returns the starting VirtualAddress
in this range of pages.
pub fn size_in_bytes(&self) -> usize
pub fn size_in_bytes(&self) -> usize
Returns the size in bytes of this range of pages.
pub fn size_in_pages(&self) -> usize
pub fn size_in_pages(&self) -> usize
Returns the size in number of pages of this range of pages.
pub fn start(&self) -> &Page<P>
pub fn start(&self) -> &Page<P>
Returns the starting Page
in this range of pages.
pub fn end(&self) -> &Page<P>
pub fn end(&self) -> &Page<P>
Returns the ending Page
(inclusive) in this range of pages.
pub fn range(&self) -> &PageRange<P>
pub fn range(&self) -> &PageRange<P>
Returns a reference to the inner PageRange
, which is cloneable/iterable.
pub fn offset_of_address(&self, addr: VirtualAddress) -> Option<usize>
pub fn offset_of_address(&self, addr: VirtualAddress) -> Option<usize>
Returns the offset of the given VirtualAddress
within this range of pages,
i.e., addr - self.start_address()
.
If the given addr
is not covered by this range of pages, this returns None
.
Examples
If the range covers addresses 0x2000
to 0x4000
,
then offset_of_address(0x3500)
would return Some(0x1500)
.
pub fn address_at_offset(&self, offset: usize) -> Option<VirtualAddress>
pub fn address_at_offset(&self, offset: usize) -> Option<VirtualAddress>
Returns the VirtualAddress
at the given offset into this range of pages,
i.e., self.start_address() + offset
.
If the given offset
is not within this range of pages, this returns None
.
Examples
If the range covers addresses 0x2000
through 0x3FFF
,
then address_at_offset(0x1500)
would return Some(0x3500)
,
and address_at_offset(0x2000)
would return None
.