GlobalMemView

Struct GlobalMemView 

Source
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 MemView can be created by taking a view from a GlobalMemView; it is structed similarly but with the extra global fields like TLB and page tables. It also tracks the physical addresses in the valid range that are unmapped.

Fields§

§pt_mappings: Set<Mapping>§tlb_mappings: Set<Mapping>§unmapped_pas: Set<Paddr>§memory: Map<Paddr, FrameContents>

Implementations§

Source§

impl GlobalMemView

Source

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
    }
}
Source

pub open spec fn is_mapped(self, pa: usize) -> bool

{
    exists |m: Mapping| {
        self.tlb_mappings.contains(m) && m.pa_range.start <= pa < m.pa_range.end
    }
}
Source

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)
    }
}
Source

pub open spec fn pas_uniquely_mapped(self) -> bool

{
    forall |m1: Mapping, m2: Mapping| {
        #[trigger] self.tlb_mappings.contains(m1) && #[trigger]
            self.tlb_mappings.contains(m2) && m1 != m2
            ==> m1.pa_range.end <= m2.pa_range.start
                || m2.pa_range.end <= m1.pa_range.start
    }
}
Source

pub open spec fn unmapped_correct(self) -> bool

{ forall |pa: Paddr| self.is_mapped(pa) <==> !self.unmapped_pas.contains(pa) }
Source

pub open spec fn take_view_spec(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 = Set::new(|pa: usize| {
        exists |m: Mapping| {
            leave_mappings.contains(m) && m.pa_range.start <= pa < m.pa_range.end
        }
    });
    let take_pas = Set::new(|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),
        },
    )
}
Source

pub proof fn take_view(tracked &mut self, vaddr: usize, len: usize) -> tracked view : MemView

ensures
*self == old(self).take_view_spec(vaddr, len).0,
view == old(self).take_view_spec(vaddr, len).1,
Source

pub open spec fn return_view_spec(self, view: MemView) -> Self

{
    GlobalMemView {
        tlb_mappings: self.tlb_mappings.union(view.mappings),
        memory: self.memory.union_prefer_right(view.memory),
        ..self
    }
}
Source

pub proof fn return_view(&mut self, view: MemView)

ensures
*self == old(self).return_view_spec(view),
Source

pub open spec fn tlb_flush_vaddr_spec(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
    }
}
Source

pub proof fn tlb_flush_vaddr(&mut self, vaddr: Vaddr)

requires
old(self).inv(),
ensures
*self == old(self).tlb_flush_vaddr_spec(vaddr),
self.inv(),
Source

pub open spec fn tlb_soft_fault_spec(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
    }
}
Source

pub proof fn tlb_soft_fault(tracked &mut self, vaddr: Vaddr)

requires
old(self).inv(),
old(self).addr_transl(vaddr) is None,
ensures
*self == old(self).tlb_soft_fault_spec(vaddr),
self.inv(),
Source

pub open spec fn pt_map_spec(self, m: Mapping) -> Self

{
    let pt_mappings = self.pt_mappings.insert(m);
    let unmapped_pas = self
        .unmapped_pas
        .difference(Set::new(|pa: usize| m.pa_range.start <= pa < m.pa_range.end));
    GlobalMemView {
        pt_mappings,
        unmapped_pas,
        ..self
    }
}
Source

pub proof fn pt_map(&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
*self == old(self).pt_map_spec(m),
Source

pub open spec fn pt_unmap_spec(self, m: Mapping) -> Self

{
    let pt_mappings = self.pt_mappings.remove(m);
    let unmapped_pas = self
        .unmapped_pas
        .union(Set::new(|pa: usize| m.pa_range.start <= pa < m.pa_range.end));
    GlobalMemView {
        pt_mappings,
        unmapped_pas,
        ..self
    }
}
Source

pub proof fn pt_unmap(&mut self, m: Mapping)

requires
old(self).pt_mappings.contains(m),
old(self).inv(),
ensures
*self == old(self).pt_unmap_spec(m),
self.inv(),
Source

pub proof fn lemma_va_mapping_unique(self, va: usize)

requires
self.inv(),
ensures
self
    .tlb_mappings
    .filter(|m: Mapping| m.va_range.start <= va < m.va_range.end)
    .is_singleton(),

Trait Implementations§

Source§

impl Inv for GlobalMemView

Source§

open spec fn inv(self) -> bool

{
    &&& self.tlb_mappings.finite()
    &&& self.pt_mappings.finite()
    &&& self.memory.dom().finite()
    &&& self.all_pas_accounted_for()
    &&& self.pas_uniquely_mapped()
    &&& self.unmapped_correct()
    &&& forall |m: Mapping| {
        self.tlb_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| {
        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))
        }
    }

}

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, VERUS_SPEC__A> FromSpec<T> for VERUS_SPEC__A
where VERUS_SPEC__A: From<T>,

§

fn obeys_from_spec() -> bool

§

fn from_spec(v: T) -> VERUS_SPEC__A

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T, VERUS_SPEC__A> IntoSpec<T> for VERUS_SPEC__A
where VERUS_SPEC__A: Into<T>,

§

fn obeys_into_spec() -> bool

§

fn into_spec(self) -> T

§

impl<T, U> IntoSpecImpl<U> for T
where U: From<T>,

§

fn obeys_into_spec() -> bool

§

fn into_spec(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, VERUS_SPEC__A> TryFromSpec<T> for VERUS_SPEC__A
where VERUS_SPEC__A: TryFrom<T>,

§

fn obeys_try_from_spec() -> bool

§

fn try_from_spec( v: T, ) -> Result<VERUS_SPEC__A, <VERUS_SPEC__A as TryFrom<T>>::Error>

Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T, VERUS_SPEC__A> TryIntoSpec<T> for VERUS_SPEC__A
where VERUS_SPEC__A: TryInto<T>,

§

fn obeys_try_into_spec() -> bool

§

fn try_into_spec(self) -> Result<T, <VERUS_SPEC__A as TryInto<T>>::Error>

§

impl<T, U> TryIntoSpecImpl<U> for T
where U: TryFrom<T>,

§

fn obeys_try_into_spec() -> bool

§

fn try_into_spec(self) -> Result<U, <U as TryFrom<T>>::Error>