Skip to content

Commit ed47e85

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 94423bd commit ed47e85

File tree

1 file changed

+27
-10
lines changed

1 file changed

+27
-10
lines changed

src/guest_memory.rs

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ use crate::bitmap::MS;
5555
use crate::bytes::{AtomicAccess, Bytes};
5656
use crate::io::{ReadVolatile, WriteVolatile};
5757
use crate::volatile_memory::{self, VolatileSlice};
58-
use crate::GuestMemoryRegion;
58+
use crate::{GuestMemoryRegion, IoMemory, Permissions};
5959

6060
/// Errors associated with handling guest memory accesses.
6161
#[allow(missing_docs)]
@@ -545,13 +545,19 @@ impl<'a, M: GuestMemory + ?Sized> Iterator for GuestMemorySliceIterator<'a, M> {
545545
}
546546
}
547547

548-
impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
548+
/// Allow accessing [`IoMemory`] (and [`GuestMemory`]) objects via [`Bytes`].
549+
///
550+
/// Thanks to the [blanket implementation of `IoMemory` for all `GuestMemory`
551+
/// types](../io_memory/trait.IoMemory.html#impl-IoMemory-for-M), this blanket implementation
552+
/// extends to all [`GuestMemory`] types.
553+
impl<T: IoMemory + ?Sized> Bytes<GuestAddress> for T {
549554
type E = Error;
550555

551556
fn write(&self, buf: &[u8], addr: GuestAddress) -> Result<usize> {
552557
self.try_access(
553558
buf.len(),
554559
addr,
560+
Permissions::Write,
555561
|offset, count, caddr, region| -> Result<usize> {
556562
region.write(&buf[offset..(offset + count)], caddr)
557563
},
@@ -562,6 +568,7 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
562568
self.try_access(
563569
buf.len(),
564570
addr,
571+
Permissions::Read,
565572
|offset, count, caddr, region| -> Result<usize> {
566573
region.read(&mut buf[offset..(offset + count)], caddr)
567574
},
@@ -629,9 +636,12 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
629636
where
630637
F: ReadVolatile,
631638
{
632-
self.try_access(count, addr, |_, len, caddr, region| -> Result<usize> {
633-
region.read_volatile_from(caddr, src, len)
634-
})
639+
self.try_access(
640+
count,
641+
addr,
642+
Permissions::Write,
643+
|_, len, caddr, region| -> Result<usize> { region.read_volatile_from(caddr, src, len) },
644+
)
635645
}
636646

637647
fn read_exact_volatile_from<F>(
@@ -657,11 +667,16 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
657667
where
658668
F: WriteVolatile,
659669
{
660-
self.try_access(count, addr, |_, len, caddr, region| -> Result<usize> {
661-
// For a non-RAM region, reading could have side effects, so we
662-
// must use write_all().
663-
region.write_all_volatile_to(caddr, dst, len).map(|()| len)
664-
})
670+
self.try_access(
671+
count,
672+
addr,
673+
Permissions::Read,
674+
|_, len, caddr, region| -> Result<usize> {
675+
// For a non-RAM region, reading could have side effects, so we
676+
// must use write_all().
677+
region.write_all_volatile_to(caddr, dst, len).map(|()| len)
678+
},
679+
)
665680
}
666681

667682
fn write_all_volatile_to<F>(&self, addr: GuestAddress, dst: &mut F, count: usize) -> Result<()>
@@ -684,6 +699,7 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
684699
let completed = self.try_access(
685700
expected,
686701
addr,
702+
Permissions::Write,
687703
|offset, len, region_addr, region| -> Result<usize> {
688704
assert_eq!(offset, 0);
689705
if len < expected {
@@ -713,6 +729,7 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
713729
let completed = self.try_access(
714730
expected,
715731
addr,
732+
Permissions::Read,
716733
|offset, len, region_addr, region| -> Result<usize> {
717734
assert_eq!(offset, 0);
718735
if len < expected {

0 commit comments

Comments
 (0)