#[repr(transparent)]pub struct Frame<M: AnyFrameMeta> {
pub ptr: PPtr<MetaSlot>,
pub _marker: PhantomData<M>,
}Expand description
A smart pointer to a frame.
A frame is a contiguous range of bytes in physical memory. The Frame
type is a smart pointer to a frame that is reference-counted.
Frames are associated with metadata. The type of the metadata M is
determines the kind of the frame. If M implements [AnyUFrameMeta], the
frame is a untyped frame. Otherwise, it is a typed frame.
Fields§
§ptr: PPtr<MetaSlot>§_marker: PhantomData<M>Implementations§
Source§impl<M: AnyFrameMeta> Frame<M>
impl<M: AnyFrameMeta> Frame<M>
Sourcepub exec fn meta_pt<'a, C: PageTableConfig>(
&'a self,
verus_tmp_p_slot: Tracked<&'a PointsTo<MetaSlot>>,
owner: MetaSlotOwner,
) -> res : &'a PageTablePageMeta<C>
pub exec fn meta_pt<'a, C: PageTableConfig>( &'a self, verus_tmp_p_slot: Tracked<&'a PointsTo<MetaSlot>>, owner: MetaSlotOwner, ) -> res : &'a PageTablePageMeta<C>
self.inv(),p_slot.pptr() == self.ptr,p_slot.is_init(),p_slot.value().wf(owner),is_variant(owner.view().storage.value(), "PTNode"),Source§impl<'a, M: AnyFrameMeta> Frame<M>
impl<'a, M: AnyFrameMeta> Frame<M>
Sourcepub open spec fn from_unused_requires(
regions: MetaRegionOwners,
paddr: Paddr,
metadata: M,
) -> bool
pub open spec fn from_unused_requires( regions: MetaRegionOwners, paddr: Paddr, metadata: M, ) -> bool
{
&&& paddr % PAGE_SIZE() == 0
&&& paddr < MAX_PADDR()
&&& regions.slots.contains_key(frame_to_index(paddr))
&&& regions.slot_owners[frame_to_index(paddr)].usage is Unused
&&& regions.slot_owners[frame_to_index(paddr)].in_list.points_to(0)
&&& regions.slot_owners[frame_to_index(paddr)].self_addr == frame_to_meta(paddr)
&&& regions.inv()
}Sourcepub open spec fn from_unused_ensures(
old_regions: MetaRegionOwners,
new_regions: MetaRegionOwners,
paddr: Paddr,
metadata: M,
r: Self,
) -> bool
pub open spec fn from_unused_ensures( old_regions: MetaRegionOwners, new_regions: MetaRegionOwners, paddr: Paddr, metadata: M, r: Self, ) -> bool
{
&&& new_regions@
== MetaSlot::get_from_unused_spec::<M>(paddr, metadata, false, old_regions@).1
&&& new_regions.inv()
&&& forall |paddr: Paddr| {
#[trigger] old_regions.slots.contains_key(frame_to_index(paddr))
==> new_regions.slots.contains_key(frame_to_index(paddr))
}
}Sourcepub exec fn from_unused(paddr: Paddr, metadata: M) -> r : Result<Self, GetFrameError>
pub exec fn from_unused(paddr: Paddr, metadata: M) -> r : Result<Self, GetFrameError>
Tracked(regions): Tracked <& mut MetaRegionOwners>,requiresSelf::from_unused_requires(*old(regions), paddr, metadata),ensuresr matches Ok(
r,
) ==> Self::from_unused_ensures(*old(regions), *regions, paddr, metadata, r),Gets a Frame with a specific usage from a raw, unused page.
The caller should provide the initial metadata of the page.
If the provided frame is not truly unused at the moment, it will return
an error. If wanting to acquire a frame that is already in use, use
Frame::from_in_use instead.
Source§impl<M: AnyFrameMeta> Frame<M>
impl<M: AnyFrameMeta> Frame<M>
Sourcepub exec fn from_in_use(paddr: Paddr) -> Result<Self, GetFrameError>
pub exec fn from_in_use(paddr: Paddr) -> Result<Self, GetFrameError>
Tracked(regions): Tracked <& mut MetaRegionOwners>,Gets a dynamically typed Frame from a raw, in-use page.
If the provided frame is not in use at the moment, it will return an error.
The returned frame will have an extra reference count to the frame.
Sourcepub open spec fn from_raw_requires(regions: MetaRegionOwners, paddr: Paddr) -> bool
pub open spec fn from_raw_requires(regions: MetaRegionOwners, paddr: Paddr) -> bool
{
&&& paddr % PAGE_SIZE() == 0
&&& !regions.slots.contains_key(frame_to_index(paddr))
&&& regions.dropped_slots.contains_key(frame_to_index(paddr))
&&& regions.inv()
}Sourcepub open spec fn from_raw_ensures(
old_regions: MetaRegionOwners,
new_regions: MetaRegionOwners,
paddr: Paddr,
r: Self,
) -> bool
pub open spec fn from_raw_ensures( old_regions: MetaRegionOwners, new_regions: MetaRegionOwners, paddr: Paddr, r: Self, ) -> bool
{
&&& new_regions.inv()
&&& new_regions.slots.contains_key(frame_to_index(paddr))
&&& !new_regions.dropped_slots.contains_key(frame_to_index(paddr))
&&& new_regions.slots[frame_to_index(paddr)]
== old_regions.dropped_slots[frame_to_index(paddr)]
&&& forall |i: usize| {
i != frame_to_index(paddr) ==> new_regions.slots[i] == old_regions.slots[i]
}
&&& forall |i: usize| {
i != frame_to_index(paddr)
==> new_regions.dropped_slots[i] == old_regions.dropped_slots[i]
}
&&& new_regions.slot_owners == old_regions.slot_owners
&&& r.ptr == new_regions.slots[frame_to_index(paddr)].pptr()
&&& r.paddr() == paddr
}Sourcepub open spec fn into_raw_requires(self, regions: MetaRegionOwners) -> bool
pub open spec fn into_raw_requires(self, regions: MetaRegionOwners) -> bool
{
&&& regions.slots.contains_key(self.index())
&&& !regions.dropped_slots.contains_key(self.index())
&&& regions.inv()
}Sourcepub open spec fn into_raw_ensures(
self,
regions: MetaRegionOwners,
r: Paddr,
perm: MetaPerm<M>,
) -> bool
pub open spec fn into_raw_ensures( self, regions: MetaRegionOwners, r: Paddr, perm: MetaPerm<M>, ) -> bool
{
&&& r == meta_to_frame(self.ptr.addr())
&&& regions.slot_owners == regions.slot_owners
&&& regions.dropped_slots == regions.dropped_slots
&&& forall |i: usize| {
i != frame_to_index(self.ptr.addr()) ==> regions.slots[i] == regions.slots[i]
}
}Source§impl<'a, M: AnyFrameMeta> Frame<M>
impl<'a, M: AnyFrameMeta> Frame<M>
Sourcepub exec fn start_paddr(&self) -> Paddr
pub exec fn start_paddr(&self) -> Paddr
Tracked(perm): Tracked <& vstd ::simple_pptr ::PointsTo <MetaSlot>>,requiresperm.addr() == self.ptr.addr(),perm.is_init(),FRAME_METADATA_RANGE().start <= perm.addr() < FRAME_METADATA_RANGE().end,perm.addr() % META_SLOT_SIZE() == 0,Gets the physical address of the start of the frame.
Sourcepub const exec fn map_level(&self) -> PagingLevel
pub const exec fn map_level(&self) -> PagingLevel
Gets the map level of this page.
This is the level of the page table entry that maps the frame, which determines the size of the frame.
Currently, the level is always 1, which means the frame is a regular page frame.
Sourcepub exec fn reference_count(&self) -> u64
pub exec fn reference_count(&self) -> u64
Tracked(slot_own): Tracked <& mut MetaSlotOwner>,
Tracked(slot_perm): Tracked <& vstd ::simple_pptr ::PointsTo <MetaSlot>>,requiresslot_perm.pptr() == self.ptr,slot_perm.is_init(),old(slot_own).ref_count.is_for(slot_perm.value().ref_count),Gets the reference count of the frame.
It returns the number of all references to the frame, including all the
existing frame handles (Frame, Frame<dyn AnyFrameMeta>), and all
the mappings in the page table that points to the frame.
§Safety
The function is safe to call, but using it requires extra care. The reference count can be changed by other threads at any time including potentially between calling this method and acting on the result.
Sourcepub exec fn borrow(&self) -> res : FrameRef<'a, M>
pub exec fn borrow(&self) -> res : FrameRef<'a, M>
Tracked(regions): Tracked <& mut MetaRegionOwners>,
Tracked(perm): Tracked <& MetaPerm <M>>,requiresold(regions).inv(),self.paddr() % PAGE_SIZE() == 0,self.paddr() < MAX_PADDR(),!old(regions).slots.contains_key(self.index()),perm.points_to.pptr() == self.ptr,perm.is_init(),FRAME_METADATA_RANGE().start <= perm.points_to.addr() < FRAME_METADATA_RANGE().end,perm.points_to.addr() % META_SLOT_SIZE() == 0,ensuresregions.inv(),res.inner@.ptr.addr() == self.ptr.addr(),Borrows a reference from the given frame.
Sourcepub exec fn into_raw(self) -> r : Paddr
pub exec fn into_raw(self) -> r : Paddr
Tracked(regions): Tracked <& mut MetaRegionOwners>,
->
frame_perm: Tracked <MetaPerm <M>>,requiresSelf::into_raw_requires(self, *old(regions)),ensuresSelf::into_raw_ensures(self, *regions, r, frame_perm@),Forgets the handle to the frame.
This will result in the frame being leaked without calling the custom dropper.
A physical address to the frame is returned in case the frame needs to be
restored using Frame::from_raw later. This is useful when some architectural
data structures need to hold the frame handle such as the page table.
Sourcepub exec fn from_raw(paddr: Paddr) -> r : Self
pub exec fn from_raw(paddr: Paddr) -> r : Self
Tracked(regions): Tracked <& mut MetaRegionOwners>,
Tracked(perm): Tracked <& MetaPerm <M>>,requiresSelf::from_raw_requires(*old(regions), paddr),ensuresSelf::from_raw_ensures(*old(regions), *regions, paddr, r),Restores a forgotten Frame from a physical address.
§Safety
The caller should only restore a Frame that was previously forgotten using
Frame::into_raw.
And the restoring operation should only be done once for a forgotten
Frame. Otherwise double-free will happen.
Also, the caller ensures that the usage of the frame is correct. There’s no checking of the usage in this function.
Source§impl<C: PageTableConfig> Frame<PageTablePageMeta<C>>
impl<C: PageTableConfig> Frame<PageTablePageMeta<C>>
Sourcepub exec fn level(&self) -> PagingLevel
pub exec fn level(&self) -> PagingLevel
Tracked(perm): Tracked <& PointsTo <MetaSlot,PageTablePageMeta <C>>>,requiresself.ptr.addr() == perm.addr(),self.ptr.addr() == perm.points_to.addr(),perm.is_init(),perm.wf(),Sourcepub exec fn alloc(level: PagingLevel) -> res : Self
pub exec fn alloc(level: PagingLevel) -> res : Self
Tracked(regions): Tracked <& mut MetaRegionOwners>,
->
owner: Tracked <OwnerSubtree <C>>,requireslevel <= NR_LEVELS(),old(regions).inv(),ensuresregions.inv(),Allocates a new empty page table node.
Source§impl<M: AnyFrameMeta + Repr<MetaSlot> + OwnerOf> Frame<M>
impl<M: AnyFrameMeta + Repr<MetaSlot> + OwnerOf> Frame<M>
Sourcepub open spec fn from_raw_spec(paddr: Paddr) -> Self
pub open spec fn from_raw_spec(paddr: Paddr) -> Self
{
Frame::<M> {
ptr: PPtr::<MetaSlot>(frame_to_meta(paddr), PhantomData),
_marker: PhantomData,
}
}Trait Implementations§
Source§impl<M: AnyFrameMeta> Clone for Frame<M>
impl<M: AnyFrameMeta> Clone for Frame<M>
Source§impl<M: AnyFrameMeta> Inv for Frame<M>
impl<M: AnyFrameMeta> Inv for Frame<M>
Source§impl<M: AnyFrameMeta> Repr<MetaSlot> for Frame<M>
impl<M: AnyFrameMeta> Repr<MetaSlot> for Frame<M>
Source§open spec fn to_repr_spec(self) -> MetaSlot
open spec fn to_repr_spec(self) -> MetaSlot
{ arbitrary() }Source§open spec fn from_repr_spec(r: MetaSlot) -> Self
open spec fn from_repr_spec(r: MetaSlot) -> Self
{ arbitrary() }Source§exec fn from_borrowed<'a>(r: &'a MetaSlot) -> res : &'a Self
exec fn from_borrowed<'a>(r: &'a MetaSlot) -> res : &'a Self
*res == Self::from_repr_spec(*r),Source§proof fn from_to_repr(self)
proof fn from_to_repr(self)
Self::from_repr(self.to_repr()) == self,Source§proof fn to_from_repr(r: MetaSlot)
proof fn to_from_repr(r: MetaSlot)
Self::from_repr(r).to_repr() == r,Source§proof fn to_repr_wf(self)
proof fn to_repr_wf(self)
Self::wf(self.to_repr()),Source§impl<M: AnyFrameMeta> Undroppable for Frame<M>
impl<M: AnyFrameMeta> Undroppable for Frame<M>
Source§open spec fn constructor_requires(self, s: Self::State) -> bool
open spec fn constructor_requires(self, s: Self::State) -> bool
{
&&& s.slots.contains_key(frame_to_index(meta_to_frame(self.ptr.addr())))
&&& !s.dropped_slots.contains_key(frame_to_index(meta_to_frame(self.ptr.addr())))
&&& s.inv()
}Source§open spec fn constructor_ensures(self, s0: Self::State, s1: Self::State) -> bool
open spec fn constructor_ensures(self, s0: Self::State, s1: Self::State) -> bool
{
&&& !s1.slots.contains_key(frame_to_index(meta_to_frame(self.ptr.addr())))
&&& s1.dropped_slots.contains_key(frame_to_index(meta_to_frame(self.ptr.addr())))
&&& s0.slot_owners == s1.slot_owners
&&& forall |i: usize| {
i != frame_to_index(meta_to_frame(self.ptr.addr()))
==> s0.dropped_slots[i] == s1.dropped_slots[i] && s0.slots[i] == s1.slots[i]
}
&&& s1.dropped_slots[frame_to_index(meta_to_frame(self.ptr.addr()))]
== s0.slots[frame_to_index(meta_to_frame(self.ptr.addr()))]
&&& s1.inv()
}