ostd/specs/mm/page_table/node/
entry.rs1use vstd::prelude::*;
2
3use vstd_extra::ghost_tree::*;
4use vstd_extra::ownership::*;
5
6use crate::mm::frame::meta::mapping::frame_to_index;
7use crate::mm::page_table::*;
8use crate::specs::arch::mm::NR_ENTRIES;
9use crate::specs::mm::frame::meta_owners::REF_COUNT_UNUSED;
10use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
11use crate::specs::mm::page_table::*;
12
13verus! {
14
15impl<'rcu, C: PageTableConfig> Entry<'rcu, C> {
16 pub open spec fn invariants(self, owner: EntryOwner<C>, regions: MetaRegionOwners) -> bool {
17 &&& owner.inv()
18 &&& regions.inv()
19 &&& self.wf(owner)
20 &&& owner.relate_region(regions)
21 }
22
23 pub open spec fn node_matching(self, owner: EntryOwner<C>, parent_owner: NodeOwner<C>, guard_perm: GuardPerm<'rcu, C>) -> bool {
24 &&& parent_owner.level == owner.parent_level
25 &&& parent_owner.inv()
26 &&& guard_perm.addr() == self.node.addr()
27 &&& guard_perm.is_init()
28 &&& guard_perm.value().inner.inner@.ptr.addr() == parent_owner.meta_perm.addr()
29 &&& guard_perm.value().inner.inner@.ptr.addr() == parent_owner.meta_perm.points_to.addr()
30 &&& guard_perm.value().inner.inner@.wf(parent_owner)
31 &&& parent_owner.meta_perm.is_init()
32 &&& parent_owner.meta_perm.wf(&parent_owner.meta_perm.inner_perms)
33 &&& owner.match_pte(parent_owner.children_perm.value()[self.idx as int], owner.parent_level)
34 }
35
36 pub open spec fn relate_region_preserved(regions0: MetaRegionOwners, regions1: MetaRegionOwners) -> bool {
37 OwnerSubtree::implies(
38 |entry: EntryOwner<C>, path: TreePath<NR_ENTRIES>| entry.relate_region(regions0),
39 |entry: EntryOwner<C>, path: TreePath<NR_ENTRIES>| entry.relate_region(regions1),
40 )
41 }
42
43 pub open spec fn replace_panic_condition(
44 parent_owner: NodeOwner<C>,
45 new_owner: EntryOwner<C>,
46 ) -> bool {
47 if new_owner.is_node() {
48 parent_owner.level - 1 == new_owner.node.unwrap().level
49 } else if new_owner.is_frame() {
50 parent_owner.level == new_owner.parent_level
51 } else {
52 true
53 }
54 }
55
56 pub open spec fn relate_region_neq_preserved(
57 old_entry_owner: EntryOwner<C>,
58 new_entry_owner: EntryOwner<C>,
59 regions0: MetaRegionOwners,
60 regions1: MetaRegionOwners,
61 ) -> bool {
62 OwnerSubtree::implies(
63 |entry: EntryOwner<C>, path: TreePath<NR_ENTRIES>|
64 entry.meta_slot_paddr_neq(old_entry_owner)
65 && entry.meta_slot_paddr_neq(new_entry_owner)
66 && entry.relate_region(regions0),
67 |entry: EntryOwner<C>, path: TreePath<NR_ENTRIES>|
68 entry.relate_region(regions1),
69 )
70 }
71
72 pub open spec fn path_tracked_pred_preserved(regions0: MetaRegionOwners, regions1: MetaRegionOwners) -> bool {
73 OwnerSubtree::implies(
74 PageTableOwner::<C>::path_tracked_pred(regions0),
75 PageTableOwner::<C>::path_tracked_pred(regions1),
76 )
77 }
78
79 pub open spec fn new_owner_compatible(self,
80 new_child: Child<C>,
81 old_owner: EntryOwner<C>,
82 new_owner: EntryOwner<C>,
83 regions: MetaRegionOwners)
84 -> bool {
85 &&& old_owner.path == new_owner.path
86 &&& old_owner.parent_level == new_owner.parent_level
87 &&& old_owner.meta_slot_paddr_neq(new_owner)
88 &&& new_owner.in_scope
89 &&& new_owner.is_node() ==> {
90 &&& regions.slots.contains_key(frame_to_index(new_owner.meta_slot_paddr().unwrap()))
91 &&& regions.slot_owners[frame_to_index(new_owner.meta_slot_paddr().unwrap())].inner_perms.ref_count.value() !=
92 REF_COUNT_UNUSED
93 }
94 }
95
96 pub open spec fn parent_perms_preserved(self,
97 parent_owner0: NodeOwner<C>,
98 parent_owner1: NodeOwner<C>,
99 guard_perm0: GuardPerm<'rcu, C>,
100 guard_perm1: GuardPerm<'rcu, C>)
101 -> bool {
102 &&& guard_perm0.addr() == guard_perm1.addr()
103 &&& guard_perm0.value().inner.inner@.ptr.addr() == guard_perm1.value().inner.inner@.ptr.addr()
104 &&& forall|i: int| 0 <= i < NR_ENTRIES ==> i != self.idx ==>
105 parent_owner0.children_perm.value()[i] == parent_owner1.children_perm.value()[i]
106 }
107}
108
109}