ostd/specs/mm/page_table/node/
owners.rs1use vstd::prelude::*;
2
3use vstd::cell;
4use vstd::simple_pptr::*;
5
6use crate::mm::frame::meta::MetaSlot;
7use crate::mm::paddr_to_vaddr;
8use crate::mm::page_table::*;
9use crate::mm::{Paddr, PagingConstsTrait, PagingLevel, Vaddr};
10use crate::specs::arch::kspace::{
11 FRAME_METADATA_RANGE, LINEAR_MAPPING_BASE_VADDR, VMALLOC_BASE_VADDR,
12};
13use crate::specs::arch::mm::{
14 CONST_NR_ENTRIES, MAX_NR_PAGES, MAX_PADDR, NR_ENTRIES, NR_LEVELS, PAGE_SIZE,
15};
16use crate::specs::arch::paging_consts::PagingConsts;
17use crate::specs::mm::frame::mapping::{meta_to_frame, frame_to_index, META_SLOT_SIZE};
18use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
19use crate::specs::mm::page_table::GuardPerm;
20
21use vstd_extra::array_ptr;
22use vstd_extra::cast_ptr::Repr;
23use vstd_extra::ownership::*;
24use vstd_extra::ghost_tree::TreePath;
25
26verus! {
27
28pub tracked struct PageMetaOwner {
29 pub nr_children: vstd::cell::PointsTo<u16>,
30 pub stray: vstd::cell::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: vstd_extra::cast_ptr::PointsTo<MetaSlot, PageTablePageMeta<C>>,
78 pub children_perm: array_ptr::PointsTo<C::E, CONST_NR_ENTRIES>,
79 pub level: PagingLevel,
80 pub path: TreePath<CONST_NR_ENTRIES>,
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 &&& <PageTablePageMeta<C> as Repr<MetaSlot>>::wf(self.meta_perm.points_to.value())
87 &&& self.meta_perm.addr() == self.meta_perm.points_to.addr()
88 &&& self.meta_own.inv()
89 &&& self.meta_perm.value().wf(self.meta_own)
90 &&& self.meta_perm.is_init()
91 &&& self.meta_perm.wf()
92 &&& FRAME_METADATA_RANGE().start <= self.meta_perm.addr() < FRAME_METADATA_RANGE().end
93 &&& self.meta_perm.addr() % META_SLOT_SIZE() == 0
94 &&& meta_to_frame(self.meta_perm.addr()) < VMALLOC_BASE_VADDR() - LINEAR_MAPPING_BASE_VADDR()
95 &&& meta_to_frame(self.meta_perm.addr()) < MAX_PADDR()
96 &&& meta_to_frame(self.meta_perm.addr()) == self.children_perm.addr()
97 &&& self.meta_own.nr_children.id() == self.meta_perm.value().nr_children.id()
98 &&& 0 <= self.meta_own.nr_children.value() <= NR_ENTRIES()
99 &&& 1 <= self.level <= NR_LEVELS()
100 &&& self.children_perm.is_init_all()
101 &&& self.children_perm.addr() == paddr_to_vaddr(meta_to_frame(self.meta_perm.addr()))
102 }
103}
104
105impl<'rcu, C: PageTableConfig> NodeOwner<C> {
106 pub open spec fn relate_guard_perm(self, guard_perm: GuardPerm<'rcu, C>) -> bool {
107 &&& guard_perm.is_init()
108 &&& guard_perm.value().inner.inner@.ptr.addr() == self.meta_perm.addr()
109 &&& guard_perm.value().inner.inner@.ptr.addr() == self.meta_perm.points_to.addr()
110 &&& guard_perm.value().inner.inner@.wf(self)
111 &&& self.meta_perm.is_init()
112 &&& self.meta_perm.wf()
113 }
114
115 pub open spec fn relate_region(self, regions: MetaRegionOwners) -> bool {
117 &&& !regions.slots.contains_key(frame_to_index(meta_to_frame(self.meta_perm.addr())))
118 &&& regions.slot_owners[frame_to_index(meta_to_frame(self.meta_perm.addr()))].path_if_in_pt == Some(self.path)
119 }
120}
121
122pub ghost struct NodeModel<C: PageTableConfig> {
123 pub meta: PageTablePageMeta<C>,
124}
125
126impl<C: PageTableConfig> Inv for NodeModel<C> {
127 open spec fn inv(self) -> bool {
128 true
129 }
130}
131
132impl<C: PageTableConfig> View for NodeOwner<C> {
133 type V = NodeModel<C>;
134
135 open spec fn view(&self) -> <Self as View>::V {
136 NodeModel { meta: self.meta_perm.value() }
137 }
138}
139
140impl<C: PageTableConfig> InvView for NodeOwner<C> {
141 proof fn view_preserves_inv(self) {
142 }
143}
144
145impl<C: PageTableConfig> OwnerOf for PageTableNode<C> {
146 type Owner = NodeOwner<C>;
147
148 open spec fn wf(self, owner: Self::Owner) -> bool {
149 &&& self.ptr.addr() == owner.meta_perm.addr()
150 }
151}
152
153}