pub struct Entry<'rcu, C: PageTableConfig> {
pub pte: C::E,
pub idx: usize,
pub node: PPtr<PageTableGuard<'rcu, C>>,
}Fields§
§pte: C::EThe page table entry.
We store the page table entry here to optimize the number of reads from
the node. We cannot hold a &mut E reference to the entry because that
other CPUs may modify the memory location for accessed/dirty bits. Such
accesses will violate the aliasing rules of Rust and cause undefined
behaviors.
§Verification Design
The concrete value of a PTE is specific to the architecture and the page table configuration,
represented by the type C::E. We represent its value as an abstract EntryOwner, which is
connected to the concrete value by match_pte. The EntryOwner is well-formed with respect to
Entry if it is related to the concrete value by match_pte.
An Entry can be thought of as a mutable handle to the concrete value of the PTE.
The node field points (with a level of indirection) to the node that contains the entry,
index provides the offset, and the pte is current value. Only one Entry can exist for
a given node at any given time.
idx: usizeThe index of the entry in the node.
node: PPtr<PageTableGuard<'rcu, C>>The node that contains the entry. In the original Rust this is a &mut PageTableGuard; the PPtr
type is handling the mutable reference because Verus does not yet support storing such a reference
in a struct.
Implementations§
Source§impl<'rcu, C: PageTableConfig> Entry<'rcu, C>
impl<'rcu, C: PageTableConfig> Entry<'rcu, C>
Sourcepub open spec fn new_spec(
pte: C::E,
idx: usize,
node: PPtr<PageTableGuard<'rcu, C>>,
) -> Self
pub open spec fn new_spec( pte: C::E, idx: usize, node: PPtr<PageTableGuard<'rcu, C>>, ) -> Self
{ Self { pte, idx, node } }Sourcepub exec fn new(pte: C::E, idx: usize, node: PPtr<PageTableGuard<'rcu, C>>) -> Self
pub exec fn new(pte: C::E, idx: usize, node: PPtr<PageTableGuard<'rcu, C>>) -> Self
Source§impl<'rcu, C: PageTableConfig> Entry<'rcu, C>
impl<'rcu, C: PageTableConfig> Entry<'rcu, C>
Sourcepub open spec fn invariants(self, owner: EntryOwner<C>, regions: MetaRegionOwners) -> bool
pub open spec fn invariants(self, owner: EntryOwner<C>, regions: MetaRegionOwners) -> bool
{
&&& owner.inv()
&&& regions.inv()
&&& self.wf(owner)
&&& owner.relate_region(regions)
}Sourcepub open spec fn node_matching(
self,
owner: EntryOwner<C>,
parent_owner: NodeOwner<C>,
guard_perm: GuardPerm<'rcu, C>,
) -> bool
pub open spec fn node_matching( self, owner: EntryOwner<C>, parent_owner: NodeOwner<C>, guard_perm: GuardPerm<'rcu, C>, ) -> bool
{
&&& parent_owner.level == owner.parent_level
&&& parent_owner.inv()
&&& guard_perm.addr() == self.node.addr()
&&& guard_perm.is_init()
&&& guard_perm.value().inner.inner@.ptr.addr() == parent_owner.meta_perm.addr()
&&& guard_perm.value().inner.inner@.ptr.addr()
== parent_owner.meta_perm.points_to.addr()
&&& guard_perm.value().inner.inner@.wf(parent_owner)
&&& parent_owner.meta_perm.is_init()
&&& parent_owner.meta_perm.wf(&parent_owner.meta_perm.inner_perms)
&&& owner
.match_pte(
parent_owner.children_perm.value()[self.idx as int],
owner.parent_level,
)
}Sourcepub open spec fn relate_region_preserved(
regions0: MetaRegionOwners,
regions1: MetaRegionOwners,
) -> bool
pub open spec fn relate_region_preserved( regions0: MetaRegionOwners, regions1: MetaRegionOwners, ) -> bool
{
OwnerSubtree::implies(
|entry: EntryOwner<C>, path: TreePath<NR_ENTRIES>| entry.relate_region(regions0),
|entry: EntryOwner<C>, path: TreePath<NR_ENTRIES>| entry.relate_region(regions1),
)
}Sourcepub open spec fn replace_panic_condition(
parent_owner: NodeOwner<C>,
new_owner: EntryOwner<C>,
) -> bool
pub open spec fn replace_panic_condition( parent_owner: NodeOwner<C>, new_owner: EntryOwner<C>, ) -> bool
{
if new_owner.is_node() {
parent_owner.level - 1 == new_owner.node.unwrap().level
} else if new_owner.is_frame() {
parent_owner.level == new_owner.parent_level
} else {
true
}
}Sourcepub open spec fn relate_region_neq_preserved(
old_entry_owner: EntryOwner<C>,
new_entry_owner: EntryOwner<C>,
regions0: MetaRegionOwners,
regions1: MetaRegionOwners,
) -> bool
pub open spec fn relate_region_neq_preserved( old_entry_owner: EntryOwner<C>, new_entry_owner: EntryOwner<C>, regions0: MetaRegionOwners, regions1: MetaRegionOwners, ) -> bool
{
OwnerSubtree::implies(
|entry: EntryOwner<C>, path: TreePath<NR_ENTRIES>| {
entry.meta_slot_paddr_neq(old_entry_owner)
&& entry.meta_slot_paddr_neq(new_entry_owner)
&& entry.relate_region(regions0)
},
|entry: EntryOwner<C>, path: TreePath<NR_ENTRIES>| entry.relate_region(regions1),
)
}Sourcepub open spec fn path_tracked_pred_preserved(
regions0: MetaRegionOwners,
regions1: MetaRegionOwners,
) -> bool
pub open spec fn path_tracked_pred_preserved( regions0: MetaRegionOwners, regions1: MetaRegionOwners, ) -> bool
{
OwnerSubtree::implies(
PageTableOwner::<C>::path_tracked_pred(regions0),
PageTableOwner::<C>::path_tracked_pred(regions1),
)
}Sourcepub open spec fn new_owner_compatible(
self,
new_child: Child<C>,
old_owner: EntryOwner<C>,
new_owner: EntryOwner<C>,
regions: MetaRegionOwners,
) -> bool
pub open spec fn new_owner_compatible( self, new_child: Child<C>, old_owner: EntryOwner<C>, new_owner: EntryOwner<C>, regions: MetaRegionOwners, ) -> bool
{
&&& old_owner.path == new_owner.path
&&& old_owner.parent_level == new_owner.parent_level
&&& old_owner.meta_slot_paddr_neq(new_owner)
&&& new_owner.in_scope
&&& new_owner.is_node()
==> {
&&& regions
.slots
.contains_key(frame_to_index(new_owner.meta_slot_paddr().unwrap()))
&&& regions
.slot_owners[frame_to_index(new_owner.meta_slot_paddr().unwrap())]
.inner_perms
.ref_count
.value() != REF_COUNT_UNUSED
}
}Sourcepub open spec fn parent_perms_preserved(
self,
parent_owner0: NodeOwner<C>,
parent_owner1: NodeOwner<C>,
guard_perm0: GuardPerm<'rcu, C>,
guard_perm1: GuardPerm<'rcu, C>,
) -> bool
pub open spec fn parent_perms_preserved( self, parent_owner0: NodeOwner<C>, parent_owner1: NodeOwner<C>, guard_perm0: GuardPerm<'rcu, C>, guard_perm1: GuardPerm<'rcu, C>, ) -> bool
{
&&& guard_perm0.addr() == guard_perm1.addr()
&&& guard_perm0.value().inner.inner@.ptr.addr()
== guard_perm1.value().inner.inner@.ptr.addr()
&&& forall |i: int| {
0 <= i < NR_ENTRIES
==> (i != self.idx
==> parent_owner0.children_perm.value()[i]
== parent_owner1.children_perm.value()[i])
}
}Trait Implementations§
Source§impl<'rcu, C: PageTableConfig> OwnerOf for Entry<'rcu, C>
impl<'rcu, C: PageTableConfig> OwnerOf for Entry<'rcu, C>
Source§open spec fn wf(self, owner: Self::Owner) -> bool
open spec fn wf(self, owner: Self::Owner) -> bool
{
&&& self.idx < NR_ENTRIES
&&& owner.match_pte(self.pte, owner.parent_level)
&&& self.pte.paddr() % PAGE_SIZE == 0
&&& self.pte.paddr() < MAX_PADDR
}Source§type Owner = EntryOwner<C>
type Owner = EntryOwner<C>
Inv, indicating that it must
has a consistent state.