1use core::marker::PhantomData;
2
3use vstd::modes::tracked_swap;
4use vstd::prelude::*;
5
6use vstd::{atomic::*, seq_lib::*, set_lib::*, simple_pptr::*};
7use vstd_extra::{
8 cast_ptr::{Repr, ReprPtr},
9 ownership::*,
10};
11
12use crate::specs::{
13 arch::MAX_NR_PAGES,
14 mm::frame::{
15 mapping::{max_meta_slots, meta_to_index},
16 meta_owners::*,
17 meta_region_owners::MetaRegionOwners,
18 unique::UniqueFrameOwner,
19 },
20};
21
22use crate::mm::{
23 Paddr,
24 frame::{
25 AnyFrameMeta, CursorMut, Link, LinkedList, MetaSlot,
26 meta::{META_SLOT_SIZE, REF_COUNT_UNIQUE},
27 },
28 kspace::FRAME_METADATA_RANGE,
29};
30
31use super::*;
32
33verus! {
34
35pub struct MetaSlotSmall;
36
37pub struct StoredLink {
39 pub next: Option<Paddr>,
40 pub prev: Option<Paddr>,
41 pub slot: MetaSlotSmall,
42}
43
44pub tracked struct LinkInnerPerms<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
45 pub storage: <M as Repr<MetaSlotSmall>>::ReprPerm,
46 pub ghost next_ptr: Option<PPtr<MetaSlotStorage>>,
47 pub ghost prev_ptr: Option<PPtr<MetaSlotStorage>>,
48}
49
50impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Repr<MetaSlotStorage> for Link<M> {
51 type ReprPerm = LinkInnerPerms<M>;
52
53 open spec fn wf(r: MetaSlotStorage, perm: LinkInnerPerms<M>) -> bool {
54 match r {
55 MetaSlotStorage::FrameLink(link) => {
56 &&& M::wf(link.slot, perm.storage)
57 &&& (link.next is Some) == (perm.next_ptr is Some)
58 &&& (link.prev is Some) == (perm.prev_ptr is Some)
59 &&& link.next is Some ==> link.next->0 == perm.next_ptr->0.addr()
60 &&& link.prev is Some ==> link.prev->0 == perm.prev_ptr->0.addr()
61 },
62 _ => false,
63 }
64 }
65
66 open spec fn to_repr_spec(self, perm: LinkInnerPerms<M>) -> (
67 MetaSlotStorage,
68 LinkInnerPerms<M>,
69 ) {
70 let (slot, storage) = self.meta.to_repr_spec(perm.storage);
71 (
72 MetaSlotStorage::FrameLink(
73 StoredLink {
74 next: match self.next {
75 Some(ptr) => Some(ptr.ptr.addr()),
76 None => None,
77 },
78 prev: match self.prev {
79 Some(ptr) => Some(ptr.ptr.addr()),
80 None => None,
81 },
82 slot,
83 },
84 ),
85 LinkInnerPerms {
86 storage,
87 next_ptr: match self.next {
88 Some(ptr) => Some(ptr.ptr),
89 None => None,
90 },
91 prev_ptr: match self.prev {
92 Some(ptr) => Some(ptr.ptr),
93 None => None,
94 },
95 },
96 )
97 }
98
99 #[verifier::external_body]
100 fn to_repr(self, Tracked(perm): Tracked<&mut LinkInnerPerms<M>>) -> MetaSlotStorage {
101 unimplemented!()
102 }
103
104 open spec fn from_repr_spec(r: MetaSlotStorage, perm: LinkInnerPerms<M>) -> Self {
105 match r {
106 MetaSlotStorage::FrameLink(link) => Link {
107 next: match link.next {
108 Some(addr) => Some(ReprPtr { ptr: perm.next_ptr->0, _T: PhantomData }),
109 None => None,
110 },
111 prev: match link.prev {
112 Some(addr) => Some(ReprPtr { ptr: perm.prev_ptr->0, _T: PhantomData }),
113 None => None,
114 },
115 meta: M::from_repr_spec(link.slot, perm.storage),
116 },
117 _ => Link {
118 next: None,
119 prev: None,
120 meta: M::from_repr_spec(MetaSlotSmall, perm.storage),
121 },
122 }
123 }
124
125 #[verifier::external_body]
126 fn from_repr(r: MetaSlotStorage, Tracked(perm): Tracked<&LinkInnerPerms<M>>) -> Self {
127 unimplemented!()
128 }
129
130 #[verifier::external_body]
131 fn from_borrowed<'a>(
132 r: &'a MetaSlotStorage,
133 Tracked(perm): Tracked<&'a LinkInnerPerms<M>>,
134 ) -> &'a Self {
135 unimplemented!()
136 }
137
138 #[verifier::external_body]
139 fn from_borrowed_mut<'a>(
140 r: &'a mut MetaSlotStorage,
141 Tracked(perm): Tracked<&'a mut LinkInnerPerms<M>>,
142 ) -> &'a mut Self {
143 unimplemented!()
144 }
145
146 proof fn from_to_repr(self, perm: LinkInnerPerms<M>) {
147 <M as Repr<MetaSlotSmall>>::from_to_repr(self.meta, perm.storage);
148 }
149
150 proof fn to_from_repr(r: MetaSlotStorage, perm: LinkInnerPerms<M>) {
151 match r {
152 MetaSlotStorage::FrameLink(link) => {
153 M::to_from_repr(link.slot, perm.storage);
154 },
155 _ => {
156 assert(false);
157 },
158 }
159 }
160
161 proof fn to_repr_wf(self, perm: LinkInnerPerms<M>) {
162 <M as Repr<MetaSlotSmall>>::to_repr_wf(self.meta, perm.storage);
163 }
164}
165
166pub ghost struct LinkModel {
167 pub paddr: Paddr,
168}
169
170impl Inv for LinkModel {
171 open spec fn inv(self) -> bool {
172 true
173 }
174}
175
176pub tracked struct LinkOwner {
177 pub ghost paddr: Paddr,
178 pub ghost in_list: u64,
179}
180
181impl Inv for LinkOwner {
182 open spec fn inv(self) -> bool {
183 true
184 }
185}
186
187impl View for LinkOwner {
188 type V = LinkModel;
189
190 open spec fn view(&self) -> Self::V {
191 LinkModel { paddr: self.paddr }
192 }
193}
194
195impl InvView for LinkOwner {
196 proof fn view_preserves_inv(self) {
197 }
198}
199
200impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> OwnerOf for Link<M> {
201 type Owner = LinkOwner;
202
203 open spec fn wf(self, owner: Self::Owner) -> bool {
204 true
205 }
210}
211
212pub ghost struct LinkedListModel {
213 pub list: Seq<LinkModel>,
214}
215
216impl LinkedListModel {
217 pub open spec fn front(self) -> Option<LinkModel> {
218 if self.list.len() > 0 {
219 Some(self.list[0])
220 } else {
221 None
222 }
223 }
224
225 pub open spec fn back(self) -> Option<LinkModel> {
226 if self.list.len() > 0 {
227 Some(self.list[self.list.len() - 1])
228 } else {
229 None
230 }
231 }
232}
233
234impl Inv for LinkedListModel {
235 open spec fn inv(self) -> bool {
236 true
237 }
238}
239
240pub tracked struct LinkedListOwner<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
241 pub list: Seq<LinkOwner>,
242 pub repr_perms: Seq<LinkInnerPerms<M>>,
243 pub ghost list_id: u64,
244 pub ghost _marker: core::marker::PhantomData<M>,
245}
246
247impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Inv for LinkedListOwner<M> {
248 open spec fn inv(self) -> bool {
249 &&& self.list.len() > 0 ==> self.list_id != 0
253 &&& self.repr_perms.len() == self.list.len()
254 &&& forall|i: int| 0 <= i < self.list.len() ==> self.inv_at(i)
255 }
256}
257
258impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> LinkedListOwner<M> {
259 pub open spec fn meta_addr_at(self, regions: MetaRegionOwners, i: int) -> usize {
260 regions.slots[meta_to_index(self.list[i].paddr)].addr()
261 }
262
263 pub open spec fn meta_pptr_at(self, regions: MetaRegionOwners, i: int) -> PPtr<MetaSlot> {
264 regions.slots[meta_to_index(self.list[i].paddr)].pptr()
265 }
266
267 pub open spec fn inv_at(self, i: int) -> bool {
272 &&& self.list[i].inv()
273 &&& self.list[i].in_list == self.list_id
274 }
275
276 pub open spec fn meta_wf_at(self, regions: MetaRegionOwners, i: int) -> bool {
277 let idx = meta_to_index(self.list[i].paddr);
278 typed_meta_wf::<Link<M>>(
279 *regions.slots[idx],
280 regions.slot_owners[idx].metadata_perm,
281 self.repr_perms[i],
282 )
283 }
284
285 pub open spec fn meta_value_at(self, regions: MetaRegionOwners, i: int) -> Link<M> {
286 let idx = meta_to_index(self.list[i].paddr);
287 typed_meta_value::<Link<M>>(regions.slot_owners[idx].metadata_perm, self.repr_perms[i])
288 }
289
290 #[verifier::opaque]
293 pub open spec fn relate_region_at(self, regions: MetaRegionOwners, i: int) -> bool {
294 let idx = meta_to_index(self.list[i].paddr);
295 let value = self.meta_value_at(regions, i);
296 &&& regions.contains(idx)
297 &&& regions.slots[idx].addr() == self.list[i].paddr
298 &&& regions.slot_owners[idx].ref_count() == REF_COUNT_UNIQUE
299 &&& regions.slot_owners[idx].usage is Frame
300 &&& regions.slot_owners[idx].in_list_perm.value() == self.list_id
301 &&& self.meta_wf_at(regions, i)
302 &&& regions.slots[idx].addr() % META_SLOT_SIZE == 0
303 &&& FRAME_METADATA_RANGE.start <= regions.slots[idx].addr() < FRAME_METADATA_RANGE.start
304 + MAX_NR_PAGES * META_SLOT_SIZE
305 &&& value.wf(self.list[i])
306 &&& i == 0 <==> value.prev is None
307 &&& i == self.list.len() - 1 <==> value.next is None
308 &&& 0 < i ==> {
309 &&& value.prev is Some
310 &&& value.prev->0.addr() == self.meta_addr_at(regions, i - 1)
311 }
312 &&& i < self.list.len() - 1 ==> {
313 &&& value.next is Some
314 &&& value.next->0.addr() == self.meta_addr_at(regions, i + 1)
315 }
316 &&& self.list[i].inv()
317 &&& self.list[i].in_list == self.list_id
318 }
319
320 pub open spec fn relate_region(self, regions: MetaRegionOwners) -> bool {
325 &&& self.repr_perms.len() == self.list.len()
326 &&& forall|i: int|
327 #![trigger self.list[i]]
328 0 <= i < self.list.len() ==> self.relate_region_at(regions, i)
329 &&& forall|i: int, j: int|
330 #![trigger meta_to_index(self.list[i].paddr), meta_to_index(self.list[j].paddr)]
331 0 <= i < self.list.len() && 0 <= j < self.list.len() && i != j ==> meta_to_index(
332 self.list[i].paddr,
333 ) != meta_to_index(self.list[j].paddr)
334 &&& self.list.len() > 0 ==> self.list_id != 0
335 }
336
337 pub proof fn length_le_max_meta_slots(self, regions: MetaRegionOwners)
344 requires
345 self.relate_region(regions),
346 regions.inv(),
347 ensures
348 self.list.len() <= max_meta_slots(),
349 {
350 let idxs = Seq::new(self.list.len(), |i: int| meta_to_index(self.list[i].paddr));
351
352 idxs.unique_seq_to_set();
353
354 let bound = set_int_range(0, max_meta_slots());
355 assert(idxs.to_set().subset_of(bound)) by {
356 assert forall|x: int|
357 #![trigger idxs.to_set().contains(x)]
358 idxs.to_set().contains(x) implies bound.contains(x) by {
359 let i = choose|i: int| 0 <= i < idxs.len() && idxs[i] == x;
360 self.relate_region_at_facts(regions, i);
361 }
363 }
364 lemma_int_range(0, max_meta_slots());
365 lemma_len_subset(idxs.to_set(), bound);
366 }
367
368 pub proof fn length_lt_usize_max(self, regions: MetaRegionOwners)
373 requires
374 self.relate_region(regions),
375 regions.inv(),
376 ensures
377 self.list.len() < usize::MAX,
378 {
379 self.length_le_max_meta_slots(regions);
380 }
381
382 pub proof fn relate_region_at_facts(self, regions: MetaRegionOwners, i: int)
387 requires
388 self.relate_region_at(regions, i),
389 ensures
390 ({
391 let idx = meta_to_index(self.list[i].paddr);
392 let value = self.meta_value_at(regions, i);
393 &&& regions.contains(idx)
394 &&& regions.slots[idx].addr() == self.list[i].paddr
395 &&& regions.slot_owners[idx].ref_count() == REF_COUNT_UNIQUE
396 &&& regions.slot_owners[idx].usage is Frame
397 &&& regions.slot_owners[idx].in_list_perm.value() == self.list_id
398 &&& self.meta_wf_at(regions, i)
399 &&& regions.slots[idx].addr() % META_SLOT_SIZE == 0
400 &&& FRAME_METADATA_RANGE.start <= regions.slots[idx].addr()
401 < FRAME_METADATA_RANGE.start + MAX_NR_PAGES * META_SLOT_SIZE
402 &&& value.wf(self.list[i])
403 &&& (i == 0 <==> value.prev is None)
404 &&& (i == self.list.len() - 1 <==> value.next is None)
405 &&& (0 < i ==> {
406 &&& value.prev is Some
407 &&& value.prev->0.addr() == self.meta_addr_at(regions, i - 1)
408 })
409 &&& (i < self.list.len() - 1 ==> {
410 &&& value.next is Some
411 &&& value.next->0.addr() == self.meta_addr_at(regions, i + 1)
412 })
413 &&& self.list[i].inv()
414 &&& self.list[i].in_list == self.list_id
415 }),
416 {
417 reveal(LinkedListOwner::relate_region_at);
418 }
419
420 pub proof fn relate_region_at_from_clauses(self, regions: MetaRegionOwners, i: int)
425 requires
426 ({
427 let idx = meta_to_index(self.list[i].paddr);
428 let value = self.meta_value_at(regions, i);
429 &&& regions.contains(idx)
430 &&& self.repr_perms.len() == self.list.len()
431 &&& regions.slots[idx].addr() == self.list[i].paddr
432 &&& regions.slot_owners[idx].ref_count() == REF_COUNT_UNIQUE
433 &&& regions.slot_owners[idx].usage is Frame
434 &&& regions.slot_owners[idx].in_list_perm.value() == self.list_id
435 &&& self.meta_wf_at(regions, i)
436 &&& regions.slots[idx].addr() % META_SLOT_SIZE == 0
437 &&& FRAME_METADATA_RANGE.start <= regions.slots[idx].addr()
438 < FRAME_METADATA_RANGE.start + MAX_NR_PAGES * META_SLOT_SIZE
439 &&& value.wf(self.list[i])
440 &&& (i == 0 <==> value.prev is None)
441 &&& (i == self.list.len() - 1 <==> value.next is None)
442 &&& (0 < i ==> {
443 &&& value.prev is Some
444 &&& value.prev->0.addr() == self.meta_addr_at(regions, i - 1)
445 })
446 &&& (i < self.list.len() - 1 ==> {
447 &&& value.next is Some
448 &&& value.next->0.addr() == self.meta_addr_at(regions, i + 1)
449 })
450 &&& self.list[i].inv()
451 &&& self.list[i].in_list == self.list_id
452 }),
453 ensures
454 self.relate_region_at(regions, i),
455 {
456 reveal(LinkedListOwner::relate_region_at);
457 }
458
459 pub proof fn relate_region_preserved_external_change(
467 self,
468 regions1: MetaRegionOwners,
469 regions2: MetaRegionOwners,
470 )
471 requires
472 self.relate_region(regions1),
473 regions2.slots == regions1.slots,
474 forall|i: int|
475 #![trigger self.list[i]]
476 0 <= i < self.list.len() ==> {
477 let idx = meta_to_index(self.list[i].paddr);
478 &&& regions2.contains(idx)
479 &&& regions2.slot_owners[idx] == regions1.slot_owners[idx]
480 },
481 ensures
482 self.relate_region(regions2),
483 {
484 let llen = self.list.len() as int;
485 assert forall|k: int|
486 #![trigger self.relate_region_at(regions2, k)]
487 0 <= k < llen implies self.relate_region_at(regions2, k) by {
488 let _ = self.list[k];
489 self.relate_region_at_facts(regions1, k);
490 self.relate_region_at_from_clauses(regions2, k);
491 }
492 }
493
494 #[verifier::spinoff_prover]
505 #[verifier::rlimit(60)]
506 pub proof fn pop_preserves_relate_region(
507 old: LinkedListOwner<M>,
508 r0: MetaRegionOwners,
509 new: LinkedListOwner<M>,
510 fr: MetaRegionOwners,
511 n: int,
512 )
513 requires
514 0 <= n < old.list.len(),
515 old.relate_region(r0),
516 new.list == old.list.remove(n),
517 new.repr_perms.len() == new.list.len(),
518 new.list_id == old.list_id,
519 forall|p: int|
520 #![trigger meta_to_index(old.list[p].paddr)]
521 (0 <= p < old.list.len() && p != n) ==> ({
522 let i = meta_to_index(old.list[p].paddr);
523 let np = if p < n {
524 p
525 } else {
526 p - 1
527 };
528 let fp = typed_meta_value::<Link<M>>(
529 fr.slot_owners[i].metadata_perm,
530 new.repr_perms[np],
531 );
532 &&& fr.contains(i)
533 &&& fr.slots[i].addr() == old.list[p].paddr
534 &&& fr.slots[i].pptr() == r0.slots[i].pptr()
535 &&& fr.slot_owners[i].ref_count() == REF_COUNT_UNIQUE
536 &&& fr.slot_owners[i].usage is Frame
537 &&& fr.slot_owners[i].in_list_perm.value() == new.list_id
538 &&& typed_meta_wf::<Link<M>>(
539 *fr.slots[i],
540 fr.slot_owners[i].metadata_perm,
541 new.repr_perms[np],
542 )
543 &&& fr.slots[i].addr() % META_SLOT_SIZE == 0
544 &&& FRAME_METADATA_RANGE.start <= fr.slots[i].addr()
545 < FRAME_METADATA_RANGE.start + MAX_NR_PAGES * META_SLOT_SIZE
546 &&& (p == n - 1 ==> fp.next == old.meta_value_at(r0, n).next)
547 &&& (p != n - 1 ==> fp.next == old.meta_value_at(r0, p).next)
548 &&& (p == n + 1 ==> fp.prev == old.meta_value_at(r0, n).prev)
549 &&& (p != n + 1 ==> fp.prev == old.meta_value_at(r0, p).prev)
550 }),
551 ensures
552 new.relate_region(fr),
553 {
554 let nlen = new.list.len() as int;
555
556 assert forall|k: int| #![trigger meta_to_index(new.list[k].paddr)] 0 <= k < nlen implies {
557 let p = if k < n {
558 k
559 } else {
560 k + 1
561 };
562 &&& new.list[k] == old.list[p]
563 &&& meta_to_index(new.list[k].paddr) == meta_to_index(old.list[p].paddr)
564 } by {}
565
566 assert forall|a: int, b: int|
567 #![trigger meta_to_index(new.list[a].paddr), meta_to_index(new.list[b].paddr)]
568 0 <= a < nlen && 0 <= b < nlen && a != b implies meta_to_index(new.list[a].paddr)
569 != meta_to_index(new.list[b].paddr) by {
570 let pa = if a < n {
571 a
572 } else {
573 a + 1
574 };
575 let pb = if b < n {
576 b
577 } else {
578 b + 1
579 };
580 }
581
582 assert forall|m: int| #![trigger new.meta_addr_at(fr, m)] 0 <= m < nlen implies {
583 let pm = if m < n {
584 m
585 } else {
586 m + 1
587 };
588 &&& new.meta_addr_at(fr, m) == old.meta_addr_at(r0, pm)
589 &&& new.meta_pptr_at(fr, m) == old.meta_pptr_at(r0, pm)
590 } by {
591 let pm = if m < n {
592 m
593 } else {
594 m + 1
595 };
596 let _ = old.list[pm];
597 old.relate_region_at_facts(r0, pm);
598 }
599
600 assert forall|k: int|
601 #![trigger new.relate_region_at(fr, k)]
602 0 <= k < nlen implies new.relate_region_at(fr, k) by {
603 let p = if k < n {
604 k
605 } else {
606 k + 1
607 };
608 let _ = old.list[p];
609 old.relate_region_at_facts(r0, p);
610 let _ = old.list[n];
611 old.relate_region_at_facts(r0, n);
612 if p - 1 >= 0 {
613 let _ = old.list[p - 1];
614 old.relate_region_at_facts(r0, p - 1);
615 }
616 if p + 1 < old.list.len() {
617 let _ = old.list[p + 1];
618 old.relate_region_at_facts(r0, p + 1);
619 }
620 if n - 1 >= 0 {
621 let _ = old.list[n - 1];
622 old.relate_region_at_facts(r0, n - 1);
623 }
624 if n + 1 < old.list.len() {
625 old.relate_region_at_facts(r0, n + 1);
626 }
627 new.relate_region_at_from_clauses(fr, k);
628 }
629
630 }
631
632 pub open spec fn insert_old_slot_post_clauses(
644 self,
645 fr: MetaRegionOwners,
646 old: LinkedListOwner<M>,
647 r0: MetaRegionOwners,
648 n: int,
649 link: LinkOwner,
650 p: int,
651 ) -> bool {
652 let i = meta_to_index(old.list[p].paddr);
653 let ins = meta_to_index(self.list[n].paddr);
654 let np = if p < n {
655 p
656 } else {
657 p + 1
658 };
659 let fp = typed_meta_value::<Link<M>>(fr.slot_owners[i].metadata_perm, self.repr_perms[np]);
660 &&& fr.contains(i)
661 &&& fr.slots[i].addr() == old.list[p].paddr
662 &&& fr.slots[i].pptr() == r0.slots[i].pptr()
663 &&& fr.slot_owners[i].ref_count() == REF_COUNT_UNIQUE
664 &&& fr.slot_owners[i].usage is Frame
665 &&& fr.slot_owners[i].in_list_perm.value() == self.list_id
666 &&& self.meta_wf_at(fr, np)
667 &&& fr.slots[i].addr() % META_SLOT_SIZE == 0
668 &&& FRAME_METADATA_RANGE.start <= fr.slots[i].addr() < FRAME_METADATA_RANGE.start
669 + MAX_NR_PAGES * META_SLOT_SIZE
670 &&& (p == n - 1 ==> {
671 &&& fp.next is Some
672 &&& fp.next->0.addr() == link.paddr
673 &&& fp.next->0.ptr.addr() == fr.slots[ins].pptr().addr()
674 })
675 &&& (p != n - 1 ==> fp.next == old.meta_value_at(r0, p).next)
676 &&& (p == n ==> {
677 &&& fp.prev is Some
678 &&& fp.prev->0.addr() == link.paddr
679 &&& fp.prev->0.ptr.addr() == fr.slots[ins].pptr().addr()
680 })
681 &&& (p != n ==> fp.prev == old.meta_value_at(r0, p).prev)
682 }
683
684 #[verifier::opaque]
685 pub open spec fn insert_old_slot_post_at(
686 self,
687 fr: MetaRegionOwners,
688 old: LinkedListOwner<M>,
689 r0: MetaRegionOwners,
690 n: int,
691 link: LinkOwner,
692 p: int,
693 ) -> bool {
694 self.insert_old_slot_post_clauses(fr, old, r0, n, link, p)
695 }
696
697 pub proof fn insert_old_slot_post_at_facts(
698 self,
699 fr: MetaRegionOwners,
700 old: LinkedListOwner<M>,
701 r0: MetaRegionOwners,
702 n: int,
703 link: LinkOwner,
704 p: int,
705 )
706 requires
707 self.insert_old_slot_post_at(fr, old, r0, n, link, p),
708 ensures
709 self.insert_old_slot_post_clauses(fr, old, r0, n, link, p),
710 {
711 reveal(LinkedListOwner::insert_old_slot_post_at);
712 }
713
714 #[verifier::spinoff_prover]
715 #[verifier::rlimit(120)]
716 pub proof fn insert_preserves_relate_region(
717 old: LinkedListOwner<M>,
718 r0: MetaRegionOwners,
719 new: LinkedListOwner<M>,
720 fr: MetaRegionOwners,
721 n: int,
722 link: LinkOwner,
723 )
724 requires
725 0 <= n <= old.list.len(),
726 old.relate_region(r0),
727 new.list == old.list.insert(n, link),
728 new.repr_perms.len() == new.list.len(),
729 new.list_id != 0,
730 old.list.len() > 0 ==> new.list_id == old.list_id,
731 link.in_list == new.list_id,
732 forall|p: int|
733 #![trigger meta_to_index(old.list[p].paddr)]
734 (0 <= p < old.list.len()) ==> meta_to_index(old.list[p].paddr) != meta_to_index(
735 new.list[n].paddr,
736 ),
737 ({
738 let ins = meta_to_index(new.list[n].paddr);
739 let fpn = new.meta_value_at(fr, n);
740 &&& fr.contains(ins)
741 &&& fr.slots[ins].addr() == link.paddr
742 &&& fr.slot_owners[ins].ref_count() == REF_COUNT_UNIQUE
743 &&& fr.slot_owners[ins].usage is Frame
744 &&& fr.slot_owners[ins].in_list_perm.value() == new.list_id
745 &&& new.meta_wf_at(fr, n)
746 &&& fr.slots[ins].addr() % META_SLOT_SIZE == 0
747 &&& FRAME_METADATA_RANGE.start <= fr.slots[ins].addr() < FRAME_METADATA_RANGE.start
748 + MAX_NR_PAGES * META_SLOT_SIZE
749 &&& (n == 0 <==> fpn.prev is None)
750 &&& (n == old.list.len() <==> fpn.next is None)
751 &&& (n > 0 ==> {
752 &&& fpn.prev is Some
753 &&& fpn.prev->0.addr() == old.list[n - 1].paddr
754 &&& fpn.prev->0.ptr.addr() == old.meta_pptr_at(r0, n - 1).addr()
755 })
756 &&& (n < old.list.len() ==> {
757 &&& fpn.next is Some
758 &&& fpn.next->0.addr() == old.list[n].paddr
759 &&& fpn.next->0.ptr.addr() == old.meta_pptr_at(r0, n).addr()
760 })
761 }),
762 forall|p: int|
763 #![trigger new.insert_old_slot_post_at(fr, old, r0, n, link, p)]
764 (0 <= p < old.list.len()) ==> new.insert_old_slot_post_at(fr, old, r0, n, link, p),
765 ensures
766 new.relate_region(fr),
767 {
768 let nlen = new.list.len() as int;
769 let ins = meta_to_index(new.list[n].paddr);
770
771 assert forall|k: int| #![trigger meta_to_index(new.list[k].paddr)] 0 <= k < nlen implies ({
772 &&& (k < n ==> new.list[k] == old.list[k] && meta_to_index(new.list[k].paddr)
773 == meta_to_index(old.list[k].paddr))
774 &&& (k == n ==> new.list[k] == link && meta_to_index(new.list[k].paddr) == ins)
775 &&& (k > n ==> new.list[k] == old.list[k - 1] && meta_to_index(new.list[k].paddr)
776 == meta_to_index(old.list[k - 1].paddr))
777 }) by {}
778
779 assert forall|a: int, b: int|
780 #![trigger meta_to_index(new.list[a].paddr), meta_to_index(new.list[b].paddr)]
781 0 <= a < nlen && 0 <= b < nlen && a != b implies meta_to_index(new.list[a].paddr)
782 != meta_to_index(new.list[b].paddr) by {}
783
784 assert forall|m: int| #![trigger new.meta_addr_at(fr, m)] 0 <= m < nlen implies ({
785 &&& (m < n ==> new.meta_addr_at(fr, m) == old.meta_addr_at(r0, m) && new.meta_pptr_at(
786 fr,
787 m,
788 ) == old.meta_pptr_at(r0, m))
789 &&& (m > n ==> new.meta_addr_at(fr, m) == old.meta_addr_at(r0, m - 1)
790 && new.meta_pptr_at(fr, m) == old.meta_pptr_at(r0, m - 1))
791 }) by {
792 if m < n {
793 let _ = old.list[m];
794 old.relate_region_at_facts(r0, m);
795 new.insert_old_slot_post_at_facts(fr, old, r0, n, link, m);
796 }
797 if m > n {
798 let _ = old.list[m - 1];
799 old.relate_region_at_facts(r0, m - 1);
800 new.insert_old_slot_post_at_facts(fr, old, r0, n, link, m - 1);
801 }
802 }
803
804 assert forall|k: int|
805 #![trigger new.relate_region_at(fr, k)]
806 0 <= k < nlen implies new.relate_region_at(fr, k) by {
807 if k < n {
808 let _ = old.list[k];
809 old.relate_region_at_facts(r0, k);
810 new.insert_old_slot_post_at_facts(fr, old, r0, n, link, k);
811 }
812 if k > n {
813 let _ = old.list[k - 1];
814 old.relate_region_at_facts(r0, k - 1);
815 new.insert_old_slot_post_at_facts(fr, old, r0, n, link, k - 1);
816 }
817 if n - 1 >= 0 && n - 1 < old.list.len() {
818 let _ = old.list[n - 1];
819 old.relate_region_at_facts(r0, n - 1);
820 }
821 if n >= 0 && n < old.list.len() {
822 let _ = old.list[n];
823 old.relate_region_at_facts(r0, n);
824 }
825 new.relate_region_at_from_clauses(fr, k);
826 }
827
828 }
830
831 pub open spec fn view_helper(owners: Seq<LinkOwner>) -> Seq<LinkModel>
832 decreases owners.len(),
833 {
834 if owners.len() == 0 {
835 Seq::<LinkModel>::empty()
836 } else {
837 seq![owners[0].view()].add(Self::view_helper(owners.remove(0)))
838 }
839 }
840
841 pub proof fn view_preserves_len(owners: Seq<LinkOwner>)
842 ensures
843 Self::view_helper(owners).len() == owners.len(),
844 decreases owners.len(),
845 {
846 if owners.len() > 0 {
847 Self::view_preserves_len(owners.remove(0))
848 }
849 }
850
851 pub proof fn view_helper_index(owners: Seq<LinkOwner>, i: int)
853 requires
854 0 <= i < owners.len(),
855 ensures
856 Self::view_helper(owners)[i] == owners[i].view(),
857 decreases owners.len(),
858 {
859 Self::view_preserves_len(owners);
860 if i > 0 {
861 Self::view_helper_index(owners.remove(0), i - 1);
862 }
863 }
864
865 pub proof fn view_helper_remove(owners: Seq<LinkOwner>, i: int)
868 requires
869 0 <= i < owners.len(),
870 ensures
871 Self::view_helper(owners.remove(i)) == Self::view_helper(owners).remove(i),
872 {
873 Self::view_preserves_len(owners);
874 Self::view_preserves_len(owners.remove(i));
875 assert forall|j: int|
876 0 <= j < Self::view_helper(owners.remove(i)).len() implies Self::view_helper(
877 owners.remove(i),
878 )[j] == Self::view_helper(owners).remove(i)[j] by {
879 Self::view_helper_index(owners.remove(i), j);
880 if j < i {
881 Self::view_helper_index(owners, j);
882 } else {
883 Self::view_helper_index(owners, j + 1);
884 }
885 };
886 }
887
888 pub proof fn view_helper_insert(owners: Seq<LinkOwner>, i: int, v: LinkOwner)
891 requires
892 0 <= i <= owners.len(),
893 ensures
894 Self::view_helper(owners.insert(i, v)) == Self::view_helper(owners).insert(i, v.view()),
895 {
896 Self::view_preserves_len(owners);
897 Self::view_preserves_len(owners.insert(i, v));
898 assert forall|j: int|
899 0 <= j < Self::view_helper(
900 owners.insert(i, v),
901 ).len() implies #[trigger] Self::view_helper(owners.insert(i, v))[j]
902 == Self::view_helper(owners).insert(i, v.view())[j] by {
903 Self::view_helper_index(owners.insert(i, v), j);
904 if j < i {
905 Self::view_helper_index(owners, j);
906 } else if j == i {
907 } else {
909 Self::view_helper_index(owners, j - 1);
910 }
911 };
912 }
913}
914
915impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> View for LinkedListOwner<M> {
916 type V = LinkedListModel;
917
918 open spec fn view(&self) -> Self::V {
919 LinkedListModel { list: Self::view_helper(self.list) }
920 }
921}
922
923impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> InvView for LinkedListOwner<M> {
924 proof fn view_preserves_inv(self) {
925 }
926}
927
928impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> LinkedListOwner<M> {
929 pub proof fn tracked_take(tracked owner: &mut Self) -> (tracked res: Self)
935 ensures
936 res == *old(owner),
937 final(owner).list == Seq::<LinkOwner>::empty(),
938 final(owner).repr_perms == Seq::<LinkInnerPerms<M>>::empty(),
939 final(owner).inv(),
940 {
941 let tracked mut tmp = crate::specs::mm::embedding::list_store::tracked_empty_list_owner::<
942 M,
943 >();
944 tracked_swap(owner, &mut tmp);
945 tmp
946 }
947
948 #[verifier::external_body]
952 pub proof fn tracked_destroy_empty(tracked self)
953 requires
954 self.list =~= Seq::<LinkOwner>::empty(),
955 self.repr_perms =~= Seq::<LinkInnerPerms<M>>::empty(),
956 {
957 unimplemented!()
958 }
959}
960
961impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> OwnerOf for LinkedList<M> {
962 type Owner = LinkedListOwner<M>;
963
964 open spec fn wf(self, owner: Self::Owner) -> bool {
969 &&& self.front is None <==> owner.list.len() == 0
970 &&& self.back is None <==> owner.list.len() == 0
971 &&& owner.list.len() > 0 ==> self.front is Some && self.front->0.addr()
972 == owner.list[0].paddr && self.back is Some && self.back->0.addr()
973 == owner.list[owner.list.len() - 1].paddr
974 &&& self.size == owner.list.len()
975 &&& self.list_id == owner.list_id
976 }
977}
978
979pub ghost struct CursorModel {
980 pub ghost fore: Seq<LinkModel>,
981 pub ghost rear: Seq<LinkModel>,
982 pub ghost list_model: LinkedListModel,
983}
984
985impl Inv for CursorModel {
986 open spec fn inv(self) -> bool {
987 self.list_model.inv()
988 }
989}
990
991pub tracked struct CursorOwner<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
992 pub list_own: LinkedListOwner<M>,
993 pub ghost index: int,
994}
995
996impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Inv for CursorOwner<M> {
997 open spec fn inv(self) -> bool {
998 &&& 0 <= self.index <= self.length()
999 &&& self.list_own.inv()
1000 }
1001}
1002
1003impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> View for CursorOwner<M> {
1004 type V = CursorModel;
1005
1006 open spec fn view(&self) -> Self::V {
1007 let list = self.list_own.view();
1008 CursorModel {
1009 fore: list.list.take(self.index),
1010 rear: list.list.skip(self.index),
1011 list_model: list,
1012 }
1013 }
1014}
1015
1016impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> InvView for CursorOwner<M> {
1017 proof fn view_preserves_inv(self) {
1018 }
1019}
1020
1021impl<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> OwnerOf for CursorMut<'a, M> {
1022 type Owner = CursorOwner<M>;
1023
1024 open spec fn wf(self, owner: Self::Owner) -> bool {
1028 &&& 0 <= owner.index < owner.length() ==> self.current.is_some() && self.current->0.addr()
1029 == owner.list_own.list[owner.index].paddr
1030 &&& owner.index == owner.list_own.list.len() ==> self.current.is_none()
1031 &&& (*self.list).wf(owner.list_own)
1032 }
1033}
1034
1035impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> LinkedList<M> {
1036 pub open spec fn wf_region(self, owner: LinkedListOwner<M>, regions: MetaRegionOwners) -> bool {
1039 &&& self.front is None <==> owner.list.len() == 0
1040 &&& self.back is None <==> owner.list.len() == 0
1041 &&& owner.list.len() > 0 ==> self.front is Some && self.front->0.addr()
1042 == owner.list[0].paddr && owner.meta_pptr_at(regions, 0).addr() == self.front->0.addr()
1043 && self.back is Some && self.back->0.addr() == owner.list[owner.list.len() - 1].paddr
1044 && owner.meta_pptr_at(regions, owner.list.len() - 1).addr() == self.back->0.addr()
1045 &&& self.size == owner.list.len()
1046 &&& self.list_id == owner.list_id
1047 }
1048}
1049
1050impl<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> CursorMut<'a, M> {
1051 pub open spec fn wf_region(self, owner: CursorOwner<M>, regions: MetaRegionOwners) -> bool {
1054 &&& 0 <= owner.index < owner.length() ==> self.current.is_some() && self.current->0.addr()
1055 == owner.list_own.list[owner.index].paddr && owner.list_own.meta_pptr_at(
1056 regions,
1057 owner.index,
1058 ).addr() == self.current->0.addr()
1059 &&& owner.index == owner.list_own.list.len() ==> self.current.is_none()
1060 &&& (*self.list).wf_region(owner.list_own, regions)
1061 }
1062}
1063
1064impl CursorModel {
1065 pub open spec fn current(self) -> Option<LinkModel> {
1066 if self.rear.len() > 0 {
1067 Some(self.rear[0])
1068 } else {
1069 None
1070 }
1071 }
1072}
1073
1074impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> CursorOwner<M> {
1075 pub open spec fn length(self) -> int {
1076 self.list_own.list.len() as int
1077 }
1078
1079 pub open spec fn wf_with_region(self, regions: MetaRegionOwners) -> bool {
1083 &&& 0 <= self.index <= self.length()
1084 &&& self.list_own.relate_region(regions)
1085 }
1086
1087 pub open spec fn current(self) -> Option<LinkOwner> {
1088 if 0 <= self.index < self.length() {
1089 Some(self.list_own.list[self.index])
1090 } else {
1091 None
1092 }
1093 }
1094
1095 pub open spec fn list_insert(
1096 cursor: Self,
1097 link: LinkOwner,
1098 repr_perm: LinkInnerPerms<M>,
1099 list_id: u64,
1100 ) -> (Self, LinkOwner) {
1101 let link = LinkOwner { paddr: link.paddr, in_list: list_id };
1102 (
1103 Self {
1104 list_own: LinkedListOwner::<M> {
1105 list: cursor.list_own.list.insert(cursor.index, link),
1106 repr_perms: cursor.list_own.repr_perms.insert(cursor.index, repr_perm),
1107 list_id,
1108 _marker: PhantomData,
1109 },
1110 index: cursor.index + 1,
1111 },
1112 link,
1113 )
1114 }
1115
1116 pub proof fn tracked_list_insert(
1125 tracked cursor: &mut Self,
1126 tracked link: &mut LinkOwner,
1127 tracked repr_perm: LinkInnerPerms<M>,
1128 list_id: u64,
1129 )
1130 requires
1131 list_id != 0,
1132 0 <= old(cursor).index <= old(cursor).list_own.list.len(),
1133 old(cursor).list_own.repr_perms.len() == old(cursor).list_own.list.len(),
1134 old(cursor).list_own.list.len() > 0 ==> list_id == old(cursor).list_own.list_id,
1135 old(cursor).list_own.list_id != 0 ==> list_id == old(cursor).list_own.list_id,
1136 ensures
1137 ({
1138 let res = Self::list_insert(*old(cursor), *old(link), repr_perm, list_id);
1139
1140 res.0 == *final(cursor) && res.1 == *final(link)
1141 }),
1142 {
1143 let ghost idx = cursor.index;
1144 let ghost link_paddr = link.paddr;
1145 let tracked list_entry = LinkOwner { paddr: link_paddr, in_list: list_id };
1146
1147 cursor.list_own.list.tracked_insert(idx, list_entry);
1148 cursor.list_own.repr_perms.tracked_insert(idx, repr_perm);
1149 cursor.list_own.list_id = list_id;
1150 cursor.index = idx + 1;
1151 *link = LinkOwner { paddr: link_paddr, in_list: list_id };
1152 }
1153
1154 pub open spec fn front_owner(list_own: LinkedListOwner<M>) -> Self {
1155 CursorOwner::<M> { list_own: list_own, index: 0 }
1156 }
1157
1158 pub open spec fn cursor_mut_at_owner(list_own: LinkedListOwner<M>, index: int) -> Self {
1159 CursorOwner::<M> { list_own: list_own, index: index }
1160 }
1161
1162 pub proof fn tracked_cursor_mut_at_owner(
1163 tracked list_own: LinkedListOwner<M>,
1164 index: int,
1165 ) -> tracked Self
1166 returns
1167 Self::cursor_mut_at_owner(list_own, index),
1168 {
1169 let tracked res = CursorOwner::<M> { list_own, index };
1170 res
1171 }
1172
1173 pub proof fn tracked_front_owner(tracked list_own: LinkedListOwner<M>) -> tracked Self
1174 returns
1175 Self::front_owner(list_own),
1176 {
1177 let tracked res = CursorOwner::<M> { list_own, index: 0 };
1178 res
1179 }
1180
1181 pub open spec fn back_owner(list_own: LinkedListOwner<M>) -> Self {
1182 CursorOwner::<M> {
1183 list_own: list_own,
1184 index: if list_own.list.len() > 0 {
1185 list_own.list.len() - 1
1186 } else {
1187 0
1188 },
1189 }
1190 }
1191
1192 pub proof fn tracked_back_owner(tracked list_own: LinkedListOwner<M>) -> (tracked res: Self)
1193 ensures
1194 res == Self::back_owner(list_own),
1195 {
1196 CursorOwner::<M> {
1197 list_own: list_own,
1198 index: if list_own.list.len() > 0 {
1199 list_own.list.len() - 1
1200 } else {
1201 0
1202 },
1203 }
1204 }
1205
1206 pub open spec fn ghost_owner(list_own: LinkedListOwner<M>) -> Self {
1207 CursorOwner::<M> { list_own: list_own, index: list_own.list.len() as int }
1208 }
1209
1210 pub proof fn tracked_ghost_owner(tracked list_own: LinkedListOwner<M>) -> (tracked res: Self)
1211 ensures
1212 res == Self::ghost_owner(list_own),
1213 {
1214 CursorOwner::<M> { list_own: list_own, index: list_own.list.len() as int }
1215 }
1216}
1217
1218impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> UniqueFrameOwner<Link<M>> {
1219 pub open spec fn frame_link_inv(&self, regions: MetaRegionOwners) -> bool {
1220 &&& self.meta_value(regions).prev is None
1221 &&& self.meta_value(regions).next is None
1222 &&& self.meta_own.paddr == regions.slots[self.slot_index].addr()
1223 &&& regions.slot_owners[self.slot_index].in_list_perm.value() == 0
1224 }
1225}
1226
1227}