ostd/specs/mm/page_table/node/
owners.rs1use vstd::cell::pcell_maybe_uninit;
2use vstd::prelude::*;
3
4use vstd::cell;
5use vstd::simple_pptr::*;
6
7use crate::mm::frame::meta::MetaSlot;
8use crate::mm::kspace::{LINEAR_MAPPING_BASE_VADDR, VMALLOC_BASE_VADDR};
9use crate::mm::paddr_to_vaddr;
10use crate::mm::page_table::*;
11use crate::mm::{Paddr, PagingConstsTrait, PagingLevel, Vaddr};
12use crate::specs::arch::kspace::FRAME_METADATA_RANGE;
13use crate::specs::arch::mm::{MAX_NR_PAGES, MAX_PADDR, NR_ENTRIES, NR_LEVELS, PAGE_SIZE};
14use crate::specs::arch::paging_consts::PagingConsts;
15use crate::specs::mm::frame::mapping::{frame_to_index, meta_to_frame, META_SLOT_SIZE};
16use crate::specs::mm::frame::meta_owners::*;
17use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
18use crate::specs::mm::page_table::owners::INC_LEVELS;
19use crate::specs::mm::page_table::GuardPerm;
20
21use vstd_extra::array_ptr;
22use vstd_extra::cast_ptr::Repr;
23use vstd_extra::ghost_tree::TreePath;
24use vstd_extra::ownership::*;
25
26verus! {
27
28pub tracked struct PageMetaOwner {
29 pub nr_children: pcell_maybe_uninit::PointsTo<u16>,
30 pub stray: pcell_maybe_uninit::PointsTo<bool>,
31}
32
33impl Inv for PageMetaOwner {
34 open spec fn inv(self) -> bool {
35 &&& self.nr_children.is_init()
36 &&& 0 <= self.nr_children.value() <= NR_ENTRIES
37 &&& self.stray.is_init()
38 }
39}
40
41pub ghost struct PageMetaModel {
42 pub nr_children: u16,
43 pub stray: bool,
44}
45
46impl Inv for PageMetaModel {
47 open spec fn inv(self) -> bool {
48 true
49 }
50}
51
52impl View for PageMetaOwner {
53 type V = PageMetaModel;
54
55 open spec fn view(&self) -> <Self as View>::V {
56 PageMetaModel { nr_children: self.nr_children.value(), stray: self.stray.value() }
57 }
58}
59
60impl InvView for PageMetaOwner {
61 proof fn view_preserves_inv(self) {
62 }
63}
64
65impl<C: PageTableConfig> OwnerOf for PageTablePageMeta<C> {
66 type Owner = PageMetaOwner;
67
68 open spec fn wf(self, owner: Self::Owner) -> bool {
69 &&& self.nr_children.id() == owner.nr_children.id()
70 &&& self.stray.id() == owner.stray.id()
71 &&& 0 <= owner.nr_children.value() <= NR_ENTRIES
72 }
73}
74
75pub tracked struct NodeOwner<C: PageTableConfig> {
76 pub meta_own: PageMetaOwner,
77 pub meta_perm: MetaPerm<PageTablePageMeta<C>>,
78 pub children_perm: array_ptr::PointsTo<C::E, NR_ENTRIES>,
79 pub level: PagingLevel,
80 pub tree_level: int,
81}
82
83impl<C: PageTableConfig> Inv for NodeOwner<C> {
84 open spec fn inv(self) -> bool {
85 &&& self.meta_perm.points_to.is_init()
86 &&& self.meta_perm.addr() == self.meta_perm.points_to.addr()
87 &&& self.meta_own.inv()
88 &&& self.meta_perm.value().metadata.wf(self.meta_own)
89 &&& self.meta_perm.is_init()
90 &&& self.meta_perm.wf(&self.meta_perm.inner_perms)
91 &&& FRAME_METADATA_RANGE.start <= self.meta_perm.addr() < FRAME_METADATA_RANGE.end
92 &&& self.meta_perm.addr() % META_SLOT_SIZE == 0
93 &&& meta_to_frame(self.meta_perm.addr()) < VMALLOC_BASE_VADDR - LINEAR_MAPPING_BASE_VADDR
94 &&& meta_to_frame(self.meta_perm.addr()) < MAX_PADDR
95 &&& meta_to_frame(self.meta_perm.addr()) == self.children_perm.addr()
96 &&& self.meta_own.nr_children.id() == self.meta_perm.value().metadata.nr_children.id()
97 &&& 0 <= self.meta_own.nr_children.value() <= NR_ENTRIES
98 &&& 1 <= self.level <= NR_LEVELS
99 &&& self.children_perm.is_init_all()
100 &&& self.children_perm.addr() == paddr_to_vaddr(meta_to_frame(self.meta_perm.addr()))
101 &&& self.level == self.meta_perm.value().metadata.level
102 &&& self.tree_level == INC_LEVELS - self.level
103 }
104}
105
106impl<C: PageTableConfig> NodeOwner<C> {
107 pub uninterp spec fn set_children_perm(self, idx: usize, pte: C::E) -> Self;
110
111 #[verifier::external_body]
112 pub axiom fn set_children_perm_axiom(self, idx: usize, pte: C::E)
113 requires
114 self.inv(),
115 idx < NR_ENTRIES,
116 ensures
117 self.set_children_perm(idx, pte).inv(),
118 self.set_children_perm(idx, pte).meta_perm == self.meta_perm,
119 self.set_children_perm(idx, pte).meta_own == self.meta_own,
120 self.set_children_perm(idx, pte).level == self.level,
121 self.set_children_perm(idx, pte).tree_level == self.tree_level,
122 self.set_children_perm(idx, pte).children_perm.addr() == self.children_perm.addr(),
123 self.set_children_perm(idx, pte).children_perm.value()
124 == self.children_perm.value().update(idx as int, pte);
125}
126
127impl<'rcu, C: PageTableConfig> NodeOwner<C> {
128
129 pub open spec fn relate_guard_perm(self, guard_perm: GuardPerm<'rcu, C>) -> bool {
130 &&& guard_perm.is_init()
131 &&& guard_perm.value().inner.inner@.ptr.addr() == self.meta_perm.addr()
132 &&& guard_perm.value().inner.inner@.ptr.addr() == self.meta_perm.points_to.addr()
133 &&& guard_perm.value().inner.inner@.wf(self)
134 &&& self.meta_perm.is_init()
135 &&& self.meta_perm.wf(&self.meta_perm.inner_perms)
136 }
137}
138
139pub ghost struct NodeModel<C: PageTableConfig> {
140 pub meta: PageTablePageMeta<C>,
141}
142
143impl<C: PageTableConfig> Inv for NodeModel<C> {
144 open spec fn inv(self) -> bool {
145 true
146 }
147}
148
149impl<C: PageTableConfig> View for NodeOwner<C> {
150 type V = NodeModel<C>;
151
152 open spec fn view(&self) -> <Self as View>::V {
153 NodeModel { meta: self.meta_perm.value().metadata }
154 }
155}
156
157impl<C: PageTableConfig> InvView for NodeOwner<C> {
158 proof fn view_preserves_inv(self) {
159 }
160}
161
162impl<C: PageTableConfig> OwnerOf for PageTableNode<C> {
163 type Owner = NodeOwner<C>;
164
165 open spec fn wf(self, owner: Self::Owner) -> bool {
166 &&& self.ptr.addr() == owner.meta_perm.addr()
167 }
168}
169
170impl<C: PageTableConfig> PageTableNode<C> {
171 pub open spec fn invariants(self, owner: NodeOwner<C>) -> bool {
172 &&& owner.inv()
173 &&& self.wf(owner)
174}
178}
179
180}