pub struct VmIoOwner {
pub id: nat,
pub range: Range<usize>,
pub is_fallible: bool,
pub is_kernel: bool,
pub mem_view: Option<VmIoMemView>,
}Expand description
The owner of a VM I/O operation, which tracks the memory range and the memory view for the operation.
Basically the caller should be only interested in this struct when using VmReader and
VmWriter to perform VM I/O operations, since the safety of these operations depends on the
validity of the memory range and memory view tracked by this struct.
Fields§
§id: natThe unique identifier of this owner.
range: Range<usize>The virtual address range owned by this owner.
is_fallible: boolWhether this reader is fallible.
is_kernel: boolWhether this owner is for kernel space.
mem_view: Option<VmIoMemView>The mem view associated with this owner.
Implementations§
Source§impl VmIoOwner
impl VmIoOwner
Sourcepub open spec fn has_read_view(self) -> bool
pub open spec fn has_read_view(self) -> bool
{ self.mem_view matches Some(VmIoMemView::ReadView(_)) }Whether this owner carries a read memory view.
Sourcepub open spec fn has_write_view(self) -> bool
pub open spec fn has_write_view(self) -> bool
{ self.mem_view matches Some(VmIoMemView::WriteView(_)) }Whether this owner carries a write memory view.
Sourcepub open spec fn can_read(self) -> bool
pub open spec fn can_read(self) -> bool
{ self.has_read_view() }Whether this owner is ready to serve as the readable side of a copy.
Sourcepub open spec fn can_write(self) -> bool
pub open spec fn can_write(self) -> bool
{ self.has_write_view() }Whether this owner is ready to serve as the writable side of a copy.
Sourcepub open spec fn read_view_initialized(self) -> bool
pub open spec fn read_view_initialized(self) -> bool
{
match self.mem_view {
Some(VmIoMemView::ReadView(mem_src)) => {
forall |i: usize| {
self.range.start <= i < self.range.end
==> {
&&& mem_src.addr_transl(i) is Some
&&& mem_src.memory.contains_key((mem_src.addr_transl(i)->0).0)
&&& mem_src
.memory[(mem_src.addr_transl(i)->0).0]
.contents[(mem_src.addr_transl(i)->0).1 as int] is Init
}
}
}
_ => false,
}
}Whether the read view initializes the entire owner range.
Sourcepub open spec fn overlaps(self, other: VmIoOwner) -> bool
pub open spec fn overlaps(self, other: VmIoOwner) -> bool
{ !self.disjoint(other) }Checks whether this owner overlaps with another owner.
Sourcepub open spec fn overlaps_with_range(self, range: Range<usize>) -> bool
pub open spec fn overlaps_with_range(self, range: Range<usize>) -> bool
{
&&& self.range.start <= range.end
&&& range.start <= self.range.end
}Sourcepub open spec fn disjoint(self, other: VmIoOwner) -> bool
pub open spec fn disjoint(self, other: VmIoOwner) -> bool
{
&&& !self.overlaps_with_range(other.range)
&&& match (self.mem_view, other.mem_view) {
(Some(lhs), Some(rhs)) => {
match (lhs, rhs) {
(VmIoMemView::WriteView(lmv), VmIoMemView::WriteView(rmv)) => {
lmv.mappings.disjoint(rmv.mappings)
}
(VmIoMemView::WriteView(lmv), VmIoMemView::ReadView(rmv)) => {
lmv.mappings.disjoint(rmv.mappings)
}
(VmIoMemView::ReadView(lmv), VmIoMemView::WriteView(rmv)) => {
lmv.mappings.disjoint(rmv.mappings)
}
(VmIoMemView::ReadView(lmv), VmIoMemView::ReadView(rmv)) => {
lmv.mappings.disjoint(rmv.mappings)
}
}
}
_ => true,
}
}Checks whether this owner is disjoint with another owner.
Sourcepub open spec fn params_eq(self, other: VmIoOwner) -> bool
pub open spec fn params_eq(self, other: VmIoOwner) -> bool
{
&&& self.range == other.range
&&& self.is_fallible == other.is_fallible
}Sourcepub proof fn change_fallible(tracked &mut self, tracked fallible: bool)
pub proof fn change_fallible(tracked &mut self, tracked fallible: bool)
old(self).inv(),old(self).is_fallible != fallible,ensuresfinal(self).inv(),final(self).is_fallible == fallible,Changes the fallibility of this owner.
§Verified Properties
§Preconditions
- The owner must satisfy its invariant.
- The new fallibility must differ from the current one.
§Postconditions
- The updated owner still satisfies its invariant.
- The
is_falliblefield is updated tofallible.
Sourcepub proof fn advance(tracked &mut self, nbytes: usize) -> tracked res : VmIoMemView
pub proof fn advance(tracked &mut self, nbytes: usize) -> tracked res : VmIoMemView
old(self).inv(),old(self).mem_view is Some,nbytes <= old(self).range.end - old(self).range.start,ensuresfinal(self).inv(),final(self).range.start == old(self).range.start + nbytes,final(self).range.end == old(self).range.end,final(self).is_fallible == old(self).is_fallible,final(self).id == old(self).id,final(self).is_kernel == old(self).is_kernel,old(self)
.mem_view matches Some(
VmIoMemView::ReadView(_),
) ==> final(self).mem_view matches Some(VmIoMemView::ReadView(_)),old(self)
.mem_view matches Some(
VmIoMemView::WriteView(_),
) ==> final(self).mem_view matches Some(VmIoMemView::WriteView(_)),old(self).read_view_initialized() ==> final(self).read_view_initialized(),old(self)
.mem_view matches Some(
VmIoMemView::ReadView(_),
) ==> forall |va: usize| {
old(self).range.start + nbytes <= va < old(self).range.end
&& old(self).read_view_of().addr_transl(va) is Some
&& old(self)
.read_view_of()
.memory
.contains_key((old(self).read_view_of().addr_transl(va)->0).0)
==> {
&&& old(self).read_view_of().addr_transl(va)
== final(self).read_view_of().addr_transl(va)
&&& old(self).read_view_of().read(va) == final(self).read_view_of().read(va)
}
},Advances the cursor of the reader/writer by the given number of bytes.
Note this will return the advanced VmIoMemView as the previous permission
is no longer needed and must be discarded then.
§Verified Properties
§Preconditions
- The owner must satisfy its invariant.
- The owner must carry a memory view.
nbytesmust not exceed the remaining length of the owned range.
§Postconditions
- The updated owner still satisfies its invariant.
- The start of the owned range is advanced by
nbytes. - The end of the owned range and the other owner parameters are preserved.
- The returned
VmIoMemViewis the portion advanced past.
Sourcepub proof fn split(tracked &mut self, nbytes: usize) -> tracked r : VmIoOwner
pub proof fn split(tracked &mut self, nbytes: usize) -> tracked r : VmIoOwner
old(self).inv(),old(self).mem_view is Some,nbytes <= old(self).range.end - old(self).range.start,ensuresr.inv(),r.range.start == old(self).range.start,r.range.end == old(self).range.start + nbytes,r.is_fallible == old(self).is_fallible,r.is_kernel == old(self).is_kernel,r.mem_view is Some,final(self).inv(),final(self).range.start == old(self).range.start + nbytes,final(self).range.end == old(self).range.end,final(self).is_fallible == old(self).is_fallible,final(self).id == old(self).id,final(self).is_kernel == old(self).is_kernel,final(self).mem_view is Some,old(self)
.mem_view matches Some(
VmIoMemView::ReadView(_),
) ==> {
&&& r
.mem_view matches Some(
VmIoMemView::ReadView(_),
) &&& &&& final(self).mem_view matches Some(VmIoMemView::ReadView(_))
},old(self)
.mem_view matches Some(
VmIoMemView::WriteView(_),
) ==> {
&&& r
.mem_view matches Some(
VmIoMemView::WriteView(_),
) &&& &&& final(self).mem_view matches Some(VmIoMemView::WriteView(_))
},old(self).read_view_initialized()
==> {
&&& r.read_view_initialized()
&&& final(self).read_view_initialized()
},Splits this owner at nbytes, returning the front portion as a new owner and shrinking
self to cover the back portion.
§Verified Properties
§Preconditions
- The owner must satisfy its invariant.
- The owner must carry a memory view.
nbytesmust not exceed the remaining length of the owned range.
§Postconditions
- Both the returned front owner and the updated
selfsatisfy their invariants and carry the same kind of memory view as the original. - The front owner covers
[old.start, old.start + nbytes). self’s range becomes[old.start + nbytes, old.end).is_fallible,is_kernelare preserved on both sides.- If the original was an initialized read view, both sides remain initialized.
Sourcepub proof fn tracked_read_view_unwrap(tracked &self) -> tracked r : &MemView
pub proof fn tracked_read_view_unwrap(tracked &self) -> tracked r : &MemView
self.inv(),self.mem_view matches Some(VmIoMemView::ReadView(_)),ensuresVmIoMemView::ReadView(*r) == self.mem_view->0,*r == Self::read_view_of(*self),Unwraps the read view.
§Verified Properties
§Preconditions
- The owner must satisfy its invariant.
- The owner must carry a read memory view.
§Postconditions
- The returned reference is exactly the read view stored in
self.mem_view.
Sourcepub open spec fn read_view_of(self) -> MemView
pub open spec fn read_view_of(self) -> MemView
{
match self.mem_view {
Some(VmIoMemView::ReadView(mv)) => mv,
_ => arbitrary(),
}
}Spec helper: extract the MemView from a read-view owner.
Defined only when self.mem_view matches Some(ReadView(_)); otherwise
returns an arbitrary value. Callers should establish the matching
pattern via [has_read_view] before using this.
Sourcepub proof fn write_to_read(tracked &mut self)
pub proof fn write_to_read(tracked &mut self)
old(self).inv(),old(self).mem_view matches Some(VmIoMemView::WriteView(_)),ensuresfinal(self).inv(),final(self).range == old(self).range,final(self).is_fallible == old(self).is_fallible,final(self).is_kernel == old(self).is_kernel,final(self).id == old(self).id,final(self).mem_view matches Some(VmIoMemView::ReadView(_)),old(self)
.mem_view matches Some(
VmIoMemView::WriteView(mv),
) ==> final(self).mem_view matches Some(VmIoMemView::ReadView(rv)) && rv == mv,Converts the owner’s VmIoMemView::WriteView into a VmIoMemView::ReadView
wrapping the same underlying MemView.
Used after a write-only phase (e.g., VmWriter::fill) to hand the buffer
back as a read-only handle.
§Verified Properties
§Preconditions
- The owner must satisfy its invariant and carry a write memory view.
§Postconditions
- The owner still satisfies its invariant.
- All structural fields (
range,is_fallible,is_kernel,id) are preserved. - The memory view is now
VmIoMemView::ReadViewwrapping the sameMemViewas the originalVmIoMemView::WriteView.
Trait Implementations§
Source§impl Inv for VmIoOwner
impl Inv for VmIoOwner
Source§open spec fn inv(self) -> bool
open spec fn inv(self) -> bool
{
&&& self.inv_wf()
&&& match self.mem_view {
Some(VmIoMemView::WriteView(mv)) => (
&&& mv.mappings_are_disjoint()
&&& forall |va: usize| {
self.range.start <= va < self.range.end
==> {
&&& #[trigger] mv.addr_transl(va) is Some
}
}
),
Some(VmIoMemView::ReadView(mv)) => (
&&& mv.mappings_are_disjoint()
&&& forall |va: usize| {
self.range.start <= va < self.range.end
==> {
&&& #[trigger] mv.addr_transl(va) is Some
}
}
),
None => true,
}
}Full invariant: well-formed AND memory view (if present) covers the range.
Auto Trait Implementations§
impl Freeze for VmIoOwner
impl RefUnwindSafe for VmIoOwner
impl Send for VmIoOwner
impl Sync for VmIoOwner
impl Unpin for VmIoOwner
impl UnsafeUnpin for VmIoOwner
impl UnwindSafe for VmIoOwner
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
§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,
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,
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,
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,
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,
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,
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,
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,
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,
§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,
§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,
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,
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
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
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
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
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
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
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
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
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
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
.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
.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
.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
.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
.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
.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
.tap_deref() only in debug builds, and is erased in release
builds.