1use vstd::prelude::*;
4use vstd::simple_pptr;
5use vstd_extra::assert;
6use vstd_extra::cast_ptr::*;
7use vstd_extra::drop_tracking::*;
8use vstd_extra::ownership::*;
9use vstd_extra::panic::may_panic;
10use vstd_extra::prelude::*;
11
12use crate::mm::page_table::RCClone;
13use crate::mm::{Paddr, PagingLevel, Vaddr, paddr_to_vaddr};
14use crate::specs::arch::kspace::FRAME_METADATA_RANGE;
15use crate::specs::arch::mm::{MAX_NR_PAGES, MAX_PADDR, PAGE_SIZE};
16use crate::specs::mm::frame::meta_owners::*;
17use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
18use crate::specs::mm::frame::segment::*;
19use crate::specs::mm::virt_mem::MemView;
20
21use core::{fmt::Debug, ops::Range};
22
23use super::meta::mapping::{frame_to_index, frame_to_meta, meta_addr};
24use super::{AnyFrameMeta, GetFrameError, MetaSlot};
25use crate::mm::frame::{Frame, has_safe_slot, untyped::AnyUFrameMeta};
26
27verus! {
28
29#[repr(transparent)]
42pub struct Segment<M: AnyFrameMeta + ?Sized> {
43 pub range: Range<Paddr>,
45 pub _marker: core::marker::PhantomData<M>,
47}
48
49pub type USegment = Segment<dyn AnyUFrameMeta>;
75
76impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> RCClone for Segment<M> {
92 open spec fn clone_requires(self, perm: MetaRegionOwners) -> bool {
93 &&& self.inv()
94 &&& perm.inv()
95 &&& forall|pa: Paddr|
96 #![trigger frame_to_index(pa)]
97 (self.start_paddr() <= pa < self.end_paddr() && pa % PAGE_SIZE == 0) ==> {
98 let idx = frame_to_index(pa);
99 &&& perm.slots.contains_key(idx)
100 &&& has_safe_slot(pa)
101 &&& perm.slot_owners[idx].inner_perms.ref_count.value() > 0
102 &&& perm.slot_owners[idx].inner_perms.ref_count.value() + 1
103 < super::meta::REF_COUNT_MAX
104 &&& !MetaSlot::inc_ref_count_panic_cond(perm.slot_owners[idx].inner_perms.ref_count)
105 }
106 }
107
108 open spec fn clone_ensures(
109 self,
110 old_perm: MetaRegionOwners,
111 new_perm: MetaRegionOwners,
112 res: Self,
113 ) -> bool {
114 &&& res.range() == self.range()
115 &&& res.inv()
116 &&& new_perm.inv()
117 &&& new_perm.frame_obligations =~= old_perm.frame_obligations
122 }
123
124 fn clone(&self, Tracked(perm): Tracked<&mut MetaRegionOwners>) -> (res: Self) {
125 let mut paddr = self.range.start;
126
127 let ghost old_perm = *perm;
128 loop
129 invariant
130 perm.inv(),
131 self.inv(),
132 perm.slots =~= old_perm.slots,
133 perm.slot_owners.dom() =~= old_perm.slot_owners.dom(),
134 perm.frame_obligations =~= old_perm.frame_obligations,
138 self.range.start <= paddr <= self.range.end,
139 paddr % PAGE_SIZE == 0,
140 paddr <= MAX_PADDR,
141 forall|pa: Paddr|
142 #![trigger frame_to_index(pa)]
143 (paddr <= pa < self.range.end && pa % PAGE_SIZE == 0) ==> {
144 let idx = frame_to_index(pa);
145 &&& perm.slots.contains_key(idx)
146 &&& has_safe_slot(pa)
147 &&& perm.slot_owners[idx].inner_perms.ref_count.value() > 0
148 &&& perm.slot_owners[idx].inner_perms.ref_count.value() + 1
149 < super::meta::REF_COUNT_MAX
150 &&& !MetaSlot::inc_ref_count_panic_cond(
151 perm.slot_owners[idx].inner_perms.ref_count,
152 )
153 },
154 decreases self.range.end - paddr,
155 {
156 if paddr >= self.range.end {
157 break;
158 }
159 proof {
160 assert(paddr + PAGE_SIZE <= self.range.end);
161 assert(paddr + PAGE_SIZE <= MAX_PADDR);
162 }
163
164 unsafe {
165 #[verus_spec(with Tracked(perm))]
166 crate::mm::frame::inc_frame_ref_count(paddr)
167 };
168
169 paddr = paddr + PAGE_SIZE;
170 }
171
172 Self { range: self.range.start..self.range.end, _marker: core::marker::PhantomData }
173 }
174}
175
176#[verus_verify]
177impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Segment<M> {
178 #[verus_spec(r =>
204 with
205 Tracked(regions): Tracked<&mut MetaRegionOwners>,
206 -> owner: Tracked<Option<SegmentOwner<M>>>,
207 requires
208 old(regions).inv(),
209 forall|paddr_in: Paddr|
210 (range.start <= paddr_in < range.end && paddr_in % PAGE_SIZE == 0) ==> {
211 &&& metadata_fn.requires((paddr_in,))
212 },
213 forall|paddr_in: Paddr, paddr_out: Paddr, m: M|
214 metadata_fn.ensures((paddr_in,), (paddr_out, m)) ==> paddr_in == paddr_out,
215 !(range.end <= MAX_PADDR ==> range.start < range.end) ==> may_panic(),
216 ensures
217 final(regions).inv(),
218 r is Err ==> final(regions).frame_obligations =~= old(regions).frame_obligations,
219 (range.start % PAGE_SIZE != 0 || range.end % PAGE_SIZE != 0)
220 ==> r == Err::<Self, _>(GetFrameError::NotAligned),
221 (range.start % PAGE_SIZE == 0 && range.end % PAGE_SIZE == 0 && range.end > MAX_PADDR)
222 ==> r == Err::<Self, _>(GetFrameError::OutOfBound),
223 r is Ok ==> range.end <= MAX_PADDR ==> range.start < range.end,
224 r matches Ok(seg) ==> {
225 &&& seg.start_paddr() == range.start
226 &&& seg.end_paddr() == range.end
227 &&& seg.start_paddr() < seg.end_paddr()
228 &&& crate::specs::mm::frame::segment::seg_obligations_minted(
229 *old(regions),
230 *final(regions),
231 range.start,
232 crate::specs::mm::frame::segment::seg_nframes(range),
233 )
234 &&& owner@ matches Some(owner) && {
235 &&& seg.inv()
236 &&& seg.wf(&owner)
237 }
238 &&& forall|paddr: Paddr|
239 #![trigger frame_to_index(paddr)]
240 (range.start <= paddr < range.end && paddr % PAGE_SIZE == 0)
241 ==> final(regions).slots.contains_key(frame_to_index(paddr))
242 },
243 )]
244 pub fn from_unused(range: Range<Paddr>, metadata_fn: impl Fn(Paddr) -> (Paddr, M)) -> (res:
245 Result<Self, GetFrameError>) {
246 proof_decl! {
247 let tracked mut owner: Option<SegmentOwner<M>> = None;
248 let tracked mut addrs = Seq::<usize>::tracked_empty();
249 }
250
251 if range.start % PAGE_SIZE != 0 || range.end % PAGE_SIZE != 0 {
252 return {
253 proof_with!(|= Tracked(owner));
254 Err(GetFrameError::NotAligned)
255 };
256 }
257 if range.end > MAX_PADDR {
258 return {
259 proof_with!(|= Tracked(owner));
260 Err(GetFrameError::OutOfBound)
261 };
262 }
263 assert!(range.start < range.end);
264
265 let mut segment = Self {
266 range: range.start..range.start,
267 _marker: core::marker::PhantomData,
268 };
269
270 let mut i = 0;
271 let addr_len = (range.end - range.start) / PAGE_SIZE;
272
273 while i < addr_len
274 invariant
275 i <= addr_len,
276 i as int == addrs.len(),
277 range.start % PAGE_SIZE == 0,
278 range.end % PAGE_SIZE == 0,
279 range.end <= MAX_PADDR,
280 range.start <= range.start + i * PAGE_SIZE <= range.end,
281 range.end == range.start + addr_len * PAGE_SIZE,
282 addr_len == (range.end - range.start) / PAGE_SIZE as int,
283 i <= addr_len,
284 forall|paddr_in: Paddr|
285 (range.start + i * PAGE_SIZE <= paddr_in < range.end && paddr_in % PAGE_SIZE
286 == 0) ==> {
287 &&& metadata_fn.requires((paddr_in,))
288 },
289 forall|paddr_in: Paddr, paddr_out: Paddr, m: M|
290 range.start + i * PAGE_SIZE <= paddr_in < range.end && paddr_in % PAGE_SIZE == 0
291 && metadata_fn.ensures((paddr_in,), (paddr_out, m)) ==> paddr_in
292 == paddr_out,
293 forall|j: int|
294 #![trigger addrs[j]]
295 0 <= j < addrs.len() as int ==> {
296 let idx = frame_to_index(addrs[j]);
297 &&& regions.slots.contains_key(idx)
298 &&& regions.slot_owners.contains_key(idx)
299 &&& regions.slot_owners[idx].self_addr == meta_addr(idx)
300 &&& regions.slot_owners[idx].inner_perms.ref_count.value() > 0
301 &&& regions.slot_owners[idx].inner_perms.ref_count.value()
302 <= crate::mm::frame::meta::REF_COUNT_MAX
303 &&& regions.slot_owners[idx].paths_in_pt.is_empty()
304 &&& addrs[j] % PAGE_SIZE == 0
305 &&& addrs[j] < MAX_PADDR
306 &&& addrs[j] == range.start + (j as u64) * PAGE_SIZE
307 },
308 regions.inv(),
309 regions.frame_obligations =~= old(regions).frame_obligations,
310 regions.slot_owners.dom() =~= old(regions).slot_owners.dom(),
311 segment.range.start == range.start,
312 segment.range.end == range.start + i * PAGE_SIZE,
313 ensures
314 i == addr_len,
315 decreases addr_len - i,
316 {
317 let paddr_in = range.start + i * PAGE_SIZE;
318 let (paddr, meta) = metadata_fn(paddr_in);
319
320 let ghost regions_pre = *regions;
321 let res = #[verus_spec(with Tracked(regions))]
322 Frame::<M>::from_unused(paddr, meta);
323 let frame = match res {
324 Ok(f) => f,
325 Err(e) => {
326 let mut p = range.start;
327 let ghost mut k: int = 0;
328 while p < segment.range.end
329 invariant
330 regions.inv(),
331 regions.frame_obligations =~= old(regions).frame_obligations,
332 regions.slot_owners.dom() =~= old(regions).slot_owners.dom(),
333 range.start % PAGE_SIZE == 0,
334 i as int == addrs.len(),
335 segment.range.end == range.start + i * PAGE_SIZE,
336 segment.range.end <= MAX_PADDR,
337 range.start <= p <= segment.range.end,
338 p == range.start + k * PAGE_SIZE,
339 p % PAGE_SIZE == 0,
340 0 <= k <= i,
341 forall|j: int|
342 #![trigger addrs[j]]
343 k <= j < addrs.len() as int ==> {
344 let idx = frame_to_index(addrs[j]);
345 &&& regions.slots.contains_key(idx)
346 &&& regions.slot_owners.contains_key(idx)
347 &&& regions.slot_owners[idx].self_addr == meta_addr(idx)
348 &&& regions.slot_owners[idx].inner_perms.ref_count.value() > 0
349 &&& regions.slot_owners[idx].inner_perms.ref_count.value()
350 <= crate::mm::frame::meta::REF_COUNT_MAX
351 &&& regions.slot_owners[idx].paths_in_pt.is_empty()
352 &&& addrs[j] % PAGE_SIZE == 0
353 &&& addrs[j] < MAX_PADDR
354 &&& addrs[j] == range.start + (j as u64) * PAGE_SIZE
355 },
356 decreases segment.range.end - p,
357 {
358 let ghost reclaim_pre = *regions;
359 let ghost idx_k = frame_to_index(p);
360 proof {
361 broadcast use crate::mm::frame::meta::mapping::group_page_meta;
362
363 assert(addrs[k] == p);
364 assert(meta_addr(idx_k) == frame_to_meta(p));
365 assert(regions.slots.contains_key(idx_k));
366 }
367 proof_decl! {
368 let tracked from_raw_obl: vstd_extra::drop_tracking::DropObligation<
369 usize,
370 >;
371 }
372 let frame = unsafe {
373 #[verus_spec(with Tracked(regions) => Tracked(from_raw_obl))]
374 Frame::<M>::from_raw(p)
375 };
376 proof {
377 broadcast use crate::mm::frame::meta::mapping::group_page_meta;
378
379 assert(regions.slots[idx_k].pptr() == frame.ptr);
380 }
381 frame.drop(Tracked(regions), Tracked(from_raw_obl));
382 proof {
383 assert forall|j: int|
384 #![trigger addrs[j]]
385 (k + 1) <= j < addrs.len() as int implies ({
386 let idx = frame_to_index(addrs[j]);
387 &&& regions.slots.contains_key(idx)
388 &&& regions.slot_owners.contains_key(idx)
389 &&& regions.slot_owners[idx] == reclaim_pre.slot_owners[idx]
390 }) by {
391 assert(addrs[j] != p);
392 crate::mm::frame::meta::mapping::lemma_frame_to_index_injective(
393 addrs[j],
394 p,
395 );
396 };
397 }
398 p = p + PAGE_SIZE;
399 proof {
400 k = k + 1;
401 }
402 }
403 return {
404 proof_with!(|= Tracked(owner));
405 Err(e)
406 };
407 },
408 };
409
410 let _ = ManuallyDrop::new(frame, Tracked(regions));
411 segment.range.end = paddr + PAGE_SIZE;
412 proof {
413 broadcast use crate::mm::frame::meta::mapping::group_page_meta;
414
415 regions.inv_implies_correct_addr(paddr);
416 let idx = frame_to_index(paddr);
417 axiom_mmio_usage_iff_mmio_paddr(regions.slot_owners[idx]);
418 axiom_mmio_usage_iff_mmio_paddr(regions_pre.slot_owners[idx]);
419 assert(regions_pre.slot_owners[idx].paths_in_pt.is_empty());
420 assert(regions.slot_owners[idx].paths_in_pt
421 =~= regions_pre.slot_owners[idx].paths_in_pt);
422 assert(regions.frame_obligations =~= regions_pre.frame_obligations);
423 addrs.tracked_push(paddr);
424 }
425
426 i += 1;
427 }
428
429 proof {
430 assert(regions.frame_obligations =~= old(regions).frame_obligations);
440 crate::specs::mm::frame::segment::tracked_mint_seg_obligations(
441 regions,
442 range.start,
443 addr_len as int,
444 );
445 assert(addr_len as int == crate::specs::mm::frame::segment::seg_nframes(range));
446 owner = Some(SegmentOwner { range, _marker: core::marker::PhantomData });
447
448 assert forall|addr: usize|
449 #![trigger frame_to_index(addr)]
450 range.start <= addr < range.end && addr % PAGE_SIZE == 0 implies {
451 regions.slots.contains_key(frame_to_index(addr))
452 } by {
453 let j = (addr - range.start) / PAGE_SIZE as int;
454 assert(0 <= j < addrs.len() as int);
455 assert(addrs[j as int] == addr);
456 }
457 }
458
459 proof_with!(|= Tracked(owner));
460 Ok(segment)
461 }
462
463 #[verus_spec(r =>
486 with
487 Tracked(regions): Tracked<&mut MetaRegionOwners>,
488 Tracked(owner): Tracked<SegmentOwner<M>>,
489 requires
490 old(regions).inv(),
491 owner.inv(),
492 range == owner.range,
493 owner.relate_regions(*old(regions)),
494 ensures
495 r.range() == range,
496 r.inv(),
497 r.wf(&owner),
498 final(regions).inv(),
499 *final(regions) =~= *old(regions),
500 )]
501 pub(crate) unsafe fn from_raw(range: Range<Paddr>) -> Self {
502 Self { range, _marker: core::marker::PhantomData }
503 }
504}
505
506#[verus_verify]
507impl<M: AnyFrameMeta + ?Sized> Segment<M> {
508 #[verus_verify(dual_spec)]
510 #[verus_spec(
511 returns
512 self.start_paddr(),
513 )]
514 pub fn start_paddr(&self) -> Paddr {
515 self.range.start
516 }
517
518 #[verus_verify(dual_spec)]
520 #[verus_spec(
521 returns
522 self.end_paddr(),
523 )]
524 pub fn end_paddr(&self) -> Paddr {
525 self.range.end
526 }
527
528 #[verus_verify(dual_spec)]
530 #[verus_spec(r =>
531 requires
532 self.inv(),
533 ensures
534 r == self.end_paddr() - self.start_paddr(),
535 returns
536 self.size()
537 )]
538 pub fn size(&self) -> usize {
539 self.range.end - self.range.start
540 }
541
542 pub open spec fn range(&self) -> Range<Paddr> {
543 self.start_paddr()..self.end_paddr()
544 }
545}
546
547#[verus_verify]
548impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Segment<M> {
549 #[verus_spec(r =>
567 with
568 Tracked(owner): Tracked<SegmentOwner<M>>,
569 Tracked(regions): Tracked<&mut MetaRegionOwners>,
570 -> result_owners: (Tracked<SegmentOwner<M>>, Tracked<SegmentOwner<M>>),
571 requires
572 self.invariants(&owner, *old(regions)),
573 offset % PAGE_SIZE != 0 ==> may_panic(),
574 !(0 < offset && offset < self.size()) ==> may_panic(),
575 ensures
576 final(regions).slots =~= old(regions).slots,
577 final(regions).slot_owners =~= old(regions).slot_owners,
578 final(regions).frame_obligations =~= old(regions).frame_obligations,
579 (r.0, r.1) == self.split_spec(offset),
580 r.0.invariants(&result_owners.0@, *final(regions)),
581 r.1.invariants(&result_owners.1@, *final(regions)),
582 )]
583 pub fn split(self, offset: usize) -> (Self, Self) {
584 assert!(offset % PAGE_SIZE == 0);
585 assert!(0 < offset && offset < self.size());
586
587 let ghost old_regions = *regions;
588
589 let old = ManuallyDrop::new(self, Tracked(regions));
590 let at = old.range.start + offset;
591
592 let ghost old_start = old@.start_paddr();
593 let ghost old_end = old@.end_paddr();
594
595 let tracked frame_own1 = SegmentOwner {
596 range: old_start..at,
597 _marker: core::marker::PhantomData,
598 };
599 let tracked frame_own2 = SegmentOwner {
600 range: at..old_end,
601 _marker: core::marker::PhantomData,
602 };
603 proof {
604 assert(*regions =~= old_regions);
605 assert(regions.slot_owners =~= old_regions.slot_owners);
606 assert(regions.frame_obligations =~= old_regions.frame_obligations);
607 assert forall|i: int|
608 #![trigger frame_to_index((frame_own1.range.start + i * PAGE_SIZE) as usize)]
609 0 <= i < crate::specs::mm::frame::segment::seg_nframes(frame_own1.range) implies {
610 let idx = frame_to_index((frame_own1.range.start + i * PAGE_SIZE) as usize);
611 &&& regions.frame_obligations.count(idx) >= 1
612 &&& regions.slot_owners.contains_key(idx)
613 &&& regions.slots.contains_key(idx)
614 &&& regions.slot_owners[idx].self_addr == meta_addr(idx)
615 &&& regions.slot_owners[idx].inner_perms.ref_count.value() > 0
616 &&& regions.slot_owners[idx].inner_perms.ref_count.value()
617 <= crate::mm::frame::meta::REF_COUNT_MAX
618 &&& regions.slot_owners[idx].paths_in_pt.is_empty()
619 &&& regions.slot_owners[idx].usage
620 == crate::specs::mm::frame::meta_owners::PageUsage::Frame
621 } by {
622 owner.relate_regions_at(old_regions, i);
623 }
624 assert forall|i: int|
625 #![trigger frame_to_index((frame_own2.range.start + i * PAGE_SIZE) as usize)]
626 0 <= i < crate::specs::mm::frame::segment::seg_nframes(frame_own2.range) implies {
627 let idx = frame_to_index((frame_own2.range.start + i * PAGE_SIZE) as usize);
628 &&& regions.frame_obligations.count(idx) >= 1
629 &&& regions.slot_owners.contains_key(idx)
630 &&& regions.slots.contains_key(idx)
631 &&& regions.slot_owners[idx].self_addr == meta_addr(idx)
632 &&& regions.slot_owners[idx].inner_perms.ref_count.value() > 0
633 &&& regions.slot_owners[idx].inner_perms.ref_count.value()
634 <= crate::mm::frame::meta::REF_COUNT_MAX
635 &&& regions.slot_owners[idx].paths_in_pt.is_empty()
636 &&& regions.slot_owners[idx].usage
637 == crate::specs::mm::frame::meta_owners::PageUsage::Frame
638 } by {
639 owner.relate_regions_at(old_regions, i + (offset / PAGE_SIZE) as int);
640 }
641
642 assert forall|i: int, j: int|
643 #![trigger frame_to_index((frame_own1.range.start + i * PAGE_SIZE) as usize),
644 frame_to_index((frame_own1.range.start + j * PAGE_SIZE) as usize)]
645 0 <= i < j < crate::specs::mm::frame::segment::seg_nframes(
646 frame_own1.range,
647 ) implies frame_to_index((frame_own1.range.start + i * PAGE_SIZE) as usize)
648 != frame_to_index((frame_own1.range.start + j * PAGE_SIZE) as usize) by {
649 owner.relate_regions_distinct(old_regions, i, j);
650 }
651 assert forall|i: int, j: int|
652 #![trigger frame_to_index((frame_own2.range.start + i * PAGE_SIZE) as usize),
653 frame_to_index((frame_own2.range.start + j * PAGE_SIZE) as usize)]
654 0 <= i < j < crate::specs::mm::frame::segment::seg_nframes(
655 frame_own2.range,
656 ) implies frame_to_index((frame_own2.range.start + i * PAGE_SIZE) as usize)
657 != frame_to_index((frame_own2.range.start + j * PAGE_SIZE) as usize) by {
658 owner.relate_regions_distinct(
659 old_regions,
660 i + (offset / PAGE_SIZE) as int,
661 j + (offset / PAGE_SIZE) as int,
662 );
663 }
664 }
665 proof_with!(|= (Tracked(frame_own1), Tracked(frame_own2)));
666 (
667 Self { range: old.range.start..at, _marker: core::marker::PhantomData },
668 Self { range: at..old.range.end, _marker: core::marker::PhantomData },
669 )
670 }
671
672 pub open spec fn page_in_range_saturated(
682 self,
683 range: &Range<usize>,
684 regions: MetaRegionOwners,
685 ) -> bool {
686 exists|j: int|
687 #![trigger frame_to_index((self.range.start + j * PAGE_SIZE) as usize)]
688 (range.start as int) / (PAGE_SIZE as int) <= j < (range.end as int) / (PAGE_SIZE as int)
689 && regions.slot_owners[frame_to_index(
690 (self.start_paddr() + j * PAGE_SIZE) as usize,
691 )].inner_perms.ref_count.value() >= REF_COUNT_MAX
692 }
693
694 #[verus_spec(r =>
710 with
711 Tracked(owner): Tracked<&SegmentOwner<M>>,
712 Tracked(regions): Tracked<&mut MetaRegionOwners>,
713 requires
714 self.invariants(owner, *old(regions)),
715 range.start % PAGE_SIZE != 0 ==> may_panic(),
716 range.end % PAGE_SIZE != 0 ==> may_panic(),
717 range.start > range.end ==> may_panic(),
718 self.range.start as int + range.end as int > self.range.end as int ==> may_panic(),
719 self.page_in_range_saturated(range, *old(regions)) ==> may_panic(),
720 ensures
721 range.start % PAGE_SIZE == 0,
722 range.end % PAGE_SIZE == 0,
723 range.start <= range.end,
724 self.range.start as int + range.end as int <= self.range.end as int,
725 !self.page_in_range_saturated(range, *old(regions)),
726 r.inv(),
727 r.start_paddr() == self.start_paddr() + range.start,
728 r.end_paddr() == self.start_paddr() + range.end,
729 r.end_paddr() <= self.end_paddr(),
730 final(regions).inv(),
731 final(regions).slots =~= old(regions).slots,
732 final(regions).slot_owners.dom() =~= old(regions).slot_owners.dom(),
733 final(regions).frame_obligations =~= old(regions).frame_obligations,
734 )]
735 #[verifier::rlimit(8000)]
736 pub fn slice(&self, range: &Range<usize>) -> Self {
737 assume(self.range.start + range.start <= usize::MAX);
739 assume(self.range.start + range.end <= usize::MAX);
740
741 assert!(range.start % PAGE_SIZE == 0 && range.end % PAGE_SIZE == 0);
742 let start = self.range.start + range.start;
743 let end = self.range.start + range.end;
744 assert!(start <= end && end <= self.range.end);
745
746 let mut paddr = start;
747 let ghost addr_len = (end - start) / PAGE_SIZE as int;
748 let ghost first_perm_idx: int = (range.start / PAGE_SIZE) as int;
749 let ghost last_perm_idx: int = (range.end / PAGE_SIZE) as int;
750 let ghost old_regions = *regions;
751 let ghost mut i: int = 0;
752 loop
753 invariant
754 self.page_in_range_saturated(range, *old(regions)) ==> may_panic(),
755 old_regions == *old(regions),
756 regions.inv(),
757 regions.slots =~= old_regions.slots,
758 regions.slot_owners.dom() =~= old_regions.slot_owners.dom(),
759 regions.frame_obligations =~= old_regions.frame_obligations,
760 start == self.range.start + range.start,
761 end == self.range.start + range.end,
762 start <= end <= self.range.end,
763 start % PAGE_SIZE == 0,
764 end % PAGE_SIZE == 0,
765 paddr == (start + i * PAGE_SIZE) as usize,
766 paddr <= end,
767 0 <= i <= addr_len,
768 addr_len == (end - start) / PAGE_SIZE as int,
769 paddr < end <==> i < addr_len,
770 self.inv(),
771 self.wf(&owner),
772 owner.inv(),
773 owner.relate_regions(old_regions),
774 first_perm_idx == range.start / PAGE_SIZE,
775 last_perm_idx == range.end / PAGE_SIZE,
776 first_perm_idx + addr_len as int == last_perm_idx,
777 first_perm_idx + i <= last_perm_idx,
778 forall|j: int|
779 #![trigger frame_to_index((self.range.start + j * PAGE_SIZE) as usize)]
780 first_perm_idx + i <= j < last_perm_idx ==> (
781 *regions).slot_owners[frame_to_index(
782 (self.range.start + j * PAGE_SIZE) as usize,
783 )] == old_regions.slot_owners[frame_to_index(
784 (self.range.start + j * PAGE_SIZE) as usize,
785 )],
786 forall|j: int|
787 #![trigger frame_to_index((self.range.start + j * PAGE_SIZE) as usize)]
788 first_perm_idx <= j < first_perm_idx + i
789 ==> old_regions.slot_owners[frame_to_index(
790 (self.range.start + j * PAGE_SIZE) as usize,
791 )].inner_perms.ref_count.value() < REF_COUNT_MAX,
792 ensures
793 i == addr_len,
794 decreases addr_len - i,
795 {
796 if paddr >= end {
797 break;
798 }
799 let ghost slot_idx: usize = frame_to_index(paddr);
800 let ghost perm_idx: int = first_perm_idx + i;
801
802 proof {
803 owner.relate_regions_at(old_regions, perm_idx);
804 assert(regions.slot_owners[slot_idx] == old_regions.slot_owners[slot_idx]);
805 }
806
807 unsafe {
808 #[verus_spec(with Tracked(regions))]
809 crate::mm::frame::inc_frame_ref_count(paddr)
810 };
811
812 paddr = paddr + PAGE_SIZE;
813
814 proof {
815 i = i + 1;
816 assert forall|j: int|
817 #![trigger frame_to_index((self.range.start + j * PAGE_SIZE) as usize)]
818 first_perm_idx + i <= j < last_perm_idx implies (
819 *regions).slot_owners[frame_to_index((self.range.start + j * PAGE_SIZE) as usize)]
820 == old_regions.slot_owners[frame_to_index(
821 (self.range.start + j * PAGE_SIZE) as usize,
822 )] by {
823 let _ = frame_to_index((self.range.start + perm_idx * PAGE_SIZE) as usize);
824 let _ = frame_to_index((self.range.start + j * PAGE_SIZE) as usize);
825 };
826 }
827 }
828
829 Self { range: start..end, _marker: core::marker::PhantomData }
830 }
831
832 #[verus_spec(r =>
848 with
849 Tracked(regions): Tracked<&mut MetaRegionOwners>,
850 Tracked(owner): Tracked<SegmentOwner<M>>,
851 -> frame_perms: Tracked<SegmentOwner<M>>,
852 requires
853 self.invariants(&owner, *old(regions)),
854 ensures
855 r == self.range(),
856 final(regions).inv(),
857 *final(regions) =~= *old(regions),
858 frame_perms@ == owner,
859 )]
860 pub(crate) fn into_raw(self) -> Range<Paddr> {
861 let range = self.range.clone();
862 let _ = ManuallyDrop::new(self, Tracked(regions));
863
864 proof_with!(|= Tracked(owner));
865 range
866 }
867
868 #[verus_spec(res =>
891 with
892 Tracked(regions): Tracked<&mut MetaRegionOwners>,
893 Tracked(owner): Tracked<&mut SegmentOwner<M>>
894 requires
895 old(self).invariants(old(owner), *old(regions)),
896 ensures
897 final(regions).inv(),
898 final(self).inv(),
899 final(owner).relate_regions(*final(regions)),
900 match res {
901 None => final(self).start_paddr() == old(self).end_paddr(),
902 Some(pair) => {
903 &&& final(self).start_paddr() == old(self).start_paddr() + PAGE_SIZE
904 &&& pair.0.paddr() == old(self).start_paddr()
905 &&& final(regions).slots.contains_key(frame_to_index(pair.0.paddr()))
906 &&& pair.1@.value() == frame_to_index(pair.0.paddr())
907 &&& pair.0.inv_with_regions(*final(regions))
908 &&& final(regions).frame_obligations.count(frame_to_index(pair.0.paddr())) >= 1
909 },
910 },
911 )]
912 pub fn next(&mut self) -> Option<
913 (Frame<M>, Tracked<vstd_extra::drop_tracking::DropObligation<usize>>),
914 > {
915 if self.range.start < self.range.end {
916 proof {
917 owner.relate_regions_at(*old(regions), 0);
918 }
919 proof_decl! {
920 let tracked from_raw_obl: vstd_extra::drop_tracking::DropObligation<usize>;
921 }
922
923 let frame = unsafe {
924 #[verus_spec(with Tracked(regions) => Tracked(from_raw_obl))]
925 Frame::<M>::from_raw(self.range.start)
926 };
927
928 proof {
929 let new_range = ((self.range.start + PAGE_SIZE) as usize)..self.range.end;
930 let tracked redeem_tok = vstd_extra::drop_tracking::DropObligation::tracked_mint(
931 frame.index(),
932 );
933 regions.tracked_redeem_frame_obligation(redeem_tok);
934 assert(regions.frame_obligations =~= old(regions).frame_obligations);
935 owner.range = new_range;
936
937 assert forall|i: int|
938 #![trigger frame_to_index((owner.range.start + i * PAGE_SIZE) as usize)]
939 0 <= i < crate::specs::mm::frame::segment::seg_nframes(owner.range) implies {
940 let idx = frame_to_index((owner.range.start + i * PAGE_SIZE) as usize);
941 &&& regions.frame_obligations.count(idx) >= 1
942 &&& regions.slot_owners.contains_key(idx)
943 &&& regions.slots.contains_key(idx)
944 &&& regions.slot_owners[idx].self_addr == meta_addr(idx)
945 &&& regions.slot_owners[idx].inner_perms.ref_count.value() > 0
946 &&& regions.slot_owners[idx].inner_perms.ref_count.value()
947 <= crate::mm::frame::meta::REF_COUNT_MAX
948 &&& regions.slot_owners[idx].paths_in_pt.is_empty()
949 &&& regions.slot_owners[idx].usage
950 == crate::specs::mm::frame::meta_owners::PageUsage::Frame
951 } by {
952 old(owner).relate_regions_at(*old(regions), i + 1);
953 old(owner).relate_regions_distinct(*old(regions), 0, i + 1);
954 }
955 assert forall|i: int, j: int|
956 #![trigger frame_to_index((owner.range.start + i * PAGE_SIZE) as usize),
957 frame_to_index((owner.range.start + j * PAGE_SIZE) as usize)]
958 0 <= i < j < crate::specs::mm::frame::segment::seg_nframes(
959 owner.range,
960 ) implies frame_to_index((owner.range.start + i * PAGE_SIZE) as usize)
961 != frame_to_index((owner.range.start + j * PAGE_SIZE) as usize) by {
962 old(owner).relate_regions_distinct(*old(regions), i + 1, j + 1);
963 }
964 broadcast use crate::mm::frame::meta::mapping::group_page_meta;
967
968 assert(regions.slots[frame.index()].pptr() == frame.ptr);
969 assert(frame.inv_with_regions(*regions));
970 }
971
972 self.range.start = self.range.start + PAGE_SIZE;
973 Some((frame, Tracked(from_raw_obl)))
974 } else {
975 None
976 }
977 }
978
979 #[verifier::inline]
981 pub open spec fn nrpage_spec(&self) -> usize
982 recommends
983 self.inv(),
984 {
985 self.size() / PAGE_SIZE
986 }
987
988 pub closed spec fn split_spec(self, offset: usize) -> (Self, Self)
990 recommends
991 self.inv(),
992 offset % PAGE_SIZE == 0,
993 0 < offset < self.size(),
994 {
995 let at = (self.start_paddr() + offset) as usize;
996 let idx = at / PAGE_SIZE;
997 (
998 Self { range: self.start_paddr()..at, _marker: core::marker::PhantomData },
999 Self { range: at..self.end_paddr(), _marker: core::marker::PhantomData },
1000 )
1001 }
1002}
1003
1004#[verus_verify]
1005impl<M: AnyFrameMeta + Repr<MetaSlotStorage>> From<Frame<M>> for Segment<M> {
1006 #[verifier::external_body]
1015 fn from(frame: Frame<M>) -> Self {
1016 let pa = frame.start_paddr();
1017 let _ = core::mem::ManuallyDrop::new(frame);
1018 Self { range: pa..(pa + PAGE_SIZE), _marker: core::marker::PhantomData }
1019 }
1020}
1021
1022impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Iterator for Segment<M> {
1023 type Item = Frame<M>;
1024
1025 #[verifier::external_body]
1032 fn next(&mut self) -> Option<Self::Item> {
1033 if self.range.start < self.range.end {
1034 let frame = unsafe { Frame::<M>::from_raw(self.range.start) };
1037 self.range.start = self.range.start + PAGE_SIZE;
1038 Some(frame)
1039 } else {
1040 None
1041 }
1042 }
1043}
1044
1045impl<M: AnyFrameMeta + Repr<MetaSlotStorage>> Segment<M> {
1046 #[verus_spec(
1055 with Tracked(owner): Tracked<SegmentOwner<M>>,
1056 Tracked(regions): Tracked<&mut MetaRegionOwners>
1057 requires
1058 self.invariants(&owner, *old(regions)),
1059 forall|i: int|
1060 #![trigger frame_to_index((self.range.start + i * PAGE_SIZE) as usize)]
1061 0 <= i < crate::specs::mm::frame::segment::seg_nframes(self.range) ==> {
1062 let idx = frame_to_index((self.range.start + i * PAGE_SIZE) as usize);
1063 old(regions).slot_owners[idx].inner_perms.ref_count.value() == 1 ==> {
1064 &&& old(regions).slot_owners[idx].inner_perms.storage.is_init()
1065 &&& old(regions).slot_owners[idx].inner_perms.in_list.value() == 0
1066 }
1067 },
1068 ensures
1069 final(regions).inv(),
1070 )]
1071 pub fn drop(self) {
1072 let tracked owner = owner;
1073 let ghost old_owner = owner;
1074 let ghost n = crate::specs::mm::frame::segment::seg_nframes(self.range);
1075 let mut paddr = self.range.start;
1076
1077 let ghost mut k: int = 0;
1078
1079 let ghost old_owner = owner;
1080
1081 assert forall|i: int| #![trigger frame_idx_at(self.range.start, i)] 0 <= i < n implies {
1082 let idx = frame_idx_at(self.range.start, i);
1083 old(regions).slot_owners[idx].inner_perms.ref_count.value() == 1 ==> {
1084 &&& old(regions).slot_owners[idx].inner_perms.storage.is_init()
1085 &&& old(regions).slot_owners[idx].inner_perms.in_list.value() == 0
1086 }
1087 } by {};
1088
1089 proof {
1090 assert(old_owner.range == self.range);
1091 assert forall|i: int|
1092 #![trigger frame_to_index((self.range.start + i * PAGE_SIZE) as usize)]
1093 0 <= i < n implies old(regions).frame_obligations.count(
1094 frame_to_index((self.range.start + i * PAGE_SIZE) as usize),
1095 ) >= 1 by {
1096 old_owner.relate_regions_at(*old(regions), i);
1097 };
1098 assert forall|i: int, j: int|
1099 #![trigger frame_to_index((self.range.start + i * PAGE_SIZE) as usize),
1100 frame_to_index((self.range.start + j * PAGE_SIZE) as usize)]
1101 0 <= i < j < n implies frame_to_index((self.range.start + i * PAGE_SIZE) as usize)
1102 != frame_to_index((self.range.start + j * PAGE_SIZE) as usize) by {
1103 old_owner.relate_regions_distinct(*old(regions), i, j);
1104 };
1105 crate::specs::mm::frame::segment::tracked_redeem_seg_obligations(
1106 regions,
1107 self.range.start,
1108 n,
1109 );
1110 }
1111
1112 loop
1113 invariant
1114 regions.inv(),
1115 self.inv(),
1116 self.range.start <= paddr <= self.range.end,
1117 paddr == (self.range.start + k * PAGE_SIZE) as usize,
1118 paddr % PAGE_SIZE == 0,
1119 paddr <= MAX_PADDR,
1120 0 <= k <= n,
1121 n == (self.range.end - self.range.start) as int / PAGE_SIZE as int,
1122 paddr < self.range.end <==> k < n,
1123 forall|j: int|
1124 #![trigger frame_to_index((self.range.start + j * PAGE_SIZE) as usize)]
1125 k <= j < n ==> {
1126 let idx = frame_to_index((self.range.start + j * PAGE_SIZE) as usize);
1127 &&& regions.slot_owners.contains_key(idx)
1128 &&& regions.slots.contains_key(idx)
1129 &&& regions.slot_owners[idx] == old(regions).slot_owners[idx]
1130 },
1131 forall|j: int|
1132 #![trigger frame_idx_at(self.range.start, j)]
1133 k <= j < n ==> regions.slot_owners.contains_key(
1134 frame_idx_at(self.range.start, j),
1135 ) && regions.slot_owners[frame_idx_at(self.range.start, j)] == old(
1136 regions,
1137 ).slot_owners[frame_idx_at(self.range.start, j)],
1138 regions.slot_owners.dom() =~= old(regions).slot_owners.dom(),
1139 self.wf(&old_owner),
1140 old_owner.inv(),
1141 old(regions).inv(),
1142 old_owner.relate_regions(*old(regions)),
1143 old_owner.range == self.range,
1144 forall|i: int|
1145 #![trigger frame_to_index((self.range.start + i * PAGE_SIZE) as usize)]
1146 0 <= i < n ==> {
1147 let idx = frame_to_index((self.range.start + i * PAGE_SIZE) as usize);
1148 old(regions).slot_owners[idx].inner_perms.ref_count.value() == 1 ==> {
1149 &&& old(regions).slot_owners[idx].inner_perms.storage.is_init()
1150 &&& old(regions).slot_owners[idx].inner_perms.in_list.value() == 0
1151 }
1152 },
1153 decreases n - k,
1154 {
1155 if paddr >= self.range.end {
1156 break;
1157 }
1158 proof {
1159 old_owner.relate_regions_at(*old(regions), k);
1160 }
1161
1162 proof_decl! {
1163 let tracked from_raw_obl: vstd_extra::drop_tracking::DropObligation<usize>;
1164 }
1165
1166 let frame = unsafe {
1172 #[verus_spec(with Tracked(regions) => Tracked(from_raw_obl))]
1173 Frame::<M>::from_raw(paddr)
1174 };
1175
1176 frame.drop(Tracked(regions), Tracked(from_raw_obl));
1177
1178 proof {
1179 assert forall|j: int|
1180 #![trigger frame_to_index((self.range.start + j * PAGE_SIZE) as usize)]
1181 (k + 1) <= j < n implies {
1182 let idx = frame_to_index((self.range.start + j * PAGE_SIZE) as usize);
1183 &&& regions.slot_owners.contains_key(idx)
1184 &&& regions.slots.contains_key(idx)
1185 &&& regions.slot_owners[idx] == old(regions).slot_owners[idx]
1186 } by {
1187 old_owner.relate_regions_distinct(*old(regions), k, j);
1188 };
1189 }
1190
1191 paddr = paddr + PAGE_SIZE;
1192
1193 proof {
1194 k = k + 1;
1195 }
1196 }
1197 }
1198}
1199
1200impl<M: AnyFrameMeta + ?Sized> Inv for Segment<M> {
1312 open spec fn inv(self) -> bool {
1317 &&& self.start_paddr() % PAGE_SIZE == 0
1318 &&& self.end_paddr() % PAGE_SIZE == 0
1319 &&& self.start_paddr() <= self.end_paddr() <= MAX_PADDR
1320 }
1321}
1322
1323}