Skip to content

Commit e25ce52

Browse files
committed
Implement Bytes on IoMemory instead of GuestMemory
Rust only allows us to give one trait the blanket implementations for `Bytes`. We want `IoMemory` to be our primary external interface becaue it has users specify the access permissions they need, and because we can (and do) provide a blanket `IoMemory` implementation for all `GuestMemory` types. Also, while `IoMemory` (as the more general trait) only has a restricted interface when compared to `GuestMemory`, this interface is enough to implement `Bytes`; notably, accesses to `IoMemory` require specifying the access mode, which is naturally trivial for `Bytes` methods like `read()` or `write()`. Signed-off-by: Hanna Czenczek <[email protected]>
1 parent e20441b commit e25ce52

File tree

1 file changed

+12
-7
lines changed

1 file changed

+12
-7
lines changed

src/guest_memory.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -573,17 +573,22 @@ impl<'a, M: GuestMemory + ?Sized> IoMemorySliceIterator<'a, MS<'a, M>>
573573
/// returning `None`, ensuring that it will only return `None` from that point on.
574574
impl<M: GuestMemory + ?Sized> FusedIterator for GuestMemorySliceIterator<'_, M> {}
575575

576-
impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
576+
/// Allow accessing [`IoMemory`] (and [`GuestMemory`]) objects via [`Bytes`].
577+
///
578+
/// Thanks to the [blanket implementation of `IoMemory` for all `GuestMemory`
579+
/// types](../io_memory/trait.IoMemory.html#impl-IoMemory-for-M), this blanket implementation
580+
/// extends to all [`GuestMemory`] types.
581+
impl<T: IoMemory + ?Sized> Bytes<GuestAddress> for T {
577582
type E = Error;
578583

579584
fn write(&self, buf: &[u8], addr: GuestAddress) -> Result<usize> {
580-
self.get_slices(addr, buf.len())
585+
self.get_slices(addr, buf.len(), Permissions::Write)?
581586
.stop_on_error()?
582587
.try_fold(0, |acc, slice| Ok(acc + slice.write(&buf[acc..], 0)?))
583588
}
584589

585590
fn read(&self, buf: &mut [u8], addr: GuestAddress) -> Result<usize> {
586-
self.get_slices(addr, buf.len())
591+
self.get_slices(addr, buf.len(), Permissions::Read)?
587592
.stop_on_error()?
588593
.try_fold(0, |acc, slice| Ok(acc + slice.read(&mut buf[acc..], 0)?))
589594
}
@@ -649,7 +654,7 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
649654
where
650655
F: ReadVolatile,
651656
{
652-
self.get_slices(addr, count)
657+
self.get_slices(addr, count, Permissions::Write)?
653658
.stop_on_error()?
654659
.try_fold(0, |acc, slice| {
655660
Ok(acc + slice.read_volatile_from(0, src, slice.len())?)
@@ -679,7 +684,7 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
679684
where
680685
F: WriteVolatile,
681686
{
682-
self.get_slices(addr, count)
687+
self.get_slices(addr, count, Permissions::Read)?
683688
.stop_on_error()?
684689
.try_fold(0, |acc, slice| {
685690
// For a non-RAM region, reading could have side effects, so we
@@ -706,7 +711,7 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
706711
fn store<O: AtomicAccess>(&self, val: O, addr: GuestAddress, order: Ordering) -> Result<()> {
707712
// No need to check past the first iterator item: It either has the size of `O`, then there
708713
// can be no further items; or it does not, and then `VolatileSlice::store()` will fail.
709-
self.get_slices(addr, size_of::<O>())
714+
self.get_slices(addr, size_of::<O>(), Permissions::Write)?
710715
.next()
711716
.unwrap()? // count > 0 never produces an empty iterator
712717
.store(val, 0, order)
@@ -716,7 +721,7 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
716721
fn load<O: AtomicAccess>(&self, addr: GuestAddress, order: Ordering) -> Result<O> {
717722
// No need to check past the first iterator item: It either has the size of `O`, then there
718723
// can be no further items; or it does not, and then `VolatileSlice::store()` will fail.
719-
self.get_slices(addr, size_of::<O>())
724+
self.get_slices(addr, size_of::<O>(), Permissions::Read)?
720725
.next()
721726
.unwrap()? // count > 0 never produces an empty iterator
722727
.load(0, order)

0 commit comments

Comments
 (0)