1use vstd::{
4 prelude::*,
5 simple_pptr::{PPtr, PointsTo},
6 std_specs::{convert::FromSpecImpl, iter::IteratorSpecImpl},
7};
8use vstd_extra::{assert, cast_ptr::*, ownership::*, panic::may_panic, prelude::*};
9
10use crate::specs::{
11 arch::*,
12 mm::frame::{
13 frame_specs::FrameRawPerms,
14 mapping::{frame_to_index, group_page_meta, index_to_meta},
15 meta_owners::*,
16 meta_region_owners::MetaRegionOwners,
17 segment::*,
18 },
19};
20
21use super::{
22 Frame, Paddr,
23 meta::mapping::frame_to_meta,
24 meta::{AnyFrameMeta, GetFrameError},
25};
26use crate::mm::frame::{meta::REF_COUNT_MAX, untyped::AnyUFrameMeta};
27use crate::mm::page_table::RCClone;
28use crate::mm::{PagingLevel, Vaddr, frame::MetaSlot, paddr_to_vaddr};
29use core::{fmt::Debug, mem::ManuallyDrop, ops::Range};
30
31verus! {
32
33pub struct Segment<M: AnyFrameMeta + ?Sized> {
47 range: Range<Paddr>,
48 _marker: core::marker::PhantomData<M>,
49 #[cfg(verus_keep_ghost_body)]
51 tracked_perms: Tracked<Option<Seq<FrameRawPerms>>>,
52}
53
54pub type USegment = Segment<dyn AnyUFrameMeta>;
80
81impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> RCClone for Segment<M> {
97 open spec fn clone_requires(self, perm: MetaRegionOwners) -> bool {
98 &&& self.inv()
99 &&& perm.inv()
100 &&& self.relate_regions(perm)
101 &&& forall|pa: Paddr|
102 #![trigger frame_to_index(pa)]
103 (self.start_paddr() <= pa < self.end_paddr() && pa % PAGE_SIZE == 0) ==> {
104 let idx = frame_to_index(pa);
105 &&& perm.contains(idx)
106 &&& valid_frame_paddr(pa)
107 &&& perm.ref_count(idx) > 0
108 &&& perm.ref_count(idx) + 1 < REF_COUNT_MAX
109 &&& !MetaSlot::inc_ref_count_panic_cond(perm.slot_owners[idx].ref_count_perm)
110 }
111 }
112
113 open spec fn clone_ensures(
114 self,
115 old_perm: MetaRegionOwners,
116 new_perm: MetaRegionOwners,
117 res: Self,
118 ) -> bool {
119 &&& res.range() == self.range()
120 &&& res.inv()
121 &&& new_perm.inv()
122 &&& res.relate_regions(new_perm)
123 }
124
125 #[verifier::loop_isolation(false)]
126 #[verifier::rlimit(200)]
127 fn clone(&self, Tracked(perm): Tracked<&mut MetaRegionOwners>) -> (res: Self) {
128 let mut paddr = self.range.start;
129 proof_decl! {
130 let tracked mut raw_perms = Seq::<FrameRawPerms>::tracked_empty();
131 }
132
133 loop
134 invariant
135 perm.inv(),
136 self.inv(),
137 perm.slots == old(perm).slots,
138 perm.slot_owners.dom() == old(perm).slot_owners.dom(),
139 raw_perms.len() == (paddr - self.range.start) / (PAGE_SIZE as int),
140 forall|i: int|
141 #![trigger raw_perms[i]]
142 0 <= i < raw_perms.len() ==> {
143 let idx = frame_to_index((self.range.start + i * PAGE_SIZE) as usize);
144 &&& raw_perms[i].slot_perm == perm.slots[idx]
145 &&& raw_perms[i].inv()
146 &&& raw_perms[i].metadata_perm.id()
147 == perm.slot_owners[idx].metadata_perm.id()
148 },
149 forall|i: int|
150 #![trigger frame_to_index((self.range.start + i * PAGE_SIZE) as usize)]
151 0 <= i < raw_perms.len() ==> ({
152 let idx = frame_to_index((self.range.start + i * PAGE_SIZE) as usize);
153 &&& perm.contains(idx)
154 &&& perm.slot_owners[idx].slot_vaddr == index_to_meta(idx)
155 &&& perm.ref_count(idx) > 0
156 &&& perm.ref_count(idx) <= REF_COUNT_MAX
157 &&& perm.slot_owners[idx].paths_in_pt.is_empty()
158 &&& perm.slot_owners[idx].usage is Frame
159 }),
160 self.range.start <= paddr <= self.range.end,
161 paddr % PAGE_SIZE == 0,
162 paddr <= MAX_PADDR,
163 forall|pa: Paddr|
164 #![trigger frame_to_index(pa)]
165 (paddr <= pa < self.range.end && pa % PAGE_SIZE == 0) ==> {
166 let idx = frame_to_index(pa);
167 &&& perm.contains(idx)
168 &&& valid_frame_paddr(pa)
169 &&& perm.ref_count(idx) > 0
170 &&& perm.ref_count(idx) + 1 < REF_COUNT_MAX
171 &&& !MetaSlot::inc_ref_count_panic_cond(
172 perm.slot_owners[idx].ref_count_perm,
173 )
174 },
175 forall|i: int|
176 #![trigger frame_to_index((self.range.start + i * PAGE_SIZE) as usize)]
177 raw_perms.len() <= i < self.len() ==> perm.slot_owner(
178 (self.range.start + i * PAGE_SIZE) as usize,
179 ) == old(perm).slot_owner((self.range.start + i * PAGE_SIZE) as usize),
180 decreases self.range.end - paddr,
181 {
182 if paddr >= self.range.end {
183 break;
184 }
185 let tracked_permission = unsafe {
186 #[verus_spec(with Tracked(perm))]
187 crate::mm::frame::inc_frame_ref_count(paddr)
188 };
189 let tracked frame_permission = tracked_permission.get();
190 proof {
191 let tracked slot_perm = perm.tracked_borrow_slot(paddr);
192 raw_perms.tracked_push(
193 FrameRawPerms { slot_perm, metadata_perm: frame_permission },
194 );
195 }
196
197 paddr += PAGE_SIZE;
198 }
199
200 Self {
201 range: self.range.start..self.range.end,
202 _marker: core::marker::PhantomData,
203 #[cfg(verus_keep_ghost_body)]
204 tracked_perms: Tracked(Some(raw_perms)),
205 }
206 }
207}
208
209#[verus_verify]
210impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Segment<M> {
211 #[verifier::spinoff_prover]
244 #[verifier::loop_isolation(false)]
245 #[verifier::allow_complex_invariants]
246 #[verus_spec(r =>
247 with
248 Tracked(regions): Tracked<&mut MetaRegionOwners>,
249 Tracked(repr_perm): Tracked<&mut M::ReprPerm>,
250 requires
251 old(regions).inv(),
252 forall|paddr_in: Paddr|
253 (range.start <= paddr_in < range.end && paddr_in % PAGE_SIZE == 0) ==> {
254 &&& metadata_fn.requires((paddr_in,))
255 },
256 forall|paddr_in: Paddr, paddr_out: Paddr, m: M|
257 metadata_fn.ensures((paddr_in,), (paddr_out, m)) ==> paddr_in == paddr_out,
258 !(range.end <= MAX_PADDR ==> range.start < range.end) ==> may_panic(),
259 ensures
260 final(regions).inv(),
261 (range.start % PAGE_SIZE != 0 || range.end % PAGE_SIZE != 0)
262 ==> r == Err::<Self, _>(GetFrameError::NotAligned),
263 (range.start % PAGE_SIZE == 0 && range.end % PAGE_SIZE == 0 && range.end > MAX_PADDR)
264 ==> r == Err::<Self, _>(GetFrameError::OutOfBound),
265 r matches Ok(seg) ==> {
266 &&& seg.inv()
267 &&& seg.start_paddr() == range.start
268 &&& seg.end_paddr() == range.end
269 &&& seg.start_paddr() < seg.end_paddr()
270 &&& seg.relate_regions(*final(regions))
271 &&& forall|paddr: Paddr|
272 #![trigger frame_to_index(paddr)]
273 (range.start <= paddr < range.end && paddr % PAGE_SIZE == 0)
274 ==> final(regions).contains(frame_to_index(paddr))
275 &&& range.start < range.end <= MAX_PADDR
276 },
277 )]
278 pub fn from_unused(range: Range<Paddr>, metadata_fn: impl Fn(Paddr) -> (Paddr, M)) -> (res:
279 Result<Self, GetFrameError>) {
280 proof_decl! {
281 let tracked mut addrs = Seq::<usize>::tracked_empty();
282 let tracked raw_perms = Seq::<FrameRawPerms>::tracked_empty();
283 }
284
285 if range.start % PAGE_SIZE != 0 || range.end % PAGE_SIZE != 0 {
286 return Err(GetFrameError::NotAligned);
287 }
288 if range.end > MAX_PADDR {
289 return Err(GetFrameError::OutOfBound);
290 }
291 assert!(range.start < range.end);
292
293 proof_with!{ tracked_perms: Tracked(Some(raw_perms)) }
297 let mut segment = Self {
298 range: range.start..range.start,
299 _marker: core::marker::PhantomData,
300 };
301
302 let mut i = 0;
303 let addr_len = (range.end - range.start) / PAGE_SIZE;
304
305 while i < addr_len
306 invariant
307 segment.tracked_perms@ is Some,
308 i <= addr_len,
309 i == addrs.len(),
310 i == segment.tracked_perms@->0.len(),
311 range.start <= range.start + i * PAGE_SIZE <= range.end,
312 range.end == range.start + addr_len * PAGE_SIZE,
313 addr_len == (range.end - range.start) / PAGE_SIZE as int,
314 i <= addr_len,
315 forall|paddr_in: Paddr|
316 (range.start + i * PAGE_SIZE <= paddr_in < range.end && paddr_in % PAGE_SIZE
317 == 0) ==> {
318 &&& metadata_fn.requires((paddr_in,))
319 },
320 forall|paddr_in: Paddr, paddr_out: Paddr, m: M|
321 range.start + i * PAGE_SIZE <= paddr_in < range.end && paddr_in % PAGE_SIZE == 0
322 && metadata_fn.ensures((paddr_in,), (paddr_out, m)) ==> paddr_in
323 == paddr_out,
324 forall|j: int|
325 #![trigger addrs[j]]
326 0 <= j < addrs.len() ==> {
327 let idx = frame_to_index(addrs[j]);
328 &&& regions.contains(idx)
329 &&& regions.slot_owners[idx].slot_vaddr == index_to_meta(idx)
330 &&& 0 < regions.ref_count(idx) <= REF_COUNT_MAX
331 &&& segment.tracked_perms@->0[j].inv()
332 &&& segment.tracked_perms@->0[j].slot_perm == regions.slots[idx]
333 &&& segment.tracked_perms@->0[j].metadata_perm.id()
334 == regions.slot_owners[idx].metadata_perm.id()
335 &&& regions.slot_owners[idx].paths_in_pt.is_empty()
336 &&& regions.slot_owners[idx].usage is Frame
337 &&& addrs[j] % PAGE_SIZE == 0
338 &&& addrs[j] < MAX_PADDR
339 &&& addrs[j] == range.start + (j as u64) * PAGE_SIZE
340 },
341 regions.inv(),
342 regions.slot_owners.dom() == old(regions).slot_owners.dom(),
343 segment.range.end == range.start + i * PAGE_SIZE,
344 ensures
345 i == addr_len,
346 decreases addr_len - i,
347 {
348 let paddr_in = range.start + i * PAGE_SIZE;
349 let (paddr, meta) = metadata_fn(paddr_in);
350
351 let ghost regions_pre = *regions;
352 let res = #[verus_spec(with Tracked(regions), Tracked(repr_perm))]
353 Frame::<M>::from_unused(paddr, meta);
354 let mut frame = match res {
355 Ok(f) => f,
356 Err(e) => {
357 let mut p = range.start;
358 let ghost mut k: int = 0;
359 while p < segment.range.end
360 invariant
361 regions.inv(),
362 segment.tracked_perms@->0.len() == i - k,
363 regions.slot_owners.dom() == old(regions).slot_owners.dom(),
364 range.start % PAGE_SIZE == 0,
365 i == addrs.len(),
366 segment.range.end == range.start + i * PAGE_SIZE,
367 range.start <= p <= segment.range.end,
368 p == range.start + k * PAGE_SIZE,
369 p % PAGE_SIZE == 0,
370 0 <= k <= i,
371 forall|j: int|
372 #![trigger addrs[j]]
373 k <= j < addrs.len() ==> {
374 let idx = frame_to_index(addrs[j]);
375 &&& regions.contains(idx)
376 &&& regions.slot_owners[idx].slot_vaddr == index_to_meta(idx)
377 &&& 0 < regions.ref_count(idx) <= REF_COUNT_MAX
378 &&& segment.tracked_perms@ is Some
379 &&& segment.tracked_perms@->0[j - k].inv()
380 &&& segment.tracked_perms@->0[j - k].slot_perm
381 == regions.slots[idx]
382 &&& segment.tracked_perms@->0[j - k].metadata_perm.id()
383 == regions.slot_owners[idx].metadata_perm.id()
384 &&& regions.slot_owners[idx].paths_in_pt.is_empty()
385 &&& regions.slot_owners[idx].usage is Frame
386 &&& addrs[j] % PAGE_SIZE == 0
387 &&& addrs[j] < MAX_PADDR
388 &&& addrs[j] == range.start + (j as u64) * PAGE_SIZE
389 },
390 decreases segment.range.end - p,
391 {
392 proof {
393 broadcast use group_page_meta;
394
395 assert(addrs[k] == p);
396
397 }
398 let tracked perm =
399 segment.tracked_perms.tracked_borrow_mut().tracked_pop_front();
400 let frame = unsafe {
401 #[verus_spec(with Tracked(perm))]
402 Frame::<M>::from_raw(p)
403 };
404 frame.drop(Tracked(regions));
405 p += PAGE_SIZE;
406 proof {
407 k = k + 1;
408 }
409 }
410 return Err(e);
411 },
412 };
413
414 proof_decl! {
415 let tracked frame_permission: FracMetadataPerm = frame.tracked_metadata_perm.tracked_take();
416 let tracked slot_perm = *frame.tracked_slot_perm;
417 }
418 let _ = ManuallyDrop::new(frame);
419 segment.range.end = paddr + PAGE_SIZE;
420 proof {
421 broadcast use group_page_meta;
422
423 let idx = frame_to_index(paddr);
424 axiom_mmio_usage_iff_mmio_paddr(regions.slot_owners[idx]);
425 axiom_mmio_usage_iff_mmio_paddr(regions_pre.slot_owners[idx]);
426 addrs.tracked_push(paddr);
427 segment.tracked_perms.tracked_borrow_mut().tracked_push(
428 FrameRawPerms { slot_perm, metadata_perm: frame_permission },
429 );
430 }
431
432 i += 1;
433 }
434
435 proof {
436 assert forall|addr: usize|
437 #![trigger frame_to_index(addr)]
438 range.start <= addr < range.end && addr % PAGE_SIZE == 0 implies {
439 regions.contains(frame_to_index(addr))
440 } by {
441 let j = (addr - range.start) / PAGE_SIZE as int;
442 assert(addrs[j as int] == addr);
443 }
444 assert forall|i: int|
445 #![trigger frame_to_index((segment.range.start + i * PAGE_SIZE) as usize)]
446 0 <= i < segment.len() implies {
447 let idx = frame_to_index((segment.range.start + i * PAGE_SIZE) as usize);
448 &&& segment.tracked_perms@->0[i].inv()
449 &&& segment.tracked_perms@->0[i].slot_perm == regions.slots[idx]
450 &&& segment.tracked_perms@->0[i].metadata_perm.id()
451 == regions.slot_owners[idx].metadata_perm.id()
452 &&& regions.contains(idx)
453 &&& regions.slot_owners[idx].slot_vaddr == index_to_meta(idx)
454 &&& regions.ref_count(idx) > 0
455 &&& regions.ref_count(idx) <= REF_COUNT_MAX
456 &&& regions.slot_owners[idx].paths_in_pt.is_empty()
457 &&& regions.slot_owners[idx].usage is Frame
458 } by {
459 assert(addrs[i] == segment.range.start + i * PAGE_SIZE);
460 }
461
462 }
463
464 Ok(segment)
465 }
466
467 #[verus_spec(r =>
482 with
483 Tracked(raw_perms): Tracked<Seq<FrameRawPerms>>,
484 requires
485 range.start % PAGE_SIZE == 0,
486 range.end % PAGE_SIZE == 0,
487 range.start <= range.end <= MAX_PADDR,
488 raw_perms.len() == (range.end - range.start) / PAGE_SIZE as int,
489 forall |i: int| #![trigger raw_perms[i]]
490 0 <= i < raw_perms.len() ==> {
491 let paddr = (range.start + i * PAGE_SIZE) as usize;
492 &&& raw_perms[i].slot_vaddr() == frame_to_meta(paddr)
493 &&& raw_perms[i].inv()
494 },
495 ensures
496 r.inv(),
497 r.range() == range,
498 )]
499 pub(crate) unsafe fn from_raw(range: Range<Paddr>) -> Self {
500 proof_with!{ tracked_perms: Tracked(Some(raw_perms)) }
501 Self { range, _marker: core::marker::PhantomData }
502 }
503}
504
505#[verus_verify]
506impl<M: AnyFrameMeta + ?Sized> Segment<M> {
507 #[verus_verify(dual_spec)]
509 #[verus_spec(
510 returns
511 self.start_paddr(),
512 )]
513 pub fn start_paddr(&self) -> Paddr {
514 self.range.start
515 }
516
517 #[verus_verify(dual_spec)]
519 #[verus_spec(
520 returns
521 self.end_paddr(),
522 )]
523 pub fn end_paddr(&self) -> Paddr {
524 self.range.end
525 }
526
527 #[verus_verify(dual_spec)]
529 #[verus_spec(r =>
530 requires
531 self.inv(),
532 ensures
533 r == self.end_paddr() - self.start_paddr(),
534 returns
535 self.size()
536 )]
537 pub fn size(&self) -> usize {
538 self.range.end - self.range.start
539 }
540
541 pub open spec fn range(&self) -> Range<Paddr> {
542 self.start_paddr()..self.end_paddr()
543 }
544
545 pub open spec fn len(&self) -> int {
547 (self.size() / PAGE_SIZE) as int
548 }
549
550 pub closed spec fn raw_perms(&self) -> Seq<FrameRawPerms> {
551 self.tracked_perms@->0
552 }
553
554 pub open spec fn metadata_perms(&self) -> Seq<FracMetadataPerm> {
555 self.raw_perms().map_values(|perm: FrameRawPerms| perm.metadata_perm)
556 }
557
558 pub closed spec fn inner_perm_inv(&self) -> bool {
559 self.tracked_perms@ is Some
560 }
561
562 pub open spec fn slot_perms(&self) -> Seq<&'static PointsTo<MetaSlot>> {
563 self.raw_perms().map_values(|perm: FrameRawPerms| perm.slot_perm)
564 }
565}
566
567#[verus_verify]
568impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Segment<M> {
569 #[verus_spec(r =>
583 requires
584 self.inv(),
585 offset % PAGE_SIZE != 0 ==> may_panic(),
586 !(0 < offset && offset < self.size()) ==> may_panic(),
587 ensures
588 (r.0, r.1) == self.split_spec(offset),
589 )]
590 #[verifier::spinoff_prover]
591 pub fn split(mut self, offset: usize) -> (Self, Self) {
592 assert!(offset % PAGE_SIZE == 0);
593 assert!(0 < offset && offset < self.size());
594
595 let tracked mut left_perms = self.tracked_perms.tracked_take();
596 let tracked right_perms = seq_tracked_split_at(
597 &mut left_perms,
598 (offset / PAGE_SIZE) as int,
599 );
600 let old = ManuallyDrop::new(self);
601 let at = old.range.start + offset;
602
603 (
604 Self {
605 range: old.range.start..at,
606 _marker: core::marker::PhantomData,
607 #[cfg(verus_keep_ghost_body)]
608 tracked_perms: Tracked(Some(left_perms)),
609 },
610 Self {
611 range: at..old.range.end,
612 _marker: core::marker::PhantomData,
613 #[cfg(verus_keep_ghost_body)]
614 tracked_perms: Tracked(Some(right_perms)),
615 },
616 )
617 }
618
619 pub open spec fn page_in_range_saturated(
629 self,
630 range: &Range<usize>,
631 regions: MetaRegionOwners,
632 ) -> bool {
633 exists|j: int|
634 #![trigger frame_to_index((self.start_paddr() + j * PAGE_SIZE) as usize)]
635 (range.start as int) / (PAGE_SIZE as int) <= j < (range.end as int) / (PAGE_SIZE as int)
636 && regions.slot_owner((self.start_paddr() + j * PAGE_SIZE) as usize).ref_count()
637 >= REF_COUNT_MAX
638 }
639
640 #[verus_spec(r =>
657 with
658 Tracked(regions): Tracked<&mut MetaRegionOwners>,
659 requires
660 self.inv(),
661 old(regions).inv(),
662 self.relate_regions(*old(regions)),
663 range.start % PAGE_SIZE != 0 ==> may_panic(),
664 range.end % PAGE_SIZE != 0 ==> may_panic(),
665 range.start > range.end ==> may_panic(),
666 range.end > self.size() ==> may_panic(),
667 self.page_in_range_saturated(range, *old(regions)) ==> may_panic(),
668 ensures
669 range.start % PAGE_SIZE == 0,
670 range.end % PAGE_SIZE == 0,
671 range.start <= range.end,
672 self.start_paddr() + range.end <= self.end_paddr(),
673 !self.page_in_range_saturated(range, *old(regions)),
674 r.inv(),
675 r.start_paddr() == self.start_paddr() + range.start,
676 r.end_paddr() == self.start_paddr() + range.end,
677 r.end_paddr() <= self.end_paddr(),
678 final(regions).inv(),
679 final(regions).slots == old(regions).slots,
680 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
681 r.relate_regions(*final(regions)),
682 )]
683 #[verifier::spinoff_prover]
684 #[verifier::loop_isolation(false)]
685 #[verifier::rlimit(200)]
686 pub fn slice(&self, range: &Range<usize>) -> Self {
687 assert!(range.start % PAGE_SIZE == 0 && range.end % PAGE_SIZE == 0);
688 assert!(range.start <= range.end && range.end <= self.size());
689 let start = self.range.start + range.start;
690 let end = self.range.start + range.end;
691
692 let mut paddr = start;
693 let ghost addr_len = (end - start) / PAGE_SIZE as int;
694 let ghost first_perm_idx: int = (range.start / PAGE_SIZE) as int;
695 let ghost last_perm_idx: int = (range.end / PAGE_SIZE) as int;
696 let ghost mut i: int = 0;
697 proof_decl! {
698 let tracked mut raw_perms = Seq::<FrameRawPerms>::tracked_empty();
699 }
700 loop
701 invariant
702 self.page_in_range_saturated(range, *old(regions)) ==> may_panic(),
703 regions.inv(),
704 regions.slots == old(regions).slots,
705 regions.slot_owners.dom() == old(regions).slot_owners.dom(),
706 raw_perms.len() == i,
707 forall|j: int|
708 #![trigger raw_perms[j]]
709 0 <= j < raw_perms.len() ==> {
710 let idx = frame_to_index((start + j * PAGE_SIZE) as usize);
711 &&& raw_perms[j].slot_perm == regions.slots[idx]
712 &&& raw_perms[j].inv()
713 &&& raw_perms[j].metadata_perm.id()
714 == regions.slot_owners[idx].metadata_perm.id()
715 },
716 forall|j: int|
717 #![trigger frame_to_index((start + j * PAGE_SIZE) as usize)]
718 0 <= j < raw_perms.len() ==> {
719 let idx = frame_to_index((start + j * PAGE_SIZE) as usize);
720 &&& regions.contains(idx)
721 &&& regions.slot_owners[idx].slot_vaddr == index_to_meta(idx)
722 &&& regions.ref_count(idx) > 0
723 &&& regions.ref_count(idx) <= REF_COUNT_MAX
724 &&& regions.slot_owners[idx].paths_in_pt.is_empty()
725 &&& regions.slot_owners[idx].usage is Frame
726 },
727 paddr == (start + i * PAGE_SIZE) as usize,
728 paddr <= end,
729 0 <= i <= addr_len,
730 paddr < end <==> i < addr_len,
731 forall|j: int|
732 #![trigger frame_to_index((self.range.start + j * PAGE_SIZE) as usize)]
733 first_perm_idx + i <= j < last_perm_idx ==> (*regions).slot_owner(
734 (self.range.start + j * PAGE_SIZE) as usize,
735 ) == old(regions).slot_owner((self.range.start + j * PAGE_SIZE) as usize),
736 forall|j: int|
737 #![trigger frame_to_index((self.range.start + j * PAGE_SIZE) as usize)]
738 first_perm_idx <= j < first_perm_idx + i ==> old(regions).slot_owner(
739 (self.range.start + j * PAGE_SIZE) as usize,
740 ).ref_count() < REF_COUNT_MAX,
741 decreases addr_len - i,
742 {
743 if paddr >= end {
744 break;
745 }
746 let ghost perm_idx: int = first_perm_idx + i;
747
748 proof {
749 assert(paddr == (self.range.start + perm_idx * PAGE_SIZE) as usize);
750 }
751
752 let tracked_permission = unsafe {
753 #[verus_spec(with Tracked(regions))]
754 crate::mm::frame::inc_frame_ref_count(paddr)
755 };
756 let tracked frame_permission = tracked_permission.get();
757 proof {
758 let tracked slot_perm = regions.tracked_borrow_slot(paddr);
759 raw_perms.tracked_push(
760 FrameRawPerms { slot_perm, metadata_perm: frame_permission },
761 );
762 }
763
764 paddr += PAGE_SIZE;
765
766 proof {
767 i = i + 1;
768 }
769 }
770
771 proof_with!{ tracked_perms: Tracked(Some(raw_perms)) }
772 Self { range: start..end, _marker: core::marker::PhantomData }
773 }
774
775 #[verus_spec(r =>
783 with
784 -> raw_perms: Tracked<Seq<FrameRawPerms>>,
785 requires
786 self.inv(),
787 ensures
788 r == self.range(),
789 raw_perms@ == self.raw_perms(),
790 )]
791 pub(crate) fn into_raw(mut self) -> Range<Paddr> {
792 let range = self.range.clone();
793
794 proof_decl!{
795 let tracked raw_perms = self.tracked_perms.tracked_take();
796 }
797
798 let _ = ManuallyDrop::new(self);
799
800 proof_with!(|= Tracked(raw_perms));
801 range
802 }
803
804 pub closed spec fn split_spec(self, offset: usize) -> (Self, Self)
806 recommends
807 offset % PAGE_SIZE == 0,
808 0 < offset < self.size(),
809 {
810 let at = (self.start_paddr() + offset) as usize;
811 let idx = offset / PAGE_SIZE;
812 (
813 Self {
814 range: self.start_paddr()..at,
815 _marker: core::marker::PhantomData,
816 #[cfg(verus_keep_ghost_body)]
817 tracked_perms: Tracked(Some(self.raw_perms()[..idx])),
818 },
819 Self {
820 range: at..self.end_paddr(),
821 _marker: core::marker::PhantomData,
822 #[cfg(verus_keep_ghost_body)]
823 tracked_perms: Tracked(Some(self.raw_perms()[idx..])),
824 },
825 )
826 }
827}
828
829impl<M: AnyFrameMeta + Repr<MetaSlotStorage>> FromSpecImpl<Frame<M>> for Segment<M> {
830 open spec fn obeys_from_spec() -> bool {
831 true
832 }
833
834 closed spec fn from_spec(frame: Frame<M>) -> Self {
835 let paddr = frame.start_paddr_spec();
836 let slot_perm = frame.slot_perm();
837 let metadata_perm = frame.frac_metadata_perm();
838 let perm =
839 seq!{
840 FrameRawPerms { slot_perm: &slot_perm, metadata_perm}
841 };
842 Self {
843 range: paddr..(paddr + PAGE_SIZE) as usize,
844 _marker: core::marker::PhantomData,
845 #[cfg(verus_keep_ghost_body)]
846 tracked_perms: Tracked(Some(perm)),
847 }
848 }
849}
850
851#[verus_verify]
852impl<M: AnyFrameMeta + Repr<MetaSlotStorage>> From<Frame<M>> for Segment<M> {
853 fn from(frame: Frame<M>) -> Self {
854 assume(frame.inv());
855
856 let mut frame = frame;
857 let pa = frame.start_paddr();
858 proof_decl!{
859 let tracked frame_perm =
860 FrameRawPerms{
861 slot_perm: *frame.tracked_slot_perm.borrow(),
862 metadata_perm: frame.tracked_metadata_perm.tracked_take()
863 };
864 let tracked perms = Seq::tracked_empty();
865 perms.tracked_push(frame_perm);
866 }
867 let _ = ManuallyDrop::new(frame);
868 Self {
869 range: pa..(pa + PAGE_SIZE),
870 _marker: core::marker::PhantomData,
871 #[cfg(verus_keep_ghost_body)]
872 tracked_perms: Tracked(Some(perms)),
873 }
874 }
875}
876
877impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Iterator for Segment<M> {
878 type Item = Frame<M>;
879
880 #[verifier::rlimit(200)]
881 fn next(&mut self) -> Option<Self::Item> {
882 proof {
883 assume(self.inv());
886 }
887
888 if self.range.start < self.range.end {
889 proof {
890 assert(self.raw_perms()[0].slot_perm == self.slot_perms()[0]);
891 assert(self.raw_perms()[0].metadata_perm == self.metadata_perms()[0]);
892 }
893 let tracked mut raw_perms = self.tracked_perms.tracked_borrow_mut();
894 let tracked perm = raw_perms.tracked_pop_front();
895 proof {
896 assert(perm.inv());
897 assert(perm.slot_vaddr() == frame_to_meta(self.range.start));
898 }
899 let frame = unsafe {
902 #[verus_spec(with Tracked(perm))]
903 Frame::<M>::from_raw(self.range.start)
904 };
905 self.range.start += PAGE_SIZE;
906 Some(frame)
907 } else {
908 None
909 }
910 }
911}
912
913impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> IteratorSpecImpl for Segment<M> {
914 open spec fn obeys_prophetic_iter_laws(&self) -> bool {
915 true
916 }
917
918 #[verifier::prophetic]
919 closed spec fn remaining(&self) -> Seq<Self::Item> {
920 Seq::new(
921 self.metadata_perms().len() as nat,
922 |i: int|
923 {
924 Frame::<M>::from_raw_spec(
925 (self.range().start + i * PAGE_SIZE) as usize,
926 self.slot_perms()[i],
927 Some(self.metadata_perms()[i]),
928 )
929 },
930 )
931 }
932
933 #[verifier::prophetic]
934 closed spec fn will_return_none(&self) -> bool {
935 true
936 }
937
938 closed spec fn decrease(&self) -> Option<nat> {
939 Some(self.len() as nat)
940 }
941
942 open spec fn peek(&self, index: int) -> Option<Self::Item> {
943 if 0 <= index < self.metadata_perms().len() {
944 Some(
945 Frame::<M>::from_raw_spec(
946 (self.range().start + index * PAGE_SIZE) as usize,
947 self.slot_perms()[index],
948 Some(self.metadata_perms()[index]),
949 ),
950 )
951 } else {
952 None
953 }
954 }
955}
956
957impl<M: AnyFrameMeta + Repr<MetaSlotStorage>> Segment<M> {
958 #[verus_spec(
959 with Tracked(regions): Tracked<&mut MetaRegionOwners>
960 requires
961 old(regions).inv(),
962 self.inv(),
963 self.relate_regions(*old(regions)),
964 forall|i: int|
965 #![trigger frame_to_index((self.start_paddr() + i * PAGE_SIZE) as usize)]
966 0 <= i < self.len() ==> {
967 let idx = frame_to_index((self.start_paddr() + i * PAGE_SIZE) as usize);
968 &&& old(regions).slot_owners[idx].storage_perm().is_init()
969 &&& old(regions).ref_count(idx) == 1 ==> {
970 &&& old(regions).slot_owners[idx].in_list_perm.value() == 0
971 }
972 },
973 ensures
974 final(regions).inv(),
975 )]
976 pub fn drop(self) {
977 let ghost n = self.len();
978 let mut paddr = self.range.start;
979 let tracked mut raw_perms = self.tracked_perms.get().tracked_unwrap();
980
981 let ghost mut k: int = 0;
982
983 loop
984 invariant
985 old(regions).inv(),
986 regions.inv(),
987 self.inv(),
988 raw_perms.len() == n - k,
989 forall|j: int|
990 #![trigger raw_perms[j]]
991 0 <= j < raw_perms.len() ==> {
992 let idx = frame_to_index((self.range.start + (k + j) * PAGE_SIZE) as usize);
993 &&& raw_perms[j].inv()
994 &&& raw_perms[j].slot_perm == regions.slots[idx]
995 &&& raw_perms[j].metadata_perm.id()
996 == regions.slot_owners[idx].metadata_perm.id()
997 },
998 self.range.start <= paddr <= self.range.end,
999 paddr == (self.range.start + k * PAGE_SIZE) as usize,
1000 paddr % PAGE_SIZE == 0,
1001 paddr <= MAX_PADDR,
1002 0 <= k <= n,
1003 n == (self.range.end - self.range.start) / PAGE_SIZE as int,
1004 paddr < self.range.end <==> k < n,
1005 forall|j: int|
1006 #![trigger frame_to_index((self.range.start + j * PAGE_SIZE) as usize)]
1007 k <= j < n ==> {
1008 let idx = frame_to_index((self.range.start + j * PAGE_SIZE) as usize);
1009 &&& regions.contains(idx)
1010 &&& regions.slot_owners[idx] == old(regions).slot_owners[idx]
1011 },
1012 forall|j: int|
1013 #![trigger frame_idx_at(self.range.start, j)]
1014 k <= j < n ==> regions.contains(frame_idx_at(self.range.start, j))
1015 && regions.slot_owners[frame_idx_at(self.range.start, j)] == old(
1016 regions,
1017 ).slot_owners[frame_idx_at(self.range.start, j)],
1018 regions.slot_owners.dom() == old(regions).slot_owners.dom(),
1019 self.relate_regions(*old(regions)),
1020 forall|i: int|
1021 #![trigger frame_to_index((self.range.start + i * PAGE_SIZE) as usize)]
1022 0 <= i < n ==> {
1023 let idx = frame_to_index((self.range.start + i * PAGE_SIZE) as usize);
1024 &&& old(regions).slot_owners[idx].storage_perm().is_init()
1025 &&& old(regions).ref_count(idx) == 1 ==> {
1026 &&& old(regions).slot_owners[idx].in_list_perm.value() == 0
1027 }
1028 },
1029 decreases n - k,
1030 {
1031 if paddr >= self.range.end {
1032 break;
1033 }
1034 let tracked perm = raw_perms.tracked_pop_front();
1035 let frame = unsafe {
1036 #[verus_spec(with Tracked(perm))]
1037 Frame::<M>::from_raw(paddr)
1038 };
1039
1040 frame.drop(Tracked(regions));
1041
1042 paddr += PAGE_SIZE;
1043
1044 proof {
1045 k = k + 1;
1046 }
1047 }
1048 }
1049}
1050
1051impl<M: AnyFrameMeta + ?Sized> Inv for Segment<M> {
1157 open spec fn inv(self) -> bool {
1162 &&& self.start_paddr() % PAGE_SIZE == 0
1163 &&& self.end_paddr() % PAGE_SIZE == 0
1164 &&& self.start_paddr() <= self.end_paddr() <= MAX_PADDR
1165 &&& self.inner_perm_inv()
1166 &&& self.raw_perms().len() == self.len()
1167 &&& forall|i: int|
1168 #![trigger self.raw_perms()[i]]
1169 0 <= i < self.raw_perms().len() ==> {
1170 let paddr = (self.range().start + i * PAGE_SIZE) as usize;
1171 &&& self.raw_perms()[i].slot_vaddr() == frame_to_meta(paddr)
1172 &&& self.raw_perms()[i].inv()
1173 }
1174 }
1175}
1176
1177}