1use vstd::{
4 prelude::*,
5 simple_pptr::{PPtr, PointsTo},
6 std_specs::{
7 convert::FromSpecImpl,
8 iter::{IteratorSpec, IteratorSpecImpl},
9 },
10};
11use vstd_extra::{assert, cast_ptr::*, ownership::*, panic::may_panic, prelude::*};
12
13use crate::specs::{
14 arch::*,
15 mm::frame::{
16 frame_specs::FrameRawPerms, mapping::*, meta_owners::*,
17 meta_region_owners::MetaRegionOwners, 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::rlimit(200)]
126 fn clone(&self, Tracked(perm): Tracked<&mut MetaRegionOwners>) -> (res: Self) {
127 let mut paddr = self.range.start;
128 proof_decl! {
129 let tracked mut raw_perms = Seq::<FrameRawPerms>::tracked_empty();
130 }
131
132 loop
133 invariant
134 perm.inv(),
135 self.inv(),
136 self.relate_regions(*old(perm)),
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
159 == raw_perms[i].metadata_perm.resource().usage()
160 }),
161 self.range.start <= paddr <= self.range.end,
162 paddr % PAGE_SIZE == 0,
163 paddr <= MAX_PADDR,
164 forall|pa: Paddr|
165 #![trigger frame_to_index(pa)]
166 (paddr <= pa < self.range.end && pa % PAGE_SIZE == 0) ==> {
167 let idx = frame_to_index(pa);
168 &&& perm.contains(idx)
169 &&& valid_frame_paddr(pa)
170 &&& perm.ref_count(idx) > 0
171 &&& perm.ref_count(idx) + 1 < REF_COUNT_MAX
172 &&& !MetaSlot::inc_ref_count_panic_cond(
173 perm.slot_owners[idx].ref_count_perm,
174 )
175 },
176 forall|i: int|
177 #![trigger frame_to_index((self.range.start + i * PAGE_SIZE) as usize)]
178 raw_perms.len() <= i < self.len() ==> perm.slot_owner(
179 (self.range.start + i * PAGE_SIZE) as usize,
180 ) == old(perm).slot_owner((self.range.start + i * PAGE_SIZE) as usize),
181 ensures
182 paddr == self.range.end,
183 decreases self.range.end - paddr,
184 {
185 if paddr >= self.range.end {
186 break;
187 }
188 let tracked_permission = unsafe {
189 #[verus_spec(with Tracked(perm))]
190 crate::mm::frame::inc_frame_ref_count(paddr)
191 };
192 let tracked frame_permission = tracked_permission.get();
193 proof {
194 frame_permission.agree(
195 &self.tracked_perms.borrow().tracked_borrow().tracked_borrow(
196 raw_perms.len() as int,
197 ).metadata_perm,
198 );
199 let tracked slot_perm = perm.tracked_borrow_slot(paddr);
200 raw_perms.tracked_push(
201 FrameRawPerms { slot_perm, metadata_perm: frame_permission },
202 );
203 }
204
205 paddr += PAGE_SIZE;
206 }
207
208 Self {
209 range: self.range.start..self.range.end,
210 _marker: core::marker::PhantomData,
211 #[cfg(verus_keep_ghost_body)]
212 tracked_perms: Tracked(Some(raw_perms)),
213 }
214 }
215}
216
217#[verus_verify]
218impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Segment<M> {
219 #[verifier::spinoff_prover]
252 #[verus_spec(r =>
253 with
254 Tracked(regions): Tracked<&mut MetaRegionOwners>,
255 Tracked(repr_perm): Tracked<&mut M::ReprPerm>,
256 requires
257 old(regions).inv(),
258 forall|paddr_in: Paddr|
259 (range.start <= paddr_in < range.end && paddr_in % PAGE_SIZE == 0) ==> {
260 &&& metadata_fn.requires((paddr_in,))
261 },
262 forall|paddr_in: Paddr, paddr_out: Paddr, m: M|
263 metadata_fn.ensures((paddr_in,), (paddr_out, m)) ==> paddr_in == paddr_out,
264 !(range.end <= MAX_PADDR ==> range.start < range.end) ==> may_panic(),
265 ensures
266 final(regions).inv(),
267 (range.start % PAGE_SIZE != 0 || range.end % PAGE_SIZE != 0)
268 ==> r == Err::<Self, _>(GetFrameError::NotAligned),
269 (range.start % PAGE_SIZE == 0 && range.end % PAGE_SIZE == 0 && range.end > MAX_PADDR)
270 ==> r == Err::<Self, _>(GetFrameError::OutOfBound),
271 r matches Ok(seg) ==> {
272 &&& seg.inv()
273 &&& seg.start_paddr() == range.start
274 &&& seg.end_paddr() == range.end
275 &&& seg.start_paddr() < seg.end_paddr()
276 &&& seg.relate_regions(*final(regions))
277 &&& forall|paddr: Paddr|
278 #![trigger frame_to_index(paddr)]
279 (range.start <= paddr < range.end && paddr % PAGE_SIZE == 0)
280 ==> final(regions).contains(frame_to_index(paddr))
281 &&& range.start < range.end <= MAX_PADDR
282 },
283 )]
284 pub fn from_unused(range: Range<Paddr>, metadata_fn: impl Fn(Paddr) -> (Paddr, M)) -> (res:
285 Result<Self, GetFrameError>) {
286 proof_decl! {
287 let tracked raw_perms = Seq::<FrameRawPerms>::tracked_empty();
288 }
289
290 if range.start % PAGE_SIZE != 0 || range.end % PAGE_SIZE != 0 {
291 return Err(GetFrameError::NotAligned);
292 }
293 if range.end > MAX_PADDR {
294 return Err(GetFrameError::OutOfBound);
295 }
296 assert!(range.start < range.end);
297
298 proof_with!{ tracked_perms: Tracked(Some(raw_perms)) }
302 let mut segment = Self {
303 range: range.start..range.start,
304 _marker: core::marker::PhantomData,
305 };
306
307 let mut i = 0;
308 let addr_len = (range.end - range.start) / PAGE_SIZE;
309
310 while i < addr_len
311 invariant
312 segment.tracked_perms@ is Some,
313 range.start % PAGE_SIZE == 0,
314 range.end % PAGE_SIZE == 0,
315 range.start < range.end <= MAX_PADDR,
316 segment.range.start == range.start,
317 i <= addr_len,
318 i == segment.tracked_perms@->0.len(),
319 range.start <= range.start + i * PAGE_SIZE <= range.end,
320 range.end == range.start + addr_len * PAGE_SIZE,
321 addr_len == (range.end - range.start) / PAGE_SIZE as int,
322 forall|paddr_in: Paddr|
323 (range.start + i * PAGE_SIZE <= paddr_in < range.end && paddr_in % PAGE_SIZE
324 == 0) ==> {
325 &&& metadata_fn.requires((paddr_in,))
326 },
327 forall|paddr_in: Paddr, paddr_out: Paddr, m: M|
328 range.start + i * PAGE_SIZE <= paddr_in < range.end && paddr_in % PAGE_SIZE == 0
329 && metadata_fn.ensures((paddr_in,), (paddr_out, m)) ==> paddr_in
330 == paddr_out,
331 forall|j: int|
332 #![trigger frame_idx_at(range.start, j)]
333 0 <= j < i ==> {
334 let paddr = (range.start + j * PAGE_SIZE) as usize;
335 let idx = frame_to_index(paddr);
336 &&& regions.contains(idx)
337 &&& regions.slot_owners[idx].slot_vaddr == index_to_meta(idx)
338 &&& 0 < regions.ref_count(idx) <= REF_COUNT_MAX
339 &&& segment.tracked_perms@->0[j].inv()
340 &&& segment.tracked_perms@->0[j].slot_perm == regions.slots[idx]
341 &&& segment.tracked_perms@->0[j].metadata_perm.id()
342 == regions.slot_owners[idx].metadata_perm.id()
343 &&& regions.slot_owners[idx].paths_in_pt.is_empty()
344 &&& regions.slot_owners[idx].usage
345 == segment.tracked_perms@->0[j].metadata_perm.resource().usage()
346 &&& paddr % PAGE_SIZE == 0
347 &&& paddr < MAX_PADDR
348 },
349 regions.inv(),
350 regions.slot_owners.dom() == old(regions).slot_owners.dom(),
351 segment.range.end == range.start + i * PAGE_SIZE,
352 ensures
353 i == addr_len,
354 decreases addr_len - i,
355 {
356 let paddr_in = range.start + i * PAGE_SIZE;
357 let (paddr, meta) = metadata_fn(paddr_in);
358
359 let res = #[verus_spec(with Tracked(regions), Tracked(repr_perm))]
360 Frame::<M>::from_unused(paddr, meta);
361 let mut frame = match res {
362 Ok(f) => f,
363 Err(e) => {
364 let mut p = range.start;
365 let ghost mut k: int = 0;
366 while p < segment.range.end
367 invariant
368 regions.inv(),
369 segment.tracked_perms@ is Some,
370 segment.tracked_perms@->0.len() == i - k,
371 regions.slot_owners.dom() == old(regions).slot_owners.dom(),
372 range.start % PAGE_SIZE == 0,
373 range.end <= MAX_PADDR,
374 segment.range.end == range.start + i * PAGE_SIZE,
375 range.start <= p <= segment.range.end,
376 p == range.start + k * PAGE_SIZE,
377 p % PAGE_SIZE == 0,
378 0 <= k <= i,
379 forall|j: int|
380 #![trigger frame_idx_at(range.start, j)]
381 k <= j < i ==> {
382 let paddr = (range.start + j * PAGE_SIZE) as usize;
383 let idx = frame_to_index(paddr);
384 &&& regions.contains(idx)
385 &&& regions.slot_owners[idx].slot_vaddr == index_to_meta(idx)
386 &&& 0 < regions.ref_count(idx) <= REF_COUNT_MAX
387 &&& segment.tracked_perms@->0[j - k].inv()
388 &&& segment.tracked_perms@->0[j - k].slot_perm
389 == regions.slots[idx]
390 &&& segment.tracked_perms@->0[j - k].metadata_perm.id()
391 == regions.slot_owners[idx].metadata_perm.id()
392 &&& regions.slot_owners[idx].paths_in_pt.is_empty()
393 &&& regions.slot_owners[idx].usage
394 == segment.tracked_perms@->0[j
395 - k].metadata_perm.resource().usage()
396 &&& paddr % PAGE_SIZE == 0
397 &&& paddr < MAX_PADDR
398 },
399 decreases segment.range.end - p,
400 {
401 proof {
402 broadcast use group_page_meta;
403
404 assert(frame_idx_at(range.start, k) == frame_to_index(p));
405
406 }
407 let tracked perm =
408 segment.tracked_perms.tracked_borrow_mut().tracked_pop_front();
409 let frame = unsafe {
410 #[verus_spec(with Tracked(perm))]
411 Frame::<M>::from_raw(p)
412 };
413 frame.drop(Tracked(regions));
414 p += PAGE_SIZE;
415 proof {
416 k = k + 1;
417 }
418 }
419 return Err(e);
420 },
421 };
422
423 proof_decl! {
424 let tracked frame_permission: FracMetadataPerm = frame.tracked_metadata_perm.tracked_take();
425 let tracked slot_perm = *frame.tracked_slot_perm;
426 }
427 let _ = ManuallyDrop::new(frame);
428 segment.range.end = paddr + PAGE_SIZE;
429 proof {
430 broadcast use group_page_meta;
431
432 segment.tracked_perms.tracked_borrow_mut().tracked_push(
433 FrameRawPerms { slot_perm, metadata_perm: frame_permission },
434 );
435 }
436
437 i += 1;
438 }
439
440 proof {
441 assert forall|addr: usize|
442 #![trigger frame_to_index(addr)]
443 range.start <= addr < range.end && addr % PAGE_SIZE == 0 implies {
444 regions.contains(frame_to_index(addr))
445 } by {
446 let j = (addr - range.start) / PAGE_SIZE as int;
447 assert(frame_idx_at(range.start, j) == frame_to_index(addr));
448 }
449 assert forall|i: int|
450 #![trigger frame_to_index((segment.range.start + i * PAGE_SIZE) as usize)]
451 0 <= i < segment.len() implies {
452 let idx = frame_to_index((segment.range.start + i * PAGE_SIZE) as usize);
453 &&& segment.tracked_perms@->0[i].inv()
454 &&& segment.tracked_perms@->0[i].slot_perm == regions.slots[idx]
455 &&& segment.tracked_perms@->0[i].metadata_perm.id()
456 == regions.slot_owners[idx].metadata_perm.id()
457 &&& regions.contains(idx)
458 &&& regions.slot_owners[idx].slot_vaddr == index_to_meta(idx)
459 &&& regions.ref_count(idx) > 0
460 &&& regions.ref_count(idx) <= REF_COUNT_MAX
461 &&& regions.slot_owners[idx].paths_in_pt.is_empty()
462 &&& regions.slot_owners[idx].usage
463 == segment.tracked_perms@->0[i].metadata_perm.resource().usage()
464 } by {
465 assert(frame_idx_at(range.start, i) == frame_to_index(
466 (segment.range.start + i * PAGE_SIZE) as usize,
467 ));
468 }
469
470 }
471
472 Ok(segment)
473 }
474
475 #[verus_spec(r =>
490 with
491 Tracked(raw_perms): Tracked<Seq<FrameRawPerms>>,
492 requires
493 range.start % PAGE_SIZE == 0,
494 range.end % PAGE_SIZE == 0,
495 range.start <= range.end <= MAX_PADDR,
496 raw_perms.len() == (range.end - range.start) / PAGE_SIZE as int,
497 forall |i: int| #![trigger raw_perms[i]]
498 0 <= i < raw_perms.len() ==> {
499 let paddr = (range.start + i * PAGE_SIZE) as usize;
500 &&& raw_perms[i].slot_vaddr() == frame_to_meta(paddr)
501 &&& raw_perms[i].inv()
502 },
503 ensures
504 r.inv(),
505 r.range() == range,
506 )]
507 pub(crate) unsafe fn from_raw(range: Range<Paddr>) -> Self {
508 proof_with!{ tracked_perms: Tracked(Some(raw_perms)) }
509 Self { range, _marker: core::marker::PhantomData }
510 }
511}
512
513#[verus_verify]
514impl<M: AnyFrameMeta + ?Sized> Segment<M> {
515 #[verus_verify(dual_spec)]
517 #[verus_spec(
518 returns
519 self.start_paddr(),
520 )]
521 pub fn start_paddr(&self) -> Paddr {
522 self.range.start
523 }
524
525 #[verus_verify(dual_spec)]
527 #[verus_spec(
528 returns
529 self.end_paddr(),
530 )]
531 pub fn end_paddr(&self) -> Paddr {
532 self.range.end
533 }
534
535 #[verus_verify(dual_spec)]
537 #[verus_spec(r =>
538 requires
539 self.inv(),
540 ensures
541 r == self.end_paddr() - self.start_paddr(),
542 returns
543 self.size()
544 )]
545 pub fn size(&self) -> usize {
546 self.range.end - self.range.start
547 }
548
549 pub open spec fn range(&self) -> Range<Paddr> {
550 self.start_paddr()..self.end_paddr()
551 }
552
553 pub open spec fn len(&self) -> int {
555 (self.size() / PAGE_SIZE) as int
556 }
557
558 pub closed spec fn raw_perms(&self) -> Seq<FrameRawPerms> {
559 self.tracked_perms@->0
560 }
561
562 pub open spec fn metadata_perms(&self) -> Seq<FracMetadataPerm> {
563 self.raw_perms().map_values(|perm: FrameRawPerms| perm.metadata_perm)
564 }
565
566 pub closed spec fn inner_perm_inv(&self) -> bool {
567 self.tracked_perms@ is Some
568 }
569
570 pub open spec fn slot_perms(&self) -> Seq<&'static PointsTo<MetaSlot>> {
571 self.raw_perms().map_values(|perm: FrameRawPerms| perm.slot_perm)
572 }
573}
574
575#[verus_verify]
576impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Segment<M> {
577 #[verus_spec(r =>
591 requires
592 self.inv(),
593 offset % PAGE_SIZE != 0 ==> may_panic(),
594 !(0 < offset && offset < self.size()) ==> may_panic(),
595 ensures
596 (r.0, r.1) == self.split_spec(offset),
597 )]
598 #[verifier::spinoff_prover]
599 pub fn split(mut self, offset: usize) -> (Self, Self) {
600 assert!(offset % PAGE_SIZE == 0);
601 assert!(0 < offset && offset < self.size());
602
603 let tracked mut left_perms = self.tracked_perms.tracked_take();
604 let tracked right_perms = seq_tracked_split_at(
605 &mut left_perms,
606 (offset / PAGE_SIZE) as int,
607 );
608 let old = ManuallyDrop::new(self);
609 let at = old.range.start + offset;
610
611 (
612 Self {
613 range: old.range.start..at,
614 _marker: core::marker::PhantomData,
615 #[cfg(verus_keep_ghost_body)]
616 tracked_perms: Tracked(Some(left_perms)),
617 },
618 Self {
619 range: at..old.range.end,
620 _marker: core::marker::PhantomData,
621 #[cfg(verus_keep_ghost_body)]
622 tracked_perms: Tracked(Some(right_perms)),
623 },
624 )
625 }
626
627 pub open spec fn page_in_range_saturated(
637 self,
638 range: &Range<usize>,
639 regions: MetaRegionOwners,
640 ) -> bool {
641 exists|j: int|
642 #![trigger frame_to_index((self.start_paddr() + j * PAGE_SIZE) as usize)]
643 (range.start as int) / (PAGE_SIZE as int) <= j < (range.end as int) / (PAGE_SIZE as int)
644 && regions.slot_owner((self.start_paddr() + j * PAGE_SIZE) as usize).ref_count()
645 >= REF_COUNT_MAX
646 }
647
648 #[verus_spec(r =>
665 with
666 Tracked(regions): Tracked<&mut MetaRegionOwners>,
667 requires
668 self.inv(),
669 old(regions).inv(),
670 self.relate_regions(*old(regions)),
671 range.start % PAGE_SIZE != 0 ==> may_panic(),
672 range.end % PAGE_SIZE != 0 ==> may_panic(),
673 range.start > range.end ==> may_panic(),
674 range.end > self.size() ==> may_panic(),
675 self.page_in_range_saturated(range, *old(regions)) ==> may_panic(),
676 ensures
677 range.start % PAGE_SIZE == 0,
678 range.end % PAGE_SIZE == 0,
679 range.start <= range.end,
680 self.start_paddr() + range.end <= self.end_paddr(),
681 !self.page_in_range_saturated(range, *old(regions)),
682 r.inv(),
683 r.start_paddr() == self.start_paddr() + range.start,
684 r.end_paddr() == self.start_paddr() + range.end,
685 r.end_paddr() <= self.end_paddr(),
686 final(regions).inv(),
687 final(regions).slots == old(regions).slots,
688 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
689 r.relate_regions(*final(regions)),
690 )]
691 #[verifier::spinoff_prover]
692 pub fn slice(&self, range: &Range<usize>) -> Self {
693 assert!(range.start % PAGE_SIZE == 0 && range.end % PAGE_SIZE == 0);
694 assert!(range.start <= range.end && range.end <= self.size());
695 let start = self.range.start + range.start;
696 let end = self.range.start + range.end;
697
698 let mut paddr = start;
699 let ghost addr_len = (end - start) / PAGE_SIZE as int;
700 let ghost first_perm_idx: int = (range.start / PAGE_SIZE) as int;
701 let ghost mut i: int = 0;
702 proof_decl! {
703 let tracked mut raw_perms = Seq::<FrameRawPerms>::tracked_empty();
704 }
705 loop
706 invariant
707 self.inv(),
708 self.relate_regions(*old(regions)),
709 range.start == first_perm_idx * PAGE_SIZE,
710 range.start <= range.end <= self.size(),
711 start == self.range.start + range.start,
712 end == self.range.start + range.end,
713 end == start + addr_len * PAGE_SIZE,
714 self.page_in_range_saturated(range, *old(regions)) ==> may_panic(),
715 regions.inv(),
716 regions.slots == old(regions).slots,
717 regions.slot_owners.dom() == old(regions).slot_owners.dom(),
718 raw_perms.len() == i,
719 forall|j: int|
720 #![trigger raw_perms[j]]
721 0 <= j < raw_perms.len() ==> {
722 let idx = frame_to_index((start + j * PAGE_SIZE) as usize);
723 &&& raw_perms[j].slot_perm == regions.slots[idx]
724 &&& raw_perms[j].inv()
725 &&& raw_perms[j].metadata_perm.id()
726 == regions.slot_owners[idx].metadata_perm.id()
727 },
728 forall|j: int|
729 #![trigger frame_to_index((start + j * PAGE_SIZE) as usize)]
730 0 <= j < raw_perms.len() ==> {
731 let idx = frame_to_index((start + j * PAGE_SIZE) as usize);
732 &&& regions.contains(idx)
733 &&& regions.slot_owners[idx].slot_vaddr == index_to_meta(idx)
734 &&& regions.ref_count(idx) > 0
735 &&& regions.ref_count(idx) <= REF_COUNT_MAX
736 &&& regions.slot_owners[idx].paths_in_pt.is_empty()
737 &&& regions.slot_owners[idx].usage
738 == raw_perms[j].metadata_perm.resource().usage()
739 },
740 paddr == start + i * PAGE_SIZE,
741 paddr <= end,
742 0 <= i <= addr_len,
743 paddr < end <==> i < addr_len,
744 forall|j: int|
745 #![trigger frame_to_index((self.range.start + j * PAGE_SIZE) as usize)]
746 first_perm_idx + i <= j < first_perm_idx + addr_len ==> (*regions).slot_owner(
747 (self.range.start + j * PAGE_SIZE) as usize,
748 ) == old(regions).slot_owner((self.range.start + j * PAGE_SIZE) as usize),
749 forall|j: int|
750 #![trigger frame_to_index((self.range.start + j * PAGE_SIZE) as usize)]
751 first_perm_idx <= j < first_perm_idx + i ==> old(regions).slot_owner(
752 (self.range.start + j * PAGE_SIZE) as usize,
753 ).ref_count() < REF_COUNT_MAX,
754 ensures
755 paddr == end,
756 i == addr_len,
757 decreases addr_len - i,
758 {
759 if paddr >= end {
760 break;
761 }
762 let ghost perm_idx: int = first_perm_idx + i;
763
764 proof {
765 assert(paddr == (self.range.start + perm_idx * PAGE_SIZE) as usize);
766 }
767
768 let tracked_permission = unsafe {
769 #[verus_spec(with Tracked(regions))]
770 crate::mm::frame::inc_frame_ref_count(paddr)
771 };
772 let tracked frame_permission = tracked_permission.get();
773 proof {
774 frame_permission.agree(
775 &self.tracked_perms.borrow().tracked_borrow().tracked_borrow(
776 perm_idx,
777 ).metadata_perm,
778 );
779 let tracked slot_perm = regions.tracked_borrow_slot(paddr);
780 raw_perms.tracked_push(
781 FrameRawPerms { slot_perm, metadata_perm: frame_permission },
782 );
783 }
784
785 paddr += PAGE_SIZE;
786
787 proof {
788 i = i + 1;
789 }
790 }
791
792 proof_with!{ tracked_perms: Tracked(Some(raw_perms)) }
793 Self { range: start..end, _marker: core::marker::PhantomData }
794 }
795
796 #[verus_spec(r =>
804 with
805 -> raw_perms: Tracked<Seq<FrameRawPerms>>,
806 requires
807 self.inv(),
808 ensures
809 r == self.range(),
810 raw_perms@ == self.raw_perms(),
811 )]
812 pub(crate) fn into_raw(mut self) -> Range<Paddr> {
813 let range = self.range.clone();
814
815 proof_decl!{
816 let tracked raw_perms = self.tracked_perms.tracked_take();
817 }
818
819 let _ = ManuallyDrop::new(self);
820
821 proof_with!(|= Tracked(raw_perms));
822 range
823 }
824
825 pub closed spec fn split_spec(self, offset: usize) -> (Self, Self)
827 recommends
828 offset % PAGE_SIZE == 0,
829 0 < offset < self.size(),
830 {
831 let at = (self.start_paddr() + offset) as usize;
832 let idx = offset / PAGE_SIZE;
833 (
834 Self {
835 range: self.start_paddr()..at,
836 _marker: core::marker::PhantomData,
837 #[cfg(verus_keep_ghost_body)]
838 tracked_perms: Tracked(Some(self.raw_perms()[..idx])),
839 },
840 Self {
841 range: at..self.end_paddr(),
842 _marker: core::marker::PhantomData,
843 #[cfg(verus_keep_ghost_body)]
844 tracked_perms: Tracked(Some(self.raw_perms()[idx..])),
845 },
846 )
847 }
848}
849
850impl<M: AnyFrameMeta + Repr<MetaSlotStorage>> FromSpecImpl<Frame<M>> for Segment<M> {
851 open spec fn obeys_from_spec() -> bool {
852 true
853 }
854
855 closed spec fn from_spec(frame: Frame<M>) -> Self {
856 let paddr = frame.start_paddr_spec();
857 let slot_perm = frame.slot_perm();
858 let metadata_perm = frame.frac_metadata_perm();
859 let perm =
860 seq!{
861 FrameRawPerms { slot_perm: &slot_perm, metadata_perm}
862 };
863 Self {
864 range: paddr..(paddr + PAGE_SIZE) as usize,
865 _marker: core::marker::PhantomData,
866 #[cfg(verus_keep_ghost_body)]
867 tracked_perms: Tracked(Some(perm)),
868 }
869 }
870}
871
872#[verus_verify]
873impl<M: AnyFrameMeta + Repr<MetaSlotStorage>> From<Frame<M>> for Segment<M> {
874 fn from(frame: Frame<M>) -> Self {
875 assume(frame.inv());
876
877 let mut frame = frame;
878 let pa = frame.start_paddr();
879 proof_decl!{
880 let tracked frame_perm =
881 FrameRawPerms{
882 slot_perm: *frame.tracked_slot_perm.borrow(),
883 metadata_perm: frame.tracked_metadata_perm.tracked_take()
884 };
885 let tracked perms = Seq::tracked_empty();
886 perms.tracked_push(frame_perm);
887 }
888 let _ = ManuallyDrop::new(frame);
889 Self {
890 range: pa..(pa + PAGE_SIZE),
891 _marker: core::marker::PhantomData,
892 #[cfg(verus_keep_ghost_body)]
893 tracked_perms: Tracked(Some(perms)),
894 }
895 }
896}
897
898impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Iterator for Segment<M> {
899 type Item = Frame<M>;
900
901 #[verifier::rlimit(200)]
902 fn next(&mut self) -> Option<Self::Item> {
903 proof {
904 assume(self.inv());
907 }
908
909 if self.range.start < self.range.end {
910 proof {
911 assert(self.raw_perms()[0].slot_perm == self.slot_perms()[0]);
912 assert(self.raw_perms()[0].metadata_perm == self.metadata_perms()[0]);
913 }
914 let tracked mut raw_perms = self.tracked_perms.tracked_borrow_mut();
915 let tracked perm = raw_perms.tracked_pop_front();
916 proof {
917 assert(perm.inv());
918 assert(perm.slot_vaddr() == frame_to_meta(self.range.start));
919 }
920 let frame = unsafe {
923 #[verus_spec(with Tracked(perm))]
924 Frame::<M>::from_raw(self.range.start)
925 };
926 self.range.start += PAGE_SIZE;
927 Some(frame)
928 } else {
929 None
930 }
931 }
932}
933
934impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> IteratorSpecImpl for Segment<M> {
935 open spec fn obeys_prophetic_iter_laws(&self) -> bool {
936 true
937 }
938
939 #[verifier::prophetic]
940 closed spec fn remaining(&self) -> Seq<Self::Item> {
941 Seq::new(
942 self.metadata_perms().len() as nat,
943 |i: int|
944 {
945 Frame::<M>::from_raw_spec(
946 (self.range().start + i * PAGE_SIZE) as usize,
947 self.slot_perms()[i],
948 Some(self.metadata_perms()[i]),
949 )
950 },
951 )
952 }
953
954 #[verifier::prophetic]
955 closed spec fn produces(&self) -> Seq<bool> {
956 Seq::new(IteratorSpec::remaining(self).len(), |i: int| true)
957 }
958
959 closed spec fn decrease(&self) -> Option<nat> {
960 Some(self.len() as nat)
961 }
962
963 open spec fn peek(&self, index: int) -> Option<Self::Item> {
964 if 0 <= index < self.metadata_perms().len() {
965 Some(
966 Frame::<M>::from_raw_spec(
967 (self.range().start + index * PAGE_SIZE) as usize,
968 self.slot_perms()[index],
969 Some(self.metadata_perms()[index]),
970 ),
971 )
972 } else {
973 None
974 }
975 }
976}
977
978impl<M: AnyFrameMeta + Repr<MetaSlotStorage>> Segment<M> {
979 #[verus_spec(
980 with Tracked(regions): Tracked<&mut MetaRegionOwners>
981 requires
982 old(regions).inv(),
983 self.inv(),
984 self.relate_regions(*old(regions)),
985 forall|i: int|
986 #![trigger frame_to_index((self.start_paddr() + i * PAGE_SIZE) as usize)]
987 0 <= i < self.len() ==> {
988 let idx = frame_to_index((self.start_paddr() + i * PAGE_SIZE) as usize);
989 &&& old(regions).slot_owners[idx].storage_perm().is_init()
990 &&& old(regions).ref_count(idx) == 1 ==> {
991 &&& old(regions).slot_owners[idx].in_list_perm.value() == 0
992 }
993 },
994 ensures
995 final(regions).inv(),
996 )]
997 pub fn drop(self) {
998 let ghost n = self.len();
999 let mut paddr = self.range.start;
1000 let tracked mut raw_perms = self.tracked_perms.get().tracked_unwrap();
1001
1002 let ghost mut k: int = 0;
1003
1004 loop
1005 invariant
1006 old(regions).inv(),
1007 regions.inv(),
1008 self.inv(),
1009 raw_perms.len() == n - k,
1010 forall|j: int|
1011 #![trigger raw_perms[j]]
1012 0 <= j < raw_perms.len() ==> {
1013 let idx = frame_to_index((self.range.start + (k + j) * PAGE_SIZE) as usize);
1014 &&& raw_perms[j].inv()
1015 &&& raw_perms[j].slot_perm == regions.slots[idx]
1016 &&& raw_perms[j].metadata_perm.id()
1017 == regions.slot_owners[idx].metadata_perm.id()
1018 },
1019 self.range.start <= paddr <= self.range.end,
1020 paddr == (self.range.start + k * PAGE_SIZE) as usize,
1021 paddr % PAGE_SIZE == 0,
1022 paddr <= MAX_PADDR,
1023 0 <= k <= n,
1024 n == (self.range.end - self.range.start) / PAGE_SIZE as int,
1025 paddr < self.range.end <==> k < n,
1026 forall|j: int|
1027 #![trigger frame_to_index((self.range.start + j * PAGE_SIZE) as usize)]
1028 k <= j < n ==> {
1029 let idx = frame_to_index((self.range.start + j * PAGE_SIZE) as usize);
1030 &&& regions.contains(idx)
1031 &&& regions.slot_owners[idx] == old(regions).slot_owners[idx]
1032 },
1033 forall|j: int|
1034 #![trigger frame_idx_at(self.range.start, j)]
1035 k <= j < n ==> regions.contains(frame_idx_at(self.range.start, j))
1036 && regions.slot_owners[frame_idx_at(self.range.start, j)] == old(
1037 regions,
1038 ).slot_owners[frame_idx_at(self.range.start, j)],
1039 regions.slot_owners.dom() == old(regions).slot_owners.dom(),
1040 self.relate_regions(*old(regions)),
1041 forall|i: int|
1042 #![trigger frame_to_index((self.range.start + i * PAGE_SIZE) as usize)]
1043 0 <= i < n ==> {
1044 let idx = frame_to_index((self.range.start + i * PAGE_SIZE) as usize);
1045 &&& old(regions).slot_owners[idx].storage_perm().is_init()
1046 &&& old(regions).ref_count(idx) == 1 ==> {
1047 &&& old(regions).slot_owners[idx].in_list_perm.value() == 0
1048 }
1049 },
1050 decreases n - k,
1051 {
1052 if paddr >= self.range.end {
1053 break;
1054 }
1055 proof {
1056 assert(valid_frame_paddr(paddr));
1057 lemma_paddr_to_meta_biinjective(paddr);
1058 lemma_frame_to_meta_soundness(paddr);
1059 }
1060 let tracked perm = raw_perms.tracked_pop_front();
1061 let frame = unsafe {
1062 #[verus_spec(with Tracked(perm))]
1063 Frame::<M>::from_raw(paddr)
1064 };
1065
1066 frame.drop(Tracked(regions));
1067
1068 paddr += PAGE_SIZE;
1069
1070 proof {
1071 k = k + 1;
1072 }
1073 }
1074 }
1075}
1076
1077impl<M: AnyFrameMeta + ?Sized> Inv for Segment<M> {
1183 open spec fn inv(self) -> bool {
1188 &&& self.start_paddr() % PAGE_SIZE == 0
1189 &&& self.end_paddr() % PAGE_SIZE == 0
1190 &&& self.start_paddr() <= self.end_paddr() <= MAX_PADDR
1191 &&& self.inner_perm_inv()
1192 &&& self.raw_perms().len() == self.len()
1193 &&& forall|i: int|
1194 #![trigger self.raw_perms()[i]]
1195 0 <= i < self.raw_perms().len() ==> {
1196 let paddr = (self.range().start + i * PAGE_SIZE) as usize;
1197 &&& self.raw_perms()[i].slot_vaddr() == frame_to_meta(paddr)
1198 &&& self.raw_perms()[i].inv()
1199 }
1200 }
1201}
1202
1203}