pub struct GlobalMemView {
pub pt_mappings: Set<Mapping>,
pub tlb_mappings: Set<Mapping>,
pub unmapped_pas: Set<Paddr>,
pub memory: Map<Paddr, FrameContents>,
}Expand description
A GlobalMemView is a more abstract view of memory that elides most of the details. The API specifications
of higher-level objects like VmSpaceOwner use this view.
Fields§
§pt_mappings: Set<Mapping>§tlb_mappings: Set<Mapping>§unmapped_pas: Set<Paddr>§memory: Map<Paddr, FrameContents>Implementations§
Source§impl GlobalMemView
impl GlobalMemView
Sourcepub open spec fn addr_transl(self, va: usize) -> Option<(usize, usize)>
pub open spec fn addr_transl(self, va: usize) -> Option<(usize, usize)>
{
let mappings = self
.tlb_mappings
.filter(|m: Mapping| m.va_range.start <= va < m.va_range.end);
if 0 < mappings.len() {
let m = mappings.choose();
let off = va - m.va_range.start;
Some((m.pa_range.start, off as usize))
} else {
None
}
}Sourcepub open spec fn is_mapped(self, pa: usize) -> bool
pub open spec fn is_mapped(self, pa: usize) -> bool
{
exists |m: Mapping| {
self.pt_mappings.contains(m) && m.pa_range.start <= pa < m.pa_range.end
}
}Sourcepub open spec fn all_pas_accounted_for(self) -> bool
pub open spec fn all_pas_accounted_for(self) -> bool
{
forall |pa: Paddr| {
0 <= pa < MAX_PADDR
==> #[trigger] self.is_mapped(pa) || #[trigger]
self.unmapped_pas.contains(pa)
}
}Sourcepub open spec fn pas_uniquely_mapped(self) -> bool
pub open spec fn pas_uniquely_mapped(self) -> bool
{
forall |m1: Mapping, m2: Mapping| {
self.tlb_mappings.contains(m1) && self.tlb_mappings.contains(m2) && m1 != m2
==> m1.pa_range.end <= m2.pa_range.start
|| m2.pa_range.end <= m1.pa_range.start
}
}Sourcepub open spec fn unmapped_correct(self) -> bool
pub open spec fn unmapped_correct(self) -> bool
{ forall |pa: Paddr| self.is_mapped(pa) <==> !self.unmapped_pas.contains(pa) }Sourcepub open spec fn take_view(self, vaddr: usize, len: usize) -> (Self, MemView)
pub open spec fn take_view(self, vaddr: usize, len: usize) -> (Self, MemView)
{
let range_end = vaddr + len;
let leave_mappings: Set<Mapping> = self
.tlb_mappings
.filter(|m: Mapping| m.va_range.end <= vaddr || m.va_range.start > range_end);
let take_mappings = self
.tlb_mappings
.filter(|m: Mapping| m.va_range.start < range_end && m.va_range.end > vaddr);
let leave_pas = self
.memory
.dom()
.filter(|pa: usize| {
exists |m: Mapping| {
leave_mappings.contains(m) && m.pa_range.start <= pa < m.pa_range.end
}
});
let take_pas = self
.memory
.dom()
.filter(|pa: usize| {
exists |m: Mapping| {
take_mappings.contains(m) && m.pa_range.start <= pa < m.pa_range.end
}
});
(
GlobalMemView {
tlb_mappings: leave_mappings,
memory: self.memory.restrict(leave_pas),
..self
},
MemView {
mappings: take_mappings,
memory: self.memory.restrict(take_pas),
},
)
}Sourcepub proof fn tracked_take_view(tracked &mut self, vaddr: usize, len: usize) -> tracked view : MemView
pub proof fn tracked_take_view(tracked &mut self, vaddr: usize, len: usize) -> tracked view : MemView
requires
old(self).inv(),ensures*final(self) == old(self).take_view(vaddr, len).0,view == old(self).take_view(vaddr, len).1,Sourcepub open spec fn return_view(self, view: MemView) -> Self
pub open spec fn return_view(self, view: MemView) -> Self
{
GlobalMemView {
tlb_mappings: self.tlb_mappings.union(view.mappings),
memory: self.memory.union_prefer_right(view.memory),
..self
}
}Sourcepub proof fn tracked_return_view(tracked &mut self, tracked view: MemView)
pub proof fn tracked_return_view(tracked &mut self, tracked view: MemView)
ensures
*final(self) == old(self).return_view(view),Sourcepub open spec fn tlb_flush_vaddr(self, vaddr: Vaddr) -> Self
pub open spec fn tlb_flush_vaddr(self, vaddr: Vaddr) -> Self
{
let tlb_mappings = self
.tlb_mappings
.filter(|m: Mapping| m.va_range.end <= vaddr || vaddr < m.va_range.start);
GlobalMemView {
tlb_mappings,
..self
}
}Sourcepub proof fn tracked_tlb_flush_vaddr(tracked &mut self, vaddr: Vaddr)
pub proof fn tracked_tlb_flush_vaddr(tracked &mut self, vaddr: Vaddr)
requires
old(self).inv(),ensures*final(self) == old(self).tlb_flush_vaddr(vaddr),final(self).inv(),Sourcepub open spec fn tlb_soft_fault(self, vaddr: Vaddr) -> Self
pub open spec fn tlb_soft_fault(self, vaddr: Vaddr) -> Self
{
let mapping = self
.pt_mappings
.filter(|m: Mapping| m.va_range.start <= vaddr < m.va_range.end)
.choose();
GlobalMemView {
tlb_mappings: self.tlb_mappings.insert(mapping),
..self
}
}Sourcepub proof fn tracked_tlb_soft_fault(tracked &mut self, vaddr: Vaddr)
pub proof fn tracked_tlb_soft_fault(tracked &mut self, vaddr: Vaddr)
requires
old(self).inv(),old(self).addr_transl(vaddr) is None,exists |m: Mapping| {
old(self).pt_mappings.contains(m) && m.va_range.start <= vaddr < m.va_range.end
},ensures*final(self) == old(self).tlb_soft_fault(vaddr),final(self).inv(),Sourcepub open spec fn pt_map(self, m: Mapping) -> Self
pub open spec fn pt_map(self, m: Mapping) -> Self
{
let pt_mappings = self.pt_mappings.insert(m);
let unmapped_pas = self
.unmapped_pas
.difference(Set::<usize>::range(m.pa_range.start, m.pa_range.end));
GlobalMemView {
pt_mappings,
unmapped_pas,
..self
}
}Sourcepub proof fn tracked_pt_map(tracked &mut self, m: Mapping)
pub proof fn tracked_pt_map(tracked &mut self, m: Mapping)
requires
forall |pa: Paddr| {
m.pa_range.start <= pa < m.pa_range.end ==> old(self).unmapped_pas.contains(pa)
},old(self).inv(),ensures*final(self) == old(self).pt_map(m),Sourcepub open spec fn pt_unmap(self, m: Mapping) -> Self
pub open spec fn pt_unmap(self, m: Mapping) -> Self
{
let pt_mappings = self.pt_mappings.remove(m);
let unmapped_pas = self
.unmapped_pas
.union(Set::<usize>::range(m.pa_range.start, m.pa_range.end));
GlobalMemView {
pt_mappings,
unmapped_pas,
..self
}
}Sourcepub proof fn tracked_pt_unmap(tracked &mut self, m: Mapping)
pub proof fn tracked_pt_unmap(tracked &mut self, m: Mapping)
requires
old(self).pt_mappings.contains(m),!old(self).tlb_mappings.contains(m),old(self).inv(),ensures*final(self) == old(self).pt_unmap(m),final(self).inv(),Sourcepub proof fn lemma_va_mapping_unique(self, va: usize)
pub proof fn lemma_va_mapping_unique(self, va: usize)
requires
self.inv(),self.addr_transl(va) is Some,ensuresself
.tlb_mappings
.filter(|m: Mapping| m.va_range.start <= va < m.va_range.end)
.is_singleton(),Trait Implementations§
Source§impl Inv for GlobalMemView
impl Inv for GlobalMemView
Source§open spec fn inv(self) -> bool
open spec fn inv(self) -> bool
{
&&& forall |m: Mapping| {
self.pt_mappings.contains(m)
==> {
&&& m.inv()
&&& forall |pa: Paddr| {
m.pa_range.start <= pa < m.pa_range.end
==> {
&&& self.memory.dom().contains(pa)
}
}
&&& self.memory.contains_key(m.pa_range.start)
&&& self.memory[m.pa_range.start].size == m.page_size
&&& self.memory[m.pa_range.start].inv()
}
}
&&& forall |m: Mapping| {
self.tlb_mappings.contains(m) ==> self.pt_mappings.contains(m)
}
&&& forall |m: Mapping| {
forall |n: Mapping| {
self.pt_mappings.contains(m)
==> (self.pt_mappings.contains(n)
==> (m != n
==> #[trigger] m.va_range.end <= n.va_range.start
|| n.va_range.end <= m.va_range.start))
}
}
&&& forall |m1: Mapping, m2: Mapping| {
self.pt_mappings.contains(m1) && self.pt_mappings.contains(m2) && m1 != m2
==> m1.pa_range.end <= m2.pa_range.start
|| m2.pa_range.end <= m1.pa_range.start
}
&&& forall |m: Mapping| {
forall |n: Mapping| {
self.tlb_mappings.contains(m)
==> (self.tlb_mappings.contains(n)
==> (m != n
==> #[trigger] m.va_range.end <= n.va_range.start
|| n.va_range.end <= m.va_range.start))
}
}
&&& self.all_pas_accounted_for()
&&& self.pas_uniquely_mapped()
&&& self.unmapped_correct()
}Auto Trait Implementations§
impl Freeze for GlobalMemView
impl RefUnwindSafe for GlobalMemView
impl Send for GlobalMemView
impl Sync for GlobalMemView
impl Unpin for GlobalMemView
impl UnsafeUnpin for GlobalMemView
impl UnwindSafe for GlobalMemView
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
Causes
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
Causes
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
Causes
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
Causes
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
Causes
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
Causes
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
Causes
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
Causes
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
Formats each item in a sequence. Read more
§impl<T, VERUS_SPEC__A> FromSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: From<T>,
impl<T, VERUS_SPEC__A> FromSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: From<T>,
fn obeys_from_spec() -> bool
fn from_spec(v: T) -> VERUS_SPEC__A
§impl<T, VERUS_SPEC__A> IntoSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: Into<T>,
impl<T, VERUS_SPEC__A> IntoSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: Into<T>,
fn obeys_into_spec() -> bool
fn into_spec(self) -> T
§impl<T, U> IntoSpecImpl<U> for Twhere
U: From<T>,
impl<T, U> IntoSpecImpl<U> for Twhere
U: From<T>,
fn obeys_into_spec() -> bool
fn into_spec(self) -> U
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Pipes by value. This is generally the method you want to use. Read more
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
Borrows
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
Mutably borrows
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
Borrows
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
Mutably borrows
self, then passes self.as_mut() into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
Borrows
self, then passes self.deref() into the pipe function.impl<A> SpecEq<&A> for Awhere
A: ?Sized,
impl<A> SpecEq<&mut A> for Awhere
A: ?Sized,
impl<A> SpecEq<A> for Awhere
A: ?Sized,
impl<A> SpecEq<Ghost<A>> for A
impl<A> SpecEq<Tracked<A>> for A
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Immutable access to the
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
Mutable access to the
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
Immutable access to the
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
Mutable access to the
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Immutable access to the
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Mutable access to the
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
Calls
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
Calls
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
Calls
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
Calls
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
Calls
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
Calls
.tap_ref_mut() only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
Calls
.tap_deref() only in debug builds, and is erased in release
builds.