Struct memory::MappedPages
source · pub struct MappedPages { /* private fields */ }
Expand description
Represents a contiguous range of virtual memory pages that are currently mapped.
A MappedPages
object can only have a single range of contiguous pages, not multiple disjoint ranges.
This does not guarantee that its pages are mapped to frames that are contiguous in physical memory.
This object also represents ownership of those pages; if this object falls out of scope, it will be dropped, and the pages will be unmapped and then also de-allocated. Thus, it ensures memory safety by guaranteeing that this object must be held in order to access data stored in these mapped pages, much like a guard type.
Implementations§
source§impl MappedPages
impl MappedPages
sourcepub const fn empty() -> MappedPages
pub const fn empty() -> MappedPages
Returns an empty MappedPages object that performs no allocation or mapping actions. Can be used as a placeholder, but will not permit any real usage.
sourcepub fn flags(&self) -> PteFlagsArch
pub fn flags(&self) -> PteFlagsArch
Returns the flags that describe this MappedPages
page table permissions.
sourcepub 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.
sourcepub fn split(
self,
at_page: Page
) -> Result<(MappedPages, MappedPages), MappedPages>
pub fn split(
self,
at_page: Page
) -> Result<(MappedPages, MappedPages), MappedPages>
Splits this MappedPages
into two separate MappedPages
objects:
[beginning : at_page - 1]
[at_page : end]
This function follows the behavior of core::slice::split_at()
,
thus, either one of the returned MappedPages
objects may be empty.
- If
at_page == self.pages.start
, the first returnedMappedPages
object will be empty. - If
at_page == self.pages.end + 1
, the second returnedMappedPages
object will be empty.
Returns an Err
containing this MappedPages
(self
) if at_page
is not within its bounds.
Note
No remapping actions or page reallocations will occur on either a failure or a success.
sourcepub fn deep_copy<F: Into<PteFlagsArch>>(
&self,
active_table_mapper: &mut Mapper,
new_flags: Option<F>
) -> Result<MappedPages, &'static str>
pub fn deep_copy<F: Into<PteFlagsArch>>(
&self,
active_table_mapper: &mut Mapper,
new_flags: Option<F>
) -> Result<MappedPages, &'static str>
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.
sourcepub fn remap<F: Into<PteFlagsArch>>(
&mut self,
active_table_mapper: &mut Mapper,
new_flags: F
) -> Result<(), &'static str>
pub fn remap<F: Into<PteFlagsArch>>(
&mut self,
active_table_mapper: &mut Mapper,
new_flags: F
) -> Result<(), &'static str>
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.
sourcepub fn unmap_into_parts(
self,
active_table_mapper: &mut Mapper
) -> Result<(AllocatedPages, Option<AllocatedFrames>), Self>
pub fn unmap_into_parts(
self,
active_table_mapper: &mut Mapper
) -> Result<(AllocatedPages, Option<AllocatedFrames>), Self>
Consumes and unmaps this MappedPages
object without auto-deallocating its AllocatedPages
and AllocatedFrames
,
allowing the caller to continue using them directly, e.g., reusing them for a future mapping.
This removes the need to attempt to to reallocate those same pages or frames on a separate code path.
Note that only the first contiguous range of AllocatedFrames
will be returned, if any were unmapped.
All other non-contiguous ranges will be auto-dropped and deallocated.
This is due to how frame deallocation works.
sourcepub fn as_type<T: FromBytes>(
&self,
byte_offset: usize
) -> Result<&T, &'static str>
pub fn as_type<T: FromBytes>(
&self,
byte_offset: usize
) -> Result<&T, &'static str>
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 typeT
, otherwise an error will be returned.
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.
sourcepub fn as_type_mut<T: FromBytes>(
&mut self,
byte_offset: usize
) -> Result<&mut T, &'static str>
pub fn as_type_mut<T: FromBytes>(
&mut self,
byte_offset: usize
) -> Result<&mut T, &'static str>
Same as MappedPages::as_type()
, but returns a mutable reference to the type T
.
Thus, it also checks that the underlying mapping is writable.
sourcepub fn as_slice<T: FromBytes>(
&self,
byte_offset: usize,
length: usize
) -> Result<&[T], &'static str>
pub fn as_slice<T: FromBytes>(
&self,
byte_offset: usize,
length: usize
) -> Result<&[T], &'static str>
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 typeT
, otherwise an error will be returned.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.
sourcepub fn as_slice_mut<T: FromBytes>(
&mut self,
byte_offset: usize,
length: usize
) -> Result<&mut [T], &'static str>
pub fn as_slice_mut<T: FromBytes>(
&mut self,
byte_offset: usize,
length: usize
) -> Result<&mut [T], &'static str>
Same as MappedPages::as_slice()
, but returns a mutable slice.
Thus, it checks that the underlying mapping is writable.
sourcepub fn into_borrowed<T: FromBytes>(
self,
byte_offset: usize
) -> Result<BorrowedMappedPages<T, Immutable>, (MappedPages, &'static str)>
pub fn into_borrowed<T: FromBytes>(
self,
byte_offset: usize
) -> Result<BorrowedMappedPages<T, Immutable>, (MappedPages, &'static str)>
A convenience function for BorrowedMappedPages::from()
.
sourcepub fn into_borrowed_mut<T: FromBytes>(
self,
byte_offset: usize
) -> Result<BorrowedMappedPages<T, Mutable>, (MappedPages, &'static str)>
pub fn into_borrowed_mut<T: FromBytes>(
self,
byte_offset: usize
) -> Result<BorrowedMappedPages<T, Mutable>, (MappedPages, &'static str)>
A convenience function for BorrowedMappedPages::from_mut()
.
sourcepub fn into_borrowed_slice<T: FromBytes>(
self,
byte_offset: usize,
length: usize
) -> Result<BorrowedSliceMappedPages<T, Immutable>, (MappedPages, &'static str)>
pub fn into_borrowed_slice<T: FromBytes>(
self,
byte_offset: usize,
length: usize
) -> Result<BorrowedSliceMappedPages<T, Immutable>, (MappedPages, &'static str)>
A convenience function for BorrowedSliceMappedPages::from()
.
sourcepub fn into_borrowed_slice_mut<T: FromBytes>(
self,
byte_offset: usize,
length: usize
) -> Result<BorrowedSliceMappedPages<T, Mutable>, (MappedPages, &'static str)>
pub fn into_borrowed_slice_mut<T: FromBytes>(
self,
byte_offset: usize,
length: usize
) -> Result<BorrowedSliceMappedPages<T, Mutable>, (MappedPages, &'static str)>
A convenience function for BorrowedSliceMappedPages::from_mut()
.
Methods from Deref<Target = PageRange>§
pub fn start_address(&self) -> VirtualAddress
pub fn start_address(&self) -> VirtualAddress
Returns the VirtualAddress
of the starting Page
in this PageRange
.
pub fn size_in_pages(&self) -> usize
pub fn size_in_pages(&self) -> usize
Returns the number of Page
s covered by this iterator.
Use this instead of Iterator::count()
method. This is instant, because it doesn’t need to iterate over each entry, unlike normal iterators.
pub fn size_in_bytes(&self) -> usize
pub fn size_in_bytes(&self) -> usize
Returns the size of this range in number of bytes.
pub fn contains_address(&self, addr: VirtualAddress) -> bool
pub fn contains_address(&self, addr: VirtualAddress) -> bool
Returns true
if this PageRange
contains the given VirtualAddress
.
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 PageRange
, i.e., addr - self.start_address()
.
If the given addr
is not covered by this range of Page
s, 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 PageRange
within this PageRange
, i.e., addr - self.start_address()
.
If the given offset
is not within this range of Page
s, this returns None
.
Examples
If the range covers addresses 0x2000
to 0x4000
, then address_at_offset(0x1500)
would return Some(0x3500)
.
pub fn to_extended(&self, to_include: Page) -> PageRange
pub fn to_extended(&self, to_include: Page) -> PageRange
Returns a new separate PageRange
that is extended to include the given Page
.
Methods from Deref<Target = RangeInclusive<Page>>§
1.27.0 · sourcepub fn start(&self) -> &Idx
pub fn start(&self) -> &Idx
Returns the lower bound of the range (inclusive).
When using an inclusive range for iteration, the values of start()
and
end()
are unspecified after the iteration ended. To determine
whether the inclusive range is empty, use the is_empty()
method
instead of comparing start() > end()
.
Note: the value returned by this method is unspecified after the range has been iterated to exhaustion.
Examples
assert_eq!((3..=5).start(), &3);
1.27.0 · sourcepub fn end(&self) -> &Idx
pub fn end(&self) -> &Idx
Returns the upper bound of the range (inclusive).
When using an inclusive range for iteration, the values of start()
and end()
are unspecified after the iteration ended. To determine
whether the inclusive range is empty, use the is_empty()
method
instead of comparing start() > end()
.
Note: the value returned by this method is unspecified after the range has been iterated to exhaustion.
Examples
assert_eq!((3..=5).end(), &5);
1.35.0 · sourcepub fn contains<U>(&self, item: &U) -> boolwhere
Idx: PartialOrd<U>,
U: PartialOrd<Idx> + ?Sized,
pub fn contains<U>(&self, item: &U) -> boolwhere
Idx: PartialOrd<U>,
U: PartialOrd<Idx> + ?Sized,
Returns true
if item
is contained in the range.
Examples
assert!(!(3..=5).contains(&2));
assert!( (3..=5).contains(&3));
assert!( (3..=5).contains(&4));
assert!( (3..=5).contains(&5));
assert!(!(3..=5).contains(&6));
assert!( (3..=3).contains(&3));
assert!(!(3..=2).contains(&3));
assert!( (0.0..=1.0).contains(&1.0));
assert!(!(0.0..=1.0).contains(&f32::NAN));
assert!(!(0.0..=f32::NAN).contains(&0.0));
assert!(!(f32::NAN..=1.0).contains(&1.0));
This method always returns false
after iteration has finished:
let mut r = 3..=5;
assert!(r.contains(&3) && r.contains(&5));
for _ in r.by_ref() {}
// Precise field values are unspecified here
assert!(!r.contains(&3) && !r.contains(&5));
1.47.0 · sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true
if the range contains no items.
Examples
assert!(!(3..=5).is_empty());
assert!(!(3..=3).is_empty());
assert!( (3..=2).is_empty());
The range is empty if either side is incomparable:
assert!(!(3.0..=5.0).is_empty());
assert!( (3.0..=f32::NAN).is_empty());
assert!( (f32::NAN..=5.0).is_empty());
This method returns true
after iteration has finished:
let mut r = 3..=5;
for _ in r.by_ref() {}
// Precise field values are unspecified here
assert!(r.is_empty());