1use vstd::pervasive::arbitrary;
15use vstd::prelude::*;
16
17use vstd::layout;
18use vstd::raw_ptr;
19use vstd::set;
20use vstd::set_lib;
21
22use core::marker::PhantomData;
23use core::ops::Range;
24
25use crate::Pod;
26use crate::mm::{Paddr, Vaddr, io::PodOnce};
27use crate::prelude::Inv;
28use crate::specs::arch::mm::MAX_PADDR;
29use crate::specs::mm::page_table::Mapping;
30use ostd_pod::{decode_pod, lemma_decode_pod_inverse, pod_bytes};
31
32verus! {
33
34pub struct VirtPtr {
44 pub vaddr: Vaddr,
46 pub range: Ghost<Range<Vaddr>>,
48}
49
50pub ghost struct FrameContents {
56 pub contents: Seq<raw_ptr::MemContents<u8>>,
58 pub size: usize,
60 pub range: Range<Paddr>,
62}
63
64impl Inv for FrameContents {
65 open spec fn inv(self) -> bool {
73 &&& self.contents.len() == self.size@
74 &&& self.size@ == self.range.end - self.range.start
75 &&& self.range.start % self.size == 0
76 &&& self.range.end % self.size == 0
77 &&& self.range.start <= self.range.end < MAX_PADDR
78 }
79}
80
81pub tracked struct MemView {
94 pub mappings: Set<Mapping>,
96 pub memory: Map<Paddr, FrameContents>,
98}
99
100impl MemView {
101 pub open spec fn addr_transl(self, va: usize) -> Option<(usize, usize)> {
105 let mappings = self.mappings.filter(|m: Mapping| m.va_range.start <= va < m.va_range.end);
106 if 0 < mappings.len() {
107 let m = mappings.choose(); let off = va - m.va_range.start;
109 Some((m.pa_range.start, off as usize))
110 } else {
111 None
112 }
113 }
114
115 pub open spec fn read(self, va: usize) -> raw_ptr::MemContents<u8> {
119 let (pa, off) = self.addr_transl(va)->0;
120 self.memory[pa].contents[off as int]
121 }
122
123 pub open spec fn write(self, va: usize, x: u8) -> Self {
127 let (pa, off) = self.addr_transl(va)->0;
128 MemView {
129 memory: self.memory.insert(
130 pa,
131 FrameContents {
132 contents: self.memory[pa].contents.update(
133 off as int,
134 raw_ptr::MemContents::Init(x),
135 ),
136 ..self.memory[pa]
137 },
138 ),
139 ..self
140 }
141 }
142
143 pub open spec fn write_bytes(self, va: usize, bytes: Seq<u8>) -> Self
147 decreases bytes.len(),
148 {
149 if bytes.len() == 0 {
150 self
151 } else {
152 self.write(va, bytes[0]).write_bytes((va + 1) as usize, bytes.drop_first())
153 }
154 }
155
156 pub open spec fn read_bytes(self, va: usize, len: usize) -> Seq<u8>
162 decreases len,
163 {
164 if len == 0 {
165 Seq::empty()
166 } else {
167 seq![self.read(va).value()].add(self.read_bytes((va + 1) as usize, (len - 1) as usize))
168 }
169 }
170
171 pub proof fn lemma_write_bytes_mappings(self, va: usize, bytes: Seq<u8>)
173 ensures
174 self.write_bytes(va, bytes).mappings == self.mappings,
175 decreases bytes.len(),
176 {
177 if bytes.len() > 0 {
178 self.write(va, bytes[0]).lemma_write_bytes_mappings(
179 (va + 1) as usize,
180 bytes.drop_first(),
181 );
182 }
183 }
184
185 pub proof fn lemma_write_bytes_addr_transl(self, va: usize, bytes: Seq<u8>, query: usize)
187 ensures
188 self.write_bytes(va, bytes).addr_transl(query) == self.addr_transl(query),
189 decreases bytes.len(),
190 {
191 if bytes.len() > 0 {
192 self.write(va, bytes[0]).lemma_write_bytes_addr_transl(
193 (va + 1) as usize,
194 bytes.drop_first(),
195 query,
196 );
197 }
198 }
199
200 pub proof fn lemma_write_bytes_memory_dom_grows(self, va: usize, bytes: Seq<u8>)
202 ensures
203 self.memory.dom().subset_of(self.write_bytes(va, bytes).memory.dom()),
204 decreases bytes.len(),
205 {
206 if bytes.len() > 0 {
207 self.write(va, bytes[0]).lemma_write_bytes_memory_dom_grows(
208 (va + 1) as usize,
209 bytes.drop_first(),
210 );
211 }
212 }
213
214 pub open spec fn eq_at(self, va1: usize, va2: usize) -> bool {
216 let (pa1, off1) = self.addr_transl(va1)->0;
217 let (pa2, off2) = self.addr_transl(va2)->0;
218 self.memory[pa1].contents[off1 as int] == self.memory[pa2].contents[off2 as int]
219 }
220
221 pub open spec fn is_mapped(self, va: usize, pa: usize) -> bool {
223 self.addr_transl(va) is Some && self.addr_transl(va)->Some_0.0 == pa
224 }
225
226 pub open spec fn borrow_at(&self, vaddr: usize, len: usize) -> MemView {
231 let range_end = vaddr + len;
232
233 let valid_pas = Set::new(
234 |pa: usize|
235 exists|va: usize| vaddr <= va < range_end && #[trigger] self.is_mapped(va, pa),
236 );
237
238 MemView {
239 mappings: self.mappings.filter(
240 |m: Mapping| m.va_range.start < range_end && m.va_range.end > vaddr,
241 ),
242 memory: self.memory.restrict(valid_pas),
243 }
244 }
245
246 pub open spec fn mappings_are_disjoint(self) -> bool {
248 forall|m1: Mapping, m2: Mapping|
249 #![trigger self.mappings.contains(m1), self.mappings.contains(m2)]
250 self.mappings.contains(m1) && self.mappings.contains(m2) && m1 != m2 ==> {
251 m1.va_range.end <= m2.va_range.start || m2.va_range.end <= m1.va_range.start
252 }
253 }
254
255 pub open spec fn split(self, vaddr: usize, len: usize) -> (MemView, MemView) {
261 let split_end = vaddr + len;
262
263 let left_mappings = self.mappings.filter(
265 |m: Mapping| m.va_range.start < split_end && m.va_range.end > vaddr,
266 );
267 let right_mappings = self.mappings.filter(|m: Mapping| m.va_range.end > split_end);
268
269 let left_pas = Set::new(
270 |pa: usize| exists|va: usize| vaddr <= va < split_end && self.is_mapped(va, pa),
271 );
272 let right_pas = Set::new(
273 |pa: usize| exists|va: usize| va >= split_end && self.is_mapped(va, pa),
274 );
275
276 (
277 MemView { mappings: left_mappings, memory: self.memory.restrict(left_pas) },
278 MemView { mappings: right_mappings, memory: self.memory.restrict(right_pas) },
279 )
280 }
281
282 #[verifier::external_body]
289 pub proof fn tracked_borrow_at(tracked &self, vaddr: usize, len: usize) -> (tracked r: MemView)
290 ensures
291 r == self.borrow_at(vaddr, len),
292 {
293 unimplemented!()
294 }
295
296 #[verifier::external_body]
303 pub proof fn tracked_split(tracked self, vaddr: usize, len: usize) -> (tracked r: (Self, Self))
304 ensures
305 r == self.split(vaddr, len),
306 {
307 unimplemented!()
308 }
309
310 pub proof fn lemma_split_preserves_transl(
324 original: MemView,
325 vaddr: usize,
326 len: usize,
327 left: MemView,
328 right: MemView,
329 )
330 requires
331 original.split(vaddr, len) == (left, right),
332 ensures
333 right.memory.dom().subset_of(original.memory.dom()),
334 forall|va: usize|
335 vaddr <= va < vaddr + len ==> {
336 #[trigger] original.addr_transl(va) == left.addr_transl(va)
337 },
338 forall|va: usize|
339 va >= vaddr + len ==> {
340 #[trigger] original.addr_transl(va) == right.addr_transl(va)
341 },
342 {
343 assert(right.memory.dom().subset_of(original.memory.dom()));
344
345 assert forall|va: usize| vaddr <= va < vaddr + len implies original.addr_transl(va)
346 == left.addr_transl(va) by {
347 assert(left.mappings =~= original.mappings.filter(
348 |m: Mapping| m.va_range.start < vaddr + len && m.va_range.end > vaddr,
349 ));
350 let o_mappings = original.mappings.filter(
351 |m: Mapping| m.va_range.start <= va < m.va_range.end,
352 );
353 let l_mappings = left.mappings.filter(
354 |m: Mapping| m.va_range.start <= va < m.va_range.end,
355 );
356
357 assert(l_mappings <= o_mappings);
358 assert forall|m: Mapping| #[trigger] o_mappings.contains(m) implies l_mappings.contains(
359 m,
360 ) by {
361 assert(left.mappings.contains(m));
362 };
363 assert(o_mappings <= l_mappings);
364 assert(o_mappings == l_mappings);
365 }
366
367 assert forall|va: usize| va >= vaddr + len implies original.addr_transl(va)
368 == right.addr_transl(va) by {
369 let split_end = vaddr + len;
370
371 let o_mappings = original.mappings.filter(
372 |m: Mapping| m.va_range.start <= va < m.va_range.end,
373 );
374 let r_mappings = right.mappings.filter(
375 |m: Mapping| m.va_range.start <= va < m.va_range.end,
376 );
377
378 assert forall|m: Mapping| o_mappings.contains(m) implies r_mappings.contains(m) by {
379 assert(right.mappings.contains(m));
380 assert(r_mappings.contains(m));
381 }
382
383 assert(o_mappings == r_mappings);
384 }
385 }
386
387 pub open spec fn join(self, other: MemView) -> MemView {
392 MemView {
393 mappings: self.mappings.union(other.mappings),
394 memory: self.memory.union_prefer_right(other.memory),
395 }
396 }
397
398 #[verifier::external_body]
408 pub proof fn tracked_join(tracked &mut self, tracked other: Self)
409 requires
410 old(self).mappings.disjoint(other.mappings),
411 ensures
412 *final(self) == old(self).join(other),
413 {
414 unimplemented!()
415 }
416
417 pub proof fn lemma_split_join_identity(
430 this: MemView,
431 lhs: MemView,
432 rhs: MemView,
433 vaddr: usize,
434 len: usize,
435 )
436 requires
437 this.split(vaddr, len) == (lhs, rhs),
438 forall|m: Mapping| #[trigger]
439 this.mappings.contains(m) ==> vaddr <= m.va_range.start < m.va_range.end,
440 forall|pa: Paddr| #[trigger]
441 this.memory.contains_key(pa) ==> exists|va: usize|
442 vaddr <= va && #[trigger] this.is_mapped(va, pa),
443 ensures
444 this.mappings == lhs.join(rhs).mappings,
445 this.memory == lhs.join(rhs).memory,
446 {
447 }
448
449 pub proof fn lemma_split_preserves_read(
458 original: MemView,
459 vaddr: usize,
460 len: usize,
461 left: MemView,
462 right: MemView,
463 )
464 requires
465 original.split(vaddr, len) == (left, right),
466 ensures
467 forall|va: usize|
468 #![trigger original.read(va)]
469 va >= vaddr + len && original.addr_transl(va) is Some
470 && original.memory.contains_key(original.addr_transl(va).unwrap().0)
471 ==> original.read(va) == right.read(va),
472 {
473 Self::lemma_split_preserves_transl(original, vaddr, len, left, right);
474 let split_end = vaddr + len;
475 let right_pas = Set::new(
476 |pa: usize| exists|va: usize| va >= split_end && original.is_mapped(va, pa),
477 );
478 assert(right.memory =~= original.memory.restrict(right_pas));
479 assert forall|va: usize|
480 va >= split_end && original.addr_transl(va) is Some && original.memory.contains_key(
481 original.addr_transl(va).unwrap().0,
482 ) implies #[trigger] original.read(va) == right.read(va) by {
483 assert(original.addr_transl(va) == right.addr_transl(va));
484 let pa = original.addr_transl(va).unwrap().0;
485 assert(original.is_mapped(va, pa));
486 assert(right_pas.contains(pa));
487 assert(right.memory[pa] == original.memory[pa]);
488 }
489 }
490
491 pub proof fn lemma_read_bytes_eq_pointwise(a: MemView, b: MemView, va: usize, n: usize)
493 requires
494 forall|i: usize| va <= i < va + n ==> a.read(i) == b.read(i),
495 va + n <= usize::MAX,
496 ensures
497 a.read_bytes(va, n) == b.read_bytes(va, n),
498 decreases n,
499 {
500 if n == 0 {
501 return;
502 }
503 assert(a.read(va) == b.read(va));
504 Self::lemma_read_bytes_eq_pointwise(a, b, (va + 1) as usize, (n - 1) as usize);
505 }
506}
507
508impl Inv for VirtPtr {
509 open spec fn inv(self) -> bool {
510 &&& self.range@.start <= self.vaddr <= self.range@.end
511 &&& self.range@.end >= self.range@.start
512 }
513}
514
515impl Clone for VirtPtr {
516 fn clone(&self) -> (res: Self)
517 ensures
518 res == self,
519 {
520 Self { vaddr: self.vaddr, range: Ghost(self.range@) }
521 }
522}
523
524impl Copy for VirtPtr {
525
526}
527
528impl VirtPtr {
529 #[vstd::contrib::auto_spec]
531 pub fn new(vaddr: Vaddr, len: usize) -> Self {
532 Self { vaddr, range: Ghost(Range { start: vaddr, end: (vaddr + len) as usize }) }
533 }
534
535 pub open spec fn is_defined(self) -> bool {
537 self.range@.start <= self.vaddr <= self.range@.end
538 }
539
540 pub open spec fn is_valid(self) -> bool {
544 &&& self.is_defined()
545 &&& self.vaddr < self.range@.end
546 }
547
548 #[verifier::external_body]
561 pub fn read(self, Tracked(mem): Tracked<&MemView>) -> u8
562 requires
563 mem.addr_transl(self.vaddr) is Some,
564 mem.memory[mem.addr_transl(self.vaddr).unwrap().0].contents[mem.addr_transl(
565 self.vaddr,
566 ).unwrap().1 as int] is Init,
567 self.is_valid(),
568 returns
569 mem.read(self.vaddr).value(),
570 {
571 unimplemented!()
572 }
573
574 #[verifier::external_body]
585 pub fn write(self, Tracked(mem): Tracked<&mut MemView>, x: u8)
586 requires
587 old(mem).addr_transl(self.vaddr) is Some,
588 self.is_valid(),
589 ensures
590 *final(mem) == old(mem).write(self.vaddr, x),
591 {
592 unimplemented!()
593 }
594
595 #[verifier::external_body]
609 pub fn read_volatile<T: PodOnce>(self, Tracked(mem): Tracked<&MemView>) -> (val: T)
610 requires
611 self.inv(),
612 core::mem::size_of::<T>() <= self.range@.end - self.vaddr,
613 self.vaddr % core::mem::align_of::<T>() == 0,
614 forall|i: usize|
615 #![trigger mem.addr_transl(i)]
616 self.vaddr <= i < self.vaddr + core::mem::size_of::<T>() ==> {
617 &&& mem.addr_transl(i) is Some
618 &&& mem.memory.contains_key(mem.addr_transl(i).unwrap().0)
619 &&& mem.memory[mem.addr_transl(i).unwrap().0].contents[mem.addr_transl(
620 i,
621 ).unwrap().1 as int] is Init
622 },
623 ensures
624 pod_bytes(val) == mem.read_bytes(self.vaddr, core::mem::size_of::<T>()),
625 {
626 let pnt = self.vaddr as *const T;
627 unsafe { pnt.read_volatile() }
628 }
629
630 #[verifier::external_body]
656 pub fn write_volatile<T: Pod>(self, Tracked(mem): Tracked<&mut MemView>, val: T)
657 requires
658 self.inv(),
659 core::mem::size_of::<T>() <= self.range@.end - self.vaddr,
660 self.vaddr % core::mem::align_of::<T>() == 0,
661 forall|i: usize|
662 #![trigger old(mem).addr_transl(i)]
663 self.vaddr <= i < self.vaddr + core::mem::size_of::<T>() ==> {
664 &&& old(mem).addr_transl(i) is Some
665 },
666 ensures
667 *final(mem) == old(mem).write_bytes(self.vaddr, pod_bytes(val)),
668 final(mem).mappings == old(mem).mappings,
669 old(mem).memory.dom().subset_of(final(mem).memory.dom()),
670 forall|va: usize|
671 #![trigger final(mem).addr_transl(va)]
672 old(mem).addr_transl(va) == final(mem).addr_transl(va),
673 {
674 let pnt = self.vaddr as *mut T;
675 unsafe { pnt.write_volatile(val) }
676 }
677
678 pub open spec fn add_spec(self, n: usize) -> Self {
679 VirtPtr { vaddr: (self.vaddr + n) as usize, range: self.range }
680 }
681
682 pub fn add(&mut self, n: usize)
694 requires
695 0 <= old(self).vaddr + n < usize::MAX,
700 ensures
701 *final(self) == old(self).add_spec(
702 n,
703 ),
704 {
708 self.vaddr = self.vaddr + n
709 }
710
711 pub open spec fn sub_spec(self, n: usize) -> Self {
712 VirtPtr { vaddr: (self.vaddr - n) as usize, range: self.range }
713 }
714
715 pub fn sub(self, n: usize) -> (res: Self)
728 requires
729 n <= self.vaddr,
730 returns
731 self.sub_spec(n),
732 {
733 VirtPtr { vaddr: self.vaddr - n, range: self.range }
734 }
735
736 pub open spec fn wrapping_add_spec(self, n: usize) -> Self {
737 VirtPtr { vaddr: self.vaddr.wrapping_add(n), range: self.range }
738 }
739
740 pub fn wrapping_add(self, n: usize) -> (res: Self)
743 returns
744 self.wrapping_add_spec(n),
745 {
746 VirtPtr { vaddr: self.vaddr.wrapping_add(n), range: self.range }
747 }
748
749 #[verifier::external_body]
756 pub fn cast<T>(self) -> (res: *mut T)
757 ensures
758 res as usize == self.vaddr,
759 {
760 self.vaddr as *mut T
761 }
762
763 pub open spec fn read_offset_spec(self, mem: MemView, n: usize) -> u8 {
764 mem.read((self.vaddr + n) as usize).value()
765 }
766
767 pub fn read_offset(&self, Tracked(mem): Tracked<&MemView>, n: usize) -> u8
783 requires
784 self.vaddr + n < usize::MAX,
785 self.range@.start <= self.vaddr + n < self.range@.end,
786 mem.addr_transl((self.vaddr + n) as usize) is Some,
787 mem.memory[mem.addr_transl(
788 (self.vaddr + n) as usize,
789 ).unwrap().0].contents[mem.addr_transl(
790 (self.vaddr + n) as usize,
791 ).unwrap().1 as int] is Init,
792 returns
793 self.read_offset_spec(*mem, n),
794 {
795 let mut tmp = self.clone();
796 tmp.add(n);
797 tmp.read(Tracked(mem))
798 }
799
800 pub open spec fn write_offset_spec(self, mem: MemView, n: usize, x: u8) -> MemView {
801 mem.write((self.vaddr + n) as usize, x)
802 }
803
804 pub fn write_offset(&self, Tracked(mem): Tracked<&mut MemView>, n: usize, x: u8)
813 requires
814 self.inv(),
815 self.vaddr + n < usize::MAX,
816 self.range@.start <= self.vaddr + n < self.range@.end,
817 old(mem).addr_transl((self.vaddr + n) as usize) is Some,
818 ensures
819 *final(mem) == self.write_offset_spec(*old(mem), n, x),
820 {
821 let mut tmp = self.clone();
822 tmp.add(n);
823 tmp.write(Tracked(mem), x)
824 }
825
826 pub open spec fn copy_offset_spec(
827 src: Self,
828 dst: Self,
829 mem_src: MemView,
830 mem_dst: MemView,
831 n: usize,
832 ) -> MemView {
833 let x = src.read_offset_spec(mem_src, n);
834 dst.write_offset_spec(mem_dst, n, x)
835 }
836
837 pub fn copy_offset(
854 src: &Self,
855 dst: &Self,
856 Tracked(mem_src): Tracked<&MemView>,
857 Tracked(mem_dst): Tracked<&mut MemView>,
858 n: usize,
859 )
860 requires
861 src.inv(),
862 dst.inv(),
863 src.vaddr + n < usize::MAX,
864 dst.vaddr + n < usize::MAX,
865 src.range@.start <= src.vaddr + n < src.range@.end,
866 mem_src.addr_transl((src.vaddr + n) as usize) is Some,
867 mem_src.memory.contains_key(mem_src.addr_transl((src.vaddr + n) as usize).unwrap().0),
868 mem_src.memory[mem_src.addr_transl(
869 (src.vaddr + n) as usize,
870 ).unwrap().0].contents[mem_src.addr_transl(
871 (src.vaddr + n) as usize,
872 ).unwrap().1 as int] is Init,
873 dst.range@.start <= dst.vaddr + n < dst.range@.end,
874 old(mem_dst).addr_transl((dst.vaddr + n) as usize) is Some,
875 ensures
876 *final(mem_dst) == Self::copy_offset_spec(*src, *dst, *mem_src, *old(mem_dst), n),
877 final(mem_dst).mappings == old(mem_dst).mappings,
878 old(mem_dst).memory.dom().subset_of(final(mem_dst).memory.dom()),
879 {
880 let x = src.read_offset(Tracked(mem_src), n);
881 dst.write_offset(Tracked(mem_dst), n, x)
882 }
883
884 pub open spec fn memcpy_spec(
885 src: Self,
886 dst: Self,
887 mem_src: MemView,
888 mem_dst: MemView,
889 n: usize,
890 ) -> MemView
891 decreases n,
892 {
893 if n == 0 {
894 mem_dst
895 } else {
896 let mem_dst_1 = Self::copy_offset_spec(src, dst, mem_src, mem_dst, (n - 1) as usize);
897
898 Self::memcpy_spec(src, dst, mem_src, mem_dst_1, (n - 1) as usize)
899 }
900 }
901
902 pub fn copy_nonoverlapping(
922 src: &Self,
923 dst: &Self,
924 Tracked(mem_src): Tracked<&MemView>,
925 Tracked(mem_dst): Tracked<&mut MemView>,
926 n: usize,
927 )
928 requires
929 src.inv(),
930 dst.inv(),
931 src.range@.start <= src.vaddr,
932 src.vaddr + n <= src.range@.end,
933 forall|i: usize|
934 #![trigger mem_src.addr_transl(i)]
935 src.vaddr <= i < src.vaddr + n ==> {
936 &&& mem_src.addr_transl(i) is Some
937 &&& mem_src.memory.contains_key(mem_src.addr_transl(i).unwrap().0)
938 &&& mem_src.memory[mem_src.addr_transl(
939 i,
940 ).unwrap().0].contents[mem_src.addr_transl(i).unwrap().1 as int] is Init
941 },
942 dst.range@.start <= dst.vaddr,
943 dst.vaddr + n <= dst.range@.end,
944 forall|i: usize|
945 dst.vaddr <= i < dst.vaddr + n ==> {
946 &&& old(mem_dst).addr_transl(i) is Some
947 },
948 ensures
949 *final(mem_dst) == Self::memcpy_spec(*src, *dst, *mem_src, *old(mem_dst), n),
950 final(mem_dst).mappings == old(mem_dst).mappings,
951 old(mem_dst).memory.dom().subset_of(final(mem_dst).memory.dom()),
953 forall|i: usize|
954 #![trigger final(mem_dst).addr_transl(i)]
955 dst.vaddr <= i < dst.vaddr + n ==> {
956 &&& final(mem_dst).addr_transl(i) is Some
957 },
958 decreases n,
959 {
960 if n == 0 {
961 return;
962 } else {
963 let ghost mem0 = *mem_dst;
964
965 Self::copy_offset(src, dst, Tracked(mem_src), Tracked(mem_dst), n - 1);
966
967 proof {
968 assert(forall|i: usize|
969 dst.vaddr <= i < dst.vaddr + n - 1 ==> mem_dst.addr_transl(i)
970 == #[trigger] mem0.addr_transl(i));
971 assert forall|i: usize|
972 dst.vaddr <= i < dst.vaddr + n - 1 implies mem_dst.addr_transl(i) is Some by {
973 assert(mem_dst.addr_transl(i) == mem0.addr_transl(i));
974 }
975 }
976
977 Self::copy_nonoverlapping(src, dst, Tracked(mem_src), Tracked(mem_dst), n - 1);
978 }
979 }
980
981 pub fn from_vaddr(vaddr: usize, len: usize) -> (r: Self)
993 requires
994 len <= usize::MAX - vaddr,
995 ensures
996 r.inv(),
997 r.vaddr == vaddr,
998 r.range@.start == vaddr,
999 r.range@.end == (vaddr + len) as usize,
1000 len > 0 ==> r.is_valid(),
1001 {
1002 Self { vaddr, range: Ghost(Range { start: vaddr, end: (vaddr + len) as usize }) }
1003 }
1004
1005 #[verus_spec(r =>
1020 requires
1021 self.is_valid(),
1022 0 <= n <= self.range@.end - self.range@.start,
1023 self.vaddr == self.range@.start,
1024 ensures
1025 r.0.range@.start == self.range@.start,
1026 r.0.range@.end == self.range@.start + n,
1027 r.0.vaddr == self.range@.start,
1028 r.1.range@.start == self.range@.start + n,
1029 r.1.range@.end == self.range@.end,
1030 r.1.vaddr == self.range@.start + n,
1031 )]
1032 pub fn split(self, n: usize) -> (Self, Self) {
1033 let left = VirtPtr {
1034 vaddr: self.vaddr,
1035 range: Ghost(Range { start: self.vaddr, end: (self.vaddr + n) as usize }),
1036 };
1037
1038 let right = VirtPtr {
1039 vaddr: self.vaddr + n,
1040 range: Ghost(Range { start: (self.vaddr + n) as usize, end: self.range@.end }),
1041 };
1042
1043 (left, right)
1044 }
1045
1046 pub fn addr(&self) -> Vaddr
1047 returns
1048 self.vaddr,
1049 {
1050 self.vaddr
1051 }
1052}
1053
1054pub tracked struct GlobalMemView {
1057 pub pt_mappings: Set<Mapping>,
1058 pub tlb_mappings: Set<Mapping>,
1059 pub unmapped_pas: Set<Paddr>,
1060 pub memory: Map<Paddr, FrameContents>,
1061}
1062
1063impl Inv for GlobalMemView {
1064 open spec fn inv(self) -> bool {
1065 &&& forall|m: Mapping|
1066 #![auto]
1067 self.tlb_mappings.contains(m) ==> {
1068 &&& m.inv()
1069 &&& forall|pa: Paddr|
1070 m.pa_range.start <= pa < m.pa_range.end ==> {
1071 &&& self.memory.dom().contains(pa)
1072 }
1073 &&& self.memory.contains_key(m.pa_range.start)
1074 &&& self.memory[m.pa_range.start].size == m.page_size
1075 &&& self.memory[m.pa_range.start].inv()
1076 }
1077 &&& forall|m: Mapping|
1078 forall|n: Mapping|
1079 #![auto]
1080 self.tlb_mappings.contains(m) ==> self.tlb_mappings.contains(n) ==> m != n
1081 ==> #[trigger] m.va_range.end <= n.va_range.start || n.va_range.end
1082 <= m.va_range.start
1083 &&& self.tlb_mappings.finite()
1084 &&& self.pt_mappings.finite()
1085 &&& self.memory.dom().finite()
1086 &&& self.all_pas_accounted_for()
1087 &&& self.pas_uniquely_mapped()
1088 &&& self.unmapped_correct()
1089 }
1090}
1091
1092impl GlobalMemView {
1093 pub open spec fn addr_transl(self, va: usize) -> Option<(usize, usize)> {
1094 let mappings = self.tlb_mappings.filter(
1095 |m: Mapping| m.va_range.start <= va < m.va_range.end,
1096 );
1097 if 0 < mappings.len() {
1098 let m = mappings.choose(); let off = va - m.va_range.start;
1100 Some((m.pa_range.start, off as usize))
1101 } else {
1102 None
1103 }
1104 }
1105
1106 pub open spec fn is_mapped(self, pa: usize) -> bool {
1107 exists|m: Mapping| self.tlb_mappings.contains(m) && m.pa_range.start <= pa < m.pa_range.end
1108 }
1109
1110 pub open spec fn all_pas_accounted_for(self) -> bool {
1111 forall|pa: Paddr|
1112 0 <= pa < MAX_PADDR ==> #[trigger] self.is_mapped(pa)
1113 || #[trigger] self.unmapped_pas.contains(pa)
1114 }
1115
1116 pub open spec fn pas_uniquely_mapped(self) -> bool {
1117 forall|m1: Mapping, m2: Mapping|
1118 #![trigger self.tlb_mappings.contains(m1), self.tlb_mappings.contains(m2)]
1119 self.tlb_mappings.contains(m1) && self.tlb_mappings.contains(m2) && m1 != m2
1120 ==> m1.pa_range.end <= m2.pa_range.start || m2.pa_range.end <= m1.pa_range.start
1121 }
1122
1123 pub open spec fn unmapped_correct(self) -> bool {
1124 forall|pa: Paddr| #![auto] self.is_mapped(pa) <==> !self.unmapped_pas.contains(pa)
1125 }
1126
1127 pub open spec fn take_view(self, vaddr: usize, len: usize) -> (Self, MemView) {
1128 let range_end = vaddr + len;
1129
1130 let leave_mappings: Set<Mapping> = self.tlb_mappings.filter(
1131 |m: Mapping| m.va_range.end <= vaddr || m.va_range.start > range_end,
1132 );
1133
1134 let take_mappings = self.tlb_mappings.filter(
1135 |m: Mapping| m.va_range.start < range_end && m.va_range.end > vaddr,
1136 );
1137
1138 let leave_pas = Set::new(
1139 |pa: usize|
1140 exists|m: Mapping|
1141 leave_mappings.contains(m) && m.pa_range.start <= pa < m.pa_range.end,
1142 );
1143 let take_pas = Set::new(
1144 |pa: usize|
1145 exists|m: Mapping|
1146 take_mappings.contains(m) && m.pa_range.start <= pa < m.pa_range.end,
1147 );
1148
1149 (
1150 GlobalMemView {
1151 tlb_mappings: leave_mappings,
1152 memory: self.memory.restrict(leave_pas),
1153 ..self
1154 },
1155 MemView { mappings: take_mappings, memory: self.memory.restrict(take_pas) },
1156 )
1157 }
1158
1159 pub axiom fn tracked_take_view(tracked &mut self, vaddr: usize, len: usize) -> (tracked view:
1160 MemView)
1161 ensures
1162 *final(self) == old(self).take_view(vaddr, len).0,
1163 view == old(self).take_view(vaddr, len).1,
1164 ;
1165
1166 pub open spec fn return_view(self, view: MemView) -> Self {
1167 GlobalMemView {
1168 tlb_mappings: self.tlb_mappings.union(view.mappings),
1169 memory: self.memory.union_prefer_right(view.memory),
1170 ..self
1171 }
1172 }
1173
1174 pub axiom fn tracked_return_view(&mut self, view: MemView)
1175 ensures
1176 *final(self) == old(self).return_view(view),
1177 ;
1178
1179 pub open spec fn tlb_flush_vaddr(self, vaddr: Vaddr) -> Self {
1180 let tlb_mappings = self.tlb_mappings.filter(
1181 |m: Mapping| m.va_range.end <= vaddr || vaddr < m.va_range.start,
1182 );
1183 GlobalMemView { tlb_mappings, ..self }
1184 }
1185
1186 pub axiom fn tracked_tlb_flush_vaddr(&mut self, vaddr: Vaddr)
1187 requires
1188 old(self).inv(),
1189 ensures
1190 *final(self) == old(self).tlb_flush_vaddr(vaddr),
1191 final(self).inv(),
1192 ;
1193
1194 pub open spec fn tlb_soft_fault(self, vaddr: Vaddr) -> Self {
1195 let mapping = self.pt_mappings.filter(
1196 |m: Mapping| m.va_range.start <= vaddr < m.va_range.end,
1197 ).choose();
1198 GlobalMemView { tlb_mappings: self.tlb_mappings.insert(mapping), ..self }
1199 }
1200
1201 pub axiom fn tracked_tlb_soft_fault(tracked &mut self, vaddr: Vaddr)
1202 requires
1203 old(self).inv(),
1204 old(self).addr_transl(vaddr) is None,
1205 ensures
1206 *final(self) == old(self).tlb_soft_fault(vaddr),
1207 final(self).inv(),
1208 ;
1209
1210 pub open spec fn pt_map(self, m: Mapping) -> Self {
1211 let pt_mappings = self.pt_mappings.insert(m);
1212 let unmapped_pas = self.unmapped_pas.difference(
1213 Set::new(|pa: usize| m.pa_range.start <= pa < m.pa_range.end),
1214 );
1215 GlobalMemView { pt_mappings, unmapped_pas, ..self }
1216 }
1217
1218 pub axiom fn tracked_pt_map(&mut self, m: Mapping)
1219 requires
1220 forall|pa: Paddr|
1221 m.pa_range.start <= pa < m.pa_range.end ==> old(self).unmapped_pas.contains(pa),
1222 old(self).inv(),
1223 ensures
1224 *final(self) == old(self).pt_map(m),
1225 ;
1226
1227 pub open spec fn pt_unmap(self, m: Mapping) -> Self {
1228 let pt_mappings = self.pt_mappings.remove(m);
1229 let unmapped_pas = self.unmapped_pas.union(
1230 Set::new(|pa: usize| m.pa_range.start <= pa < m.pa_range.end),
1231 );
1232 GlobalMemView { pt_mappings, unmapped_pas, ..self }
1233 }
1234
1235 pub axiom fn tracked_pt_unmap(&mut self, m: Mapping)
1236 requires
1237 old(self).pt_mappings.contains(m),
1238 old(self).inv(),
1239 ensures
1240 *final(self) == old(self).pt_unmap(m),
1241 final(self).inv(),
1242 ;
1243
1244 pub proof fn lemma_va_mapping_unique(self, va: usize)
1245 requires
1246 self.inv(),
1247 self.addr_transl(va) is Some,
1249 ensures
1250 self.tlb_mappings.filter(
1251 |m: Mapping| m.va_range.start <= va < m.va_range.end,
1252 ).is_singleton(),
1253 {
1254 let f = self.tlb_mappings.filter(|m: Mapping| m.va_range.start <= va < m.va_range.end);
1255 assert(f.len() > 0);
1257 assert forall|m: Mapping, n: Mapping| f.contains(m) && f.contains(n) implies m == n by {
1260 assert(self.tlb_mappings.contains(m));
1261 assert(self.tlb_mappings.contains(n));
1262 assert(m.va_range.start <= va < m.va_range.end);
1263 assert(n.va_range.start <= va < n.va_range.end);
1264 };
1266 }
1267}
1268
1269}