ostd/specs/mm/page_table/node/
child.rs1use vstd::prelude::*;
2
3use vstd_extra::ownership::*;
4
5use crate::mm::frame::*;
6use crate::mm::page_prop::PageProperty;
7use crate::mm::page_table::*;
8use crate::mm::{Paddr, PagingConstsTrait, PagingLevel, Vaddr};
9use crate::specs::arch::mm::{NR_ENTRIES, NR_LEVELS, PAGE_SIZE};
10use crate::specs::arch::paging_consts::PagingConsts;
11use crate::specs::mm::frame::meta_owners::MetaSlotOwner;
12use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
13
14verus! {
15
16impl<C: PageTableConfig> OwnerOf for Child<C> {
17 type Owner = EntryOwner<C>;
18
19 open spec fn wf(self, owner: Self::Owner) -> bool {
20 match self {
21 Self::PageTable(node) => {
22 &&& owner.is_node()
23 &&& node.ptr.addr() == owner.node.unwrap().meta_addr_self()
24 &&& node.index() == frame_to_index(meta_to_frame(node.ptr.addr()))
25 },
26 Self::Frame(paddr, level, prop) => {
27 &&& owner.is_frame()
28 &&& owner.frame.unwrap().mapped_pa == paddr
29 &&& owner.frame.unwrap().prop == prop
30 &&& level == owner.parent_level
31 },
32 Self::None => owner.is_absent(),
33 }
34 }
35}
36
37impl<'a, C: PageTableConfig> OwnerOf for ChildRef<'a, C> {
38 type Owner = EntryOwner<C>;
39
40 open spec fn wf(self, owner: Self::Owner) -> bool {
41 match self {
42 Self::PageTable(node) => {
43 &&& owner.is_node()
44 &&& node.inner.0.ptr.addr() == owner.node.unwrap().meta_addr_self()
45 },
46 Self::Frame(paddr, level, prop) => {
47 &&& owner.is_frame()
48 &&& owner.frame.unwrap().mapped_pa == paddr
49 &&& owner.frame.unwrap().prop == prop
50 },
51 Self::None => owner.is_absent(),
52 }
53 }
54}
55
56impl<C: PageTableConfig> Child<C> {
57 pub open spec fn get_node(self) -> Option<PageTableNode<C>> {
58 match self {
59 Self::PageTable(node) => Some(node),
60 _ => None,
61 }
62 }
63
64 pub open spec fn get_frame_tuple(self) -> Option<(Paddr, PagingLevel, PageProperty)> {
65 match self {
66 Self::Frame(paddr, level, prop) => Some((paddr, level, prop)),
67 _ => None,
68 }
69 }
70
71 pub open spec fn into_pte_frame_spec(self, tuple: (Paddr, PagingLevel, PageProperty)) -> C::E {
72 let (paddr, level, prop) = tuple;
73 C::E::new_page_spec(paddr, level, prop)
74 }
75
76 pub open spec fn into_pte_none_spec(self) -> C::E {
77 C::E::new_absent_spec()
78 }
79
80 pub open spec fn from_pte_spec(
81 pte: C::E,
82 level: PagingLevel,
83 regions: MetaRegionOwners,
84 ) -> Self {
85 if !pte.is_present() {
86 Self::None
87 } else if pte.is_last(level) {
88 Self::Frame(pte.paddr(), level, pte.prop())
89 } else {
90 Self::PageTable(PageTableNode::from_raw_spec(pte.paddr()))
91 }
92 }
93
94 pub open spec fn from_pte_frame_spec(pte: C::E, level: PagingLevel) -> Self {
95 Self::Frame(pte.paddr(), level, pte.prop())
96 }
97
98 pub open spec fn from_pte_pt_spec(paddr: Paddr, regions: MetaRegionOwners) -> Self {
99 Self::PageTable(PageTableNode::from_raw_spec(paddr))
100 }
101
102 pub open spec fn invariants(self, owner: EntryOwner<C>, regions: MetaRegionOwners) -> bool {
103 &&& owner.inv_base()
104 &&& regions.inv()
105 &&& self.wf(owner)
106 &&& owner.metaregion_sound(regions)
107 &&& owner.in_scope
108 }
109}
110
111impl<C: PageTableConfig> ChildRef<'_, C> {
112 pub open spec fn invariants(self, owner: EntryOwner<C>, regions: MetaRegionOwners) -> bool {
113 &&& owner.inv()
114 &&& regions.inv()
115 &&& self.wf(owner)
116 &&& owner.metaregion_sound(regions)
117 &&& !owner.in_scope
118 }
119}
120
121impl<C: PageTableConfig> EntryOwner<C> {
122 pub open spec fn from_pte_regions_spec(self, regions: MetaRegionOwners) -> MetaRegionOwners {
123 if self.is_node() {
124 let index = frame_to_index(self.meta_slot_paddr().unwrap());
125 MetaRegionOwners {
126 frame_obligations: regions.frame_obligations.insert(index),
127 ..regions
128 }
129 } else {
130 regions
131 }
132 }
133
134 pub open spec fn into_pte_regions_spec(self, regions: MetaRegionOwners) -> MetaRegionOwners {
135 if self.is_node() {
136 let index = frame_to_index(self.meta_slot_paddr().unwrap());
137 MetaRegionOwners {
144 frame_obligations: regions.frame_obligations.remove(index),
145 ..regions
146 }
147 } else {
148 regions
151 }
152 }
153
154 pub open spec fn into_pte_owner_spec(self) -> EntryOwner<C> {
155 EntryOwner { in_scope: false, ..self }
156 }
157
158 pub open spec fn from_pte_owner_spec(self) -> EntryOwner<C> {
159 EntryOwner { in_scope: true, ..self }
160 }
161
162 pub open spec fn pte_invariants(self, pte: C::E, regions: MetaRegionOwners) -> bool {
165 &&& self.inv()
166 &&& regions.inv()
167 &&& self.match_pte(pte, self.parent_level)
168 &&& self.metaregion_sound(regions)
169 &&& !self.in_scope
170 }
171}
172
173}