1use vstd::prelude::*;
4
5use vstd::simple_pptr::{self, PPtr, PointsTo};
6
7use vstd_extra::cast_ptr;
8use vstd_extra::drop_tracking::ManuallyDrop;
9use vstd_extra::ghost_tree::*;
10use vstd_extra::ownership::*;
11
12use crate::mm::frame::meta::mapping::{frame_to_index, frame_to_meta, meta_to_frame};
13use crate::mm::frame::{Frame, FrameRef};
14use crate::mm::page_table::*;
15use crate::mm::{Paddr, PagingConstsTrait, PagingLevel, Vaddr};
16use crate::specs::arch::mm::{NR_ENTRIES, NR_LEVELS, PAGE_SIZE};
17use crate::specs::arch::paging_consts::PagingConsts;
18use crate::specs::mm::frame::meta_owners::{MetaSlotOwner, REF_COUNT_UNUSED};
19use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
20use crate::specs::mm::page_table::{PageTableOwner, INC_LEVELS};
21use crate::specs::task::InAtomicMode;
22
23use core::marker::PhantomData;
24use core::ops::Deref;
25
26use crate::{
27 mm::{nr_subpage_per_huge, page_prop::PageProperty},
28 };
31
32use super::*;
33
34verus! {
35
36pub type PageTableNodeRef<'a, C> = FrameRef<'a, PageTablePageMeta<C>>;
38
39pub struct PageTableGuard<'rcu, C: PageTableConfig> {
41 pub inner: PageTableNodeRef<'rcu, C>,
42}
43
44impl<'rcu, C: PageTableConfig> Deref for PageTableGuard<'rcu, C> {
45 type Target = PageTableNodeRef<'rcu, C>;
46
47 #[verus_spec(ensures returns self.inner)]
48 fn deref(&self) -> &Self::Target {
49 &self.inner
50 }
51}
52
53pub struct Entry<'rcu, C: PageTableConfig> {
54 pub pte: C::E,
73 pub idx: usize,
75 pub node: PPtr<PageTableGuard<'rcu, C>>,
79}
80
81impl<'rcu, C: PageTableConfig> Entry<'rcu, C> {
82 pub open spec fn new_spec(pte: C::E, idx: usize, node: PPtr<PageTableGuard<'rcu, C>>) -> Self {
83 Self { pte, idx, node }
84 }
85
86 #[verifier::when_used_as_spec(new_spec)]
87 pub fn new(pte: C::E, idx: usize, node: PPtr<PageTableGuard<'rcu, C>>) -> Self {
88 Self { pte, idx, node }
89 }
90}
91
92#[verus_verify]
93impl<'a, 'rcu, C: PageTableConfig> Entry<'rcu, C> {
94 #[verus_spec(r =>
96 with Tracked(owner): Tracked<&EntryOwner<C>>,
97 requires
98 self.wf(*owner),
99 owner.inv(),
100 returns owner.is_absent(),
101 )]
102 pub(in crate::mm) fn is_none(&self) -> bool {
103 !self.pte.is_present()
104 }
105
106 #[verus_spec(
108 with Tracked(owner): Tracked<EntryOwner<C>>,
109 Tracked(parent_owner): Tracked<&NodeOwner<C>>,
110 Tracked(guard_perm): Tracked<&GuardPerm<'rcu, C>>
111 )]
112 pub(in crate::mm) fn is_node(&self) -> bool
113 requires
114 owner.inv(),
115 self.wf(owner),
116 guard_perm.addr() == self.node.addr(),
117 parent_owner.relate_guard_perm(*guard_perm),
118 parent_owner.inv(),
119 parent_owner.level == owner.parent_level,
120 returns
121 owner.is_node(),
122 {
123 let guard = self.node.borrow(Tracked(guard_perm));
124
125 self.pte.is_present() && !self.pte.is_last(
126 #[verus_spec(with Tracked(&parent_owner.meta_perm))]
127 guard.level(),
128 )
129 }
130
131 #[verus_spec(
133 with Tracked(owner): Tracked<&EntryOwner<C>>,
134 Tracked(parent_owner): Tracked<&NodeOwner<C>>,
135 Tracked(regions): Tracked<&mut MetaRegionOwners>,
136 Tracked(guard_perm): Tracked<&GuardPerm<'rcu, C>>
137 )]
138 pub(in crate::mm) fn to_ref(&self) -> (res: ChildRef<'rcu, C>)
139 requires
140 self.invariants(*owner, *old(regions)),
141 self.node_matching(*owner, *parent_owner, *guard_perm),
142 !owner.in_scope,
143 ensures
144 res.invariants(*owner, *old(regions)),
145 *regions =~= *old(regions),
146 Self::relate_region_preserved(*old(regions), *regions),
147 {
148 let guard = self.node.borrow(Tracked(guard_perm));
149
150 #[verus_spec(with Tracked(&parent_owner.meta_perm))]
151 let level = guard.level();
152
153 #[verus_spec(with Tracked(regions), Tracked(owner))]
157 let res = ChildRef::from_pte(&self.pte, level);
158
159 res
160 }
161
162 #[verus_spec(
180 with Tracked(owner) : Tracked<&mut EntryOwner<C>>,
181 Tracked(parent_owner): Tracked<&mut NodeOwner<C>>,
182 Tracked(guard_perm): Tracked<&mut GuardPerm<'rcu, C>>,
183 )]
184 pub(in crate::mm) fn protect(&mut self, op: impl FnOnce(PageProperty) -> PageProperty)
185 requires
186 old(owner).inv(),
187 old(self).wf(*old(owner)),
188 old(self).node_matching(*old(owner), *old(parent_owner), *old(guard_perm)),
189 op.requires((old(self).pte.prop(),)),
190 old(owner).is_frame(),
191 ensures
192 owner.inv(),
193 self.wf(*owner),
194 self.node_matching(*owner, *parent_owner, *guard_perm),
195 self.parent_perms_preserved(
196 *old(parent_owner),
197 *parent_owner,
198 *old(guard_perm),
199 *guard_perm,
200 ),
201 owner.is_frame(),
202 owner.frame.unwrap().mapped_pa == old(owner).frame.unwrap().mapped_pa,
203 old(self).pte.is_present() ==> op.ensures(
204 (old(owner).frame.unwrap().prop,),
205 owner.frame.unwrap().prop,
206 ),
207 {
208 let ghost pte0 = self.pte;
209
210 if !self.pte.is_present() {
211 return ;
212 }
213 let prop = self.pte.prop();
214 let new_prop = op(prop);
215
216 proof {
221 self.pte.set_prop_properties(new_prop);
222 }
223 self.pte.set_prop(new_prop);
224
225 let mut guard = self.node.take(Tracked(guard_perm));
226
227 #[verus_spec(with Tracked(parent_owner))]
233 guard.write_pte(self.idx, self.pte);
234
235 proof {
236 let tracked mut frame_owner = owner.frame.tracked_take();
237 frame_owner.prop = new_prop;
238 owner.frame = Some(frame_owner);
239 }
240 assert(owner.match_pte(self.pte, owner.parent_level));
241
242 self.node.put(Tracked(guard_perm), guard);
243 }
244
245 #[verus_spec(
266 with Tracked(regions) : Tracked<&mut MetaRegionOwners>,
267 Tracked(owner): Tracked<&mut EntryOwner<C>>,
268 Tracked(new_owner): Tracked<&mut EntryOwner<C>>,
269 Tracked(parent_owner): Tracked<&mut NodeOwner<C>>,
270 Tracked(guard_perm): Tracked<&mut GuardPerm<'rcu, C>>
271 )]
272 pub(in crate::mm) fn replace(&mut self, new_child: Child<C>) -> (res: Child<C>)
273 requires
274 old(self).invariants(*old(owner), *old(regions)),
275 new_child.invariants(*old(new_owner), *old(regions)),
276 old(self).node_matching(*old(owner), *old(parent_owner), *old(guard_perm)),
277 old(self).new_owner_compatible(new_child, *old(owner), *old(new_owner), *old(regions)),
278 !old(owner).in_scope,
279 Self::replace_panic_condition(*old(parent_owner), *old(new_owner)),
280 ensures
281 self.invariants(*new_owner, *regions),
282 res.invariants(*owner, *regions),
283 self.node_matching(*new_owner, *parent_owner, *guard_perm),
284 self.idx == old(self).idx,
285 *owner == old(owner).from_pte_owner_spec(),
286 *new_owner == old(new_owner).into_pte_owner_spec(),
287 Self::relate_region_neq_preserved(*old(owner), *new_owner, *old(regions), *regions),
288 Self::path_tracked_pred_preserved(*old(regions), *regions),
289 !new_owner.is_absent() ==> PageTableOwner::<C>::path_tracked_pred(*regions)(
290 *new_owner,
291 new_owner.path,
292 ),
293 self.parent_perms_preserved(
294 *old(parent_owner),
295 *parent_owner,
296 *guard_perm,
297 *old(guard_perm),
298 ),
299 {
300 let ghost new_idx = frame_to_index(new_owner.meta_slot_paddr().unwrap());
301 let ghost old_idx = frame_to_index(owner.meta_slot_paddr().unwrap());
302
303 let mut guard = self.node.take(Tracked(guard_perm));
304
305 #[verus_spec(with Tracked(&parent_owner.meta_perm))]
321 let level = guard.level();
322
323 #[verus_spec(with Tracked(regions), Tracked(owner))]
324 let old_child = Child::from_pte(self.pte, level);
325
326 let ghost regions_after_from = *regions;
327
328 assert(new_owner.is_node() ==> regions.slots.contains_key(
329 frame_to_index(new_owner.meta_slot_paddr().unwrap()),
330 ));
331
332 if old_child.is_none() && !new_child.is_none() {
333 #[verus_spec(with Tracked(&parent_owner.meta_perm))]
334 let nr_children = guard.nr_children_mut();
335 let _tmp = nr_children.read(Tracked(&parent_owner.meta_own.nr_children));
336 assume(_tmp < NR_ENTRIES);
337 nr_children.write(Tracked(&mut parent_owner.meta_own.nr_children), _tmp + 1);
338 } else if !old_child.is_none() && new_child.is_none() {
339 #[verus_spec(with Tracked(&parent_owner.meta_perm))]
340 let nr_children = guard.nr_children_mut();
341 let _tmp = nr_children.read(Tracked(&parent_owner.meta_own.nr_children));
342 assume(_tmp > 0);
343 nr_children.write(Tracked(&mut parent_owner.meta_own.nr_children), _tmp - 1);
344 }
345 proof {
346 assert(owner.relate_region(*regions));
347 }
348
349 #[verus_spec(with Tracked(new_owner), Tracked(regions))]
350 let new_pte = new_child.into_pte();
351
352 let ghost regions_after_into = *regions;
353
354 proof {
355 assert(owner.relate_region(*regions));
356 }
357
358 #[verus_spec(with Tracked(parent_owner))]
363 guard.write_pte(self.idx, new_pte);
364
365 self.node.put(Tracked(guard_perm), guard);
366
367 self.pte = new_pte;
368
369 proof {
370 if new_owner.is_node() || new_owner.is_frame() {
371 let paddr = new_owner.meta_slot_paddr().unwrap();
372 regions.inv_implies_correct_addr(paddr);
373
374 let tracked mut new_meta_slot = regions.slot_owners.tracked_remove(new_idx);
375 new_meta_slot.path_if_in_pt = Some(new_owner.get_path());
376 regions.slot_owners.tracked_insert(new_idx, new_meta_slot);
377 }
378 owner.in_scope = true;
379 }
380
381 assert(Self::relate_region_neq_preserved(*old(owner), *new_owner, *old(regions), *regions));
382 assert(Self::path_tracked_pred_preserved(*old(regions), *regions));
383
384 proof {
385 if new_owner.is_node() || new_owner.is_frame() {
386 let paddr = new_owner.meta_slot_paddr().unwrap();
387 regions.inv_implies_correct_addr(paddr);
388 }
389 }
390
391 old_child
392 }
393
394 #[verus_spec(res =>
411 with Tracked(owner): Tracked<&mut OwnerSubtree<C>>,
412 Tracked(parent_owner): Tracked<&mut NodeOwner<C>>,
413 Tracked(regions): Tracked<&mut MetaRegionOwners>,
414 Tracked(guards): Tracked<&mut Guards<'rcu, C>>,
415 Tracked(parent_guard_perm): Tracked<&mut GuardPerm<'rcu, C>>
416 -> guard_perm: Tracked<Option<GuardPerm<'rcu, C>>>
417 requires
418 old(self).invariants(old(owner).value, *old(regions)),
419 old(owner).inv(),
420 old(self).node_matching(old(owner).value, *old(parent_owner), *old(parent_guard_perm)),
421 old(owner).level < INC_LEVELS - 1,
422 ensures
423 self.invariants(owner.value, *regions),
424 self.parent_perms_preserved(*old(parent_owner), *parent_owner, *old(parent_guard_perm), *parent_guard_perm),
425 old(owner).value.is_absent() && old(parent_owner).level > 1 ==> {
426 &&& res is Some
427 &&& owner.value.is_node()
428 &&& guard_perm@ is Some
429 &&& guard_perm@.unwrap().addr() == res.unwrap().addr()
430 &&& owner.level == old(owner).level
431 &&& owner.value.parent_level == old(owner).value.parent_level
432 &&& owner.value.node.unwrap().relate_guard_perm(guard_perm@.unwrap())
433 &&& guards.lock_held(owner.value.node.unwrap().meta_perm.addr())
434 &&& owner.value.path == old(owner).value.path
435 &&& owner.value.relate_region(*regions)
436 &&& OwnerSubtree::implies(
437 CursorOwner::<'rcu, C>::node_unlocked(*old(guards)),
438 CursorOwner::<'rcu, C>::node_unlocked_except(*guards, owner.value.node.unwrap().meta_perm.addr()))
439 &&& Self::relate_region_neq_preserved(old(owner).value, owner.value, *old(regions), *regions)
440 &&& Self::path_tracked_pred_preserved(*old(regions), *regions)
441 &&& owner.tree_predicate_map(owner.value.path,
442 CursorOwner::<'rcu, C>::node_unlocked_except(*guards, owner.value.node.unwrap().meta_perm.addr()))
443 &&& owner.tree_predicate_map(owner.value.path, PageTableOwner::<C>::relate_region_pred(*regions))
444 },
445 !old(owner).value.is_absent() ==> {
446 &&& res is None
447 &&& *owner == *old(owner)
448 },
449 forall |i: usize| old(guards).lock_held(i) ==> guards.lock_held(i),
450 forall |i: usize| old(guards).unlocked(i) && i != owner.value.node.unwrap().meta_perm.addr() ==> guards.unlocked(i),
451 )]
452 pub(in crate::mm) fn alloc_if_none<A: InAtomicMode>(&mut self, guard: &'rcu A) -> (res: Option<
453 PPtr<PageTableGuard<'rcu, C>>,
454 >) {
455 let entry_is_present = self.pte.is_present();
456
457 let mut parent_guard = self.node.take(Tracked(parent_guard_perm));
458
459 #[verus_spec(with Tracked(&parent_owner.meta_perm))]
460 let level = parent_guard.level();
461
462 if entry_is_present || level <= 1 {
463 self.node.put(Tracked(parent_guard_perm), parent_guard);
464
465 proof_with!{|= Tracked(None)}
466 None
467 } else {
468 let tracked old_path = owner.value.get_path();
469
470 proof_decl! {
471 let tracked mut new_node_owner: Tracked<OwnerSubtree<C>>;
472 }
473
474 #[verus_spec(with Tracked(parent_owner), Tracked(regions), Tracked(guards), Ghost(self.idx) => Tracked(new_node_owner))]
475 let new_page = PageTableNode::<C>::alloc(level - 1);
476
477 proof {
478 let pte = C::E::new_pt_spec(
479 meta_to_frame(new_node_owner.value.node.unwrap().meta_perm.addr()),
480 );
481 old(parent_owner).set_children_perm_axiom(self.idx, pte);
482 C::E::new_properties();
483 assert(!pte.is_last_spec(level as PagingLevel));
484 }
485
486 #[verus_spec(with Tracked(&new_node_owner.value.node.tracked_borrow().meta_perm.points_to))]
487 let paddr = new_page.start_paddr();
488
489 assert(new_node_owner.value.relate_region(*regions));
490
491 #[verus_spec(with Tracked(&mut new_node_owner.value), Tracked(regions))]
492 let new_pte = Child::PageTable(new_page).into_pte();
493 self.pte = new_pte;
494
495 proof {
496 assert(new_node_owner.value.pte_invariants(self.pte, *regions));
498 assert(new_node_owner.value.match_pte(self.pte, new_node_owner.value.parent_level));
499 broadcast use crate::mm::frame::meta::mapping::group_page_meta;
500
501 }
502
503 #[verus_spec(with Tracked(regions), Tracked(&new_node_owner.value.node.tracked_borrow().meta_perm))]
504 let pt_ref = PageTableNodeRef::borrow_paddr(paddr);
505
506 proof_decl! {
507 let tracked mut guard_perm: Tracked<GuardPerm<'rcu, C>>;
508 }
509
510 #[verus_spec(with Tracked(&new_node_owner.value.node.tracked_borrow()), Tracked(guards) => Tracked(guard_perm))]
512 let pt_lock_guard = pt_ref.lock(guard);
513
514 #[verus_spec(with Tracked(parent_owner))]
519 parent_guard.write_pte(self.idx, self.pte);
520
521 #[verus_spec(with Tracked(&parent_owner.meta_perm))]
522 let nr_children = parent_guard.nr_children_mut();
523 let _tmp = nr_children.read(Tracked(&parent_owner.meta_own.nr_children));
524 assume(_tmp < NR_ENTRIES);
525 nr_children.write(Tracked(&mut parent_owner.meta_own.nr_children), _tmp + 1);
526
527 self.node.put(Tracked(parent_guard_perm), parent_guard);
528
529 proof {
530 owner.value = new_node_owner.value;
531 owner.value.parent_level = level as PagingLevel;
532 owner.value.path = old_path;
533 owner.children = new_node_owner.children;
534
535 let new_paddr = owner.value.meta_slot_paddr().unwrap();
536 regions.inv_implies_correct_addr(new_paddr);
537 let new_idx = frame_to_index(new_paddr);
538 let tracked mut new_meta_slot = regions.slot_owners.tracked_remove(new_idx);
539 new_meta_slot.path_if_in_pt = Some(owner.value.get_path());
540 regions.slot_owners.tracked_insert(new_idx, new_meta_slot);
541 }
542
543 proof_with!{|= Tracked(Some(guard_perm))}
544 Some(pt_lock_guard)
545 }
546 }
547
548 #[verus_spec(res =>
564 with Tracked(owner) : Tracked<&mut OwnerSubtree<C>>,
565 Tracked(parent_owner): Tracked<&mut NodeOwner<C>>,
566 Tracked(regions): Tracked<&mut MetaRegionOwners>,
567 Tracked(guards): Tracked<&mut Guards<'rcu, C>>,
568 Tracked(guard_perm): Tracked<&mut GuardPerm<'rcu, C>>
569 requires
570 old(regions).inv(),
571 old(owner).inv(),
572 old(self).wf(old(owner).value),
573 old(self).node.addr() == old(guard_perm).addr(),
574 old(guard_perm).is_init(),
575 old(parent_owner).relate_guard_perm(*old(guard_perm)),
576 old(parent_owner).inv(),
577 old(parent_owner).level == old(owner).value.parent_level,
578 old(parent_owner).level < NR_LEVELS,
579 ensures
580 old(owner).value.is_frame() && old(parent_owner).level > 1 ==> {
581 &&& res is Some
582 &&& owner.value.is_node()
583 &&& owner.level == old(owner).level
584 &&& parent_owner.relate_guard_perm(*guard_perm)
585 &&& guards.guards.contains_key(res.unwrap().addr())
586 &&& guards.guards[res.unwrap().addr()] is Some
587 &&& guards.guards[res.unwrap().addr()].unwrap().pptr() == res.unwrap()
588 &&& owner.value.node.unwrap().relate_guard_perm(guards.guards[res.unwrap().addr()].unwrap())
589 &&& owner.value.node.unwrap().meta_perm.addr() == res.unwrap().addr()
590 &&& owner.value.path == old(owner).value.path
591 &&& owner.value.relate_region(*regions)
592 &&& OwnerSubtree::implies(
593 CursorOwner::<'rcu, C>::node_unlocked(*old(guards)),
594 CursorOwner::<'rcu, C>::node_unlocked(*guards))
595 &&& OwnerSubtree::implies(
596 PageTableOwner::<C>::relate_region_pred(*old(regions)),
597 PageTableOwner::<C>::relate_region_pred(*regions))
598 &&& owner.tree_predicate_map(owner.value.path,
599 CursorOwner::<'rcu, C>::node_unlocked(*guards))
600 &&& owner.tree_predicate_map(owner.value.path,
601 PageTableOwner::<C>::relate_region_pred(*regions))
602 },
603 !old(owner).value.is_frame() || old(parent_owner).level <= 1 ==> {
604 &&& res is None
605 &&& *owner == *old(owner)
606 },
607 owner.inv(),
608 regions.inv(),
609 parent_owner.inv(),
610 guard_perm.pptr() == old(guard_perm).pptr(),
611 guard_perm.value().inner.inner@.ptr.addr() == old(guard_perm).value().inner.inner@.ptr.addr(),
612 forall |i: usize| old(guards).lock_held(i) ==> guards.lock_held(i),
613 forall |i: usize| old(guards).unlocked(i) ==> guards.unlocked(i),
614 )]
615 pub(in crate::mm) fn split_if_mapped_huge<A: InAtomicMode>(&mut self, guard: &'rcu A) -> (res:
616 Option<PPtr<PageTableGuard<'rcu, C>>>) {
617 let mut node_guard = self.node.take(Tracked(guard_perm));
618
619 #[verus_spec(with Tracked(&parent_owner.meta_perm))]
620 let level = node_guard.level();
621
622 if !(self.pte.is_last(level) && level > 1) {
623 self.node.put(Tracked(guard_perm), node_guard);
624
625 return None;
626 }
627 let pa = self.pte.paddr();
628 let prop = self.pte.prop();
629
630 proof_decl!{
631 let tracked mut new_owner: OwnerSubtree<C>;
632 }
633
634 #[verus_spec(with Tracked(parent_owner), Tracked(regions), Tracked(guards), Ghost(self.idx) => Tracked(new_owner))]
635 let new_page = PageTableNode::<C>::alloc(level);
636
637 #[verus_spec(with Tracked(&new_owner.value.node.tracked_borrow().meta_perm.points_to))]
638 let paddr = new_page.start_paddr();
639
640 assert(regions.slot_owners[frame_to_index(paddr)].raw_count == 1) by { admit() };
642
643 proof {
644 broadcast use crate::mm::frame::meta::mapping::group_page_meta;
645
646 }
647
648 #[verus_spec(with Tracked(regions), Tracked(&new_owner.value.node.tracked_borrow().meta_perm))]
649 let pt_ref = PageTableNodeRef::borrow_paddr(paddr);
650
651 proof_decl! {
652 let tracked mut new_guard_perm: Tracked<GuardPerm<'rcu, C>>;
653 }
654
655 #[verus_spec(with Tracked(&new_owner.value.node.tracked_borrow()), Tracked(guards) => Tracked(new_guard_perm))]
657 let pt_lock_guard = pt_ref.lock(guard);
658
659 let ghost children_perm = new_owner.value.node.unwrap().children_perm;
660 let ghost new_owner_path = new_owner.value.path;
661 let ghost new_owner_meta_addr = new_owner.value.node.unwrap().meta_perm.addr();
662
663 for i in 0..nr_subpage_per_huge::<C>()
664 invariant
665 1 < level < NR_LEVELS,
666 owner.inv(),
667 regions.inv(),
668 parent_owner.inv(),
669 new_owner.value.is_node(),
670 new_owner.inv(),
671 new_owner.value.path == new_owner_path,
672 new_owner.value.node.unwrap().meta_perm.addr() == new_owner_meta_addr,
673 new_owner.value.node.unwrap().relate_guard_perm(new_guard_perm),
674 new_owner.value.node.unwrap().level == (level - 1) as PagingLevel,
675 pt_lock_guard.addr() == new_guard_perm.addr(),
676 forall|j: int|
677 #![auto]
678 0 <= j < NR_ENTRIES ==> {
679 &&& new_owner.children[j] is Some
680 &&& new_owner.children[j].unwrap().value.match_pte(
681 new_owner.value.node.unwrap().children_perm.value()[j],
682 new_owner.value.node.unwrap().level,
683 )
684 &&& new_owner.children[j].unwrap().value.parent_level
685 == new_owner.value.node.unwrap().level
686 &&& new_owner.children[j].unwrap().value.inv()
687 &&& new_owner.children[j].unwrap().value.path == new_owner_path.push_tail(
688 j as usize,
689 )
690 },
691 forall|j: int|
692 #![auto]
693 i <= j < NR_ENTRIES ==> {
694 &&& new_owner.children[j].unwrap().value.is_absent()
695 &&& !new_owner.children[j].unwrap().value.in_scope
696 &&& new_owner.value.node.unwrap().children_perm.value()[j]
697 == C::E::new_absent_spec()
698 },
699 new_page.ptr.addr() == new_owner_meta_addr,
700 {
701 proof {
702 C::axiom_nr_subpage_per_huge_eq_nr_entries();
703 }
704 assert(i < NR_ENTRIES);
705
706 proof {
707 let ghost the_node = new_owner.value.node.unwrap();
709 assert(0 <= i < NR_ENTRIES);
710 assert(new_owner.children[i as int].unwrap().value.match_pte(
711 the_node.children_perm.value()[i as int],
712 new_owner.children[i as int].unwrap().value.parent_level,
713 ));
714 assert(the_node.relate_guard_perm(new_guard_perm));
715 assert(new_guard_perm.addr() == pt_lock_guard.addr());
716 assert(new_owner.children[i as int].unwrap().value.parent_level == the_node.level);
717 assert(!new_owner.children[i as int].unwrap().value.in_scope);
718
719 OwnerSubtree::child_some_properties(new_owner, i as usize);
720 }
721
722 let tracked mut new_owner_node = new_owner.value.node.tracked_take();
723
724 proof {
725 let ghost old_children_perm = new_owner_node.children_perm;
726 }
727
728 assert(pa + i * page_size((level - 1) as u8) < MAX_PADDR) by { admit() };
729 let small_pa = pa + i * page_size(level - 1);
730
731 assert(small_pa % PAGE_SIZE == 0) by { admit() };
732
733 let tracked child_owner = EntryOwner::new_frame(
734 small_pa,
735 new_owner.value.path.push_tail(i as usize),
736 (level - 1) as PagingLevel,
737 prop,
738 );
739
740 #[verus_spec(with Tracked(&new_owner_node), Tracked(&new_owner.children.tracked_borrow(i as int).tracked_borrow().value), Tracked(&new_guard_perm))]
741 let mut entry = PageTableGuard::entry(pt_lock_guard, i);
742
743 proof {
744 assert(entry.idx == i as usize);
745 let ghost child_before_remove = new_owner.child(i as usize).unwrap();
746 assert(child_before_remove.inv());
747 }
748 let tracked mut new_owner_child = new_owner.children.tracked_remove(
749 i as int,
750 ).tracked_unwrap();
751
752 proof {
753 assert(new_owner_child.value.match_pte(
754 new_owner_node.children_perm.value()[i as int],
755 new_owner_child.value.parent_level,
756 ));
757
758 let idx = frame_to_index(small_pa);
759 assert(regions.slot_owners[idx].path_if_in_pt is None) by { admit() };
760
761 assert(entry.node_matching(new_owner_child.value, new_owner_node, new_guard_perm))
762 by {
763 let pte = new_owner_node.children_perm.value()[i as int];
764 assert(pte == C::E::new_absent_spec());
765 crate::specs::arch::PageTableEntry::absent_pte_paddr_ok();
766 EntryOwner::absent_match_pte(
767 new_owner_child.value,
768 pte,
769 new_owner_child.value.parent_level,
770 );
771 };
772 }
773
774 #[verus_spec(with Tracked(regions),
775 Tracked(&mut new_owner_child.value),
776 Tracked(&mut child_owner),
777 Tracked(&mut new_owner_node),
778 Tracked(&mut new_guard_perm))]
779 let old = entry.replace(Child::Frame(small_pa, level - 1, prop));
780
781 proof {
782 new_owner.value.node = Some(new_owner_node);
783 OwnerSubtree::set_value_property(new_owner_child, child_owner);
784 new_owner_child.value = child_owner;
785 new_owner.children.tracked_insert(i as int, Some(new_owner_child));
786
787 TreePath::push_tail_property_len(new_owner_path, i as usize);
788 OwnerSubtree::insert_preserves_inv(new_owner, i as usize, new_owner_child);
789 }
790 }
791
792 self.pte = (#[verus_spec(with Tracked(&mut new_owner.value), Tracked(regions))]
793 Child::PageTable(new_page).into_pte());
794
795 proof {
796 new_owner.level = owner.level;
797 *owner = new_owner;
798 }
799
800 let tracked mut node_owner = owner.value.node.tracked_take();
801
802 #[verus_spec(with Tracked(&mut node_owner))]
807 node_guard.write_pte(self.idx, self.pte);
808
809 proof {
810 owner.value.node = Some(node_owner);
811 }
812
813 self.node.put(Tracked(guard_perm), node_guard);
814
815 Some(pt_lock_guard)
816 }
817
818 #[verus_spec(
834 with Tracked(owner): Tracked<&EntryOwner<C>>,
835 Tracked(parent_owner): Tracked<&NodeOwner<C>>,
836 Tracked(guard_perm): Tracked<&GuardPerm<'rcu, C>>
837 )]
838 pub(in crate::mm) fn new_at(guard: PPtr<PageTableGuard<'rcu, C>>, idx: usize) -> (res: Self)
839 requires
840 owner.inv(),
841 !owner.in_scope,
842 parent_owner.inv(),
843 guard_perm.addr() == guard.addr(),
844 parent_owner.relate_guard_perm(*guard_perm),
845 idx < NR_ENTRIES,
846 owner.match_pte(parent_owner.children_perm.value()[idx as int], owner.parent_level),
847 ensures
848 res.wf(*owner),
849 res.node.addr() == guard_perm.addr(),
850 res.idx == idx,
851 {
852 let guard_val = guard.borrow(Tracked(guard_perm));
854 #[verus_spec(with Tracked(parent_owner))]
855 let pte = guard_val.read_pte(idx);
856 Self { pte, idx, node: guard }
857 }
858}
859
860}