Skip to content

Commit 90e0fbf

Browse files
roypatbonzini
authored andcommitted
fix: move volatile memory access methods to Bytes trait
The `read_[exact_]_volatile_from` and `write_[all_]volatile_to` functions were intended to be replacements for their `Read` and `Write` based counterparts. However, those used to live in the `Bytes` trait, not the `GuestMemory` trait. Fix up this goof on my part by moving them to the `Bytes` trait. Signed-off-by: Patrick Roy <roypat@amazon.co.uk>
1 parent 51245be commit 90e0fbf

File tree

5 files changed

+300
-135
lines changed

5 files changed

+300
-135
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66

77
- \[[#311](https://github.com/rust-vmm/vm-memory/pull/311)\] Allow compiling without the ReadVolatile and WriteVolatile implementations
88

9+
### Changed
10+
11+
- \[[#307](https://github.com/rust-vmm/vm-memory/pull/304)\] Move `read_volatile_from`, `read_exact_volatile_from`,
12+
`write_volatile_to` and `write_all_volatile_to` functions from the `GuestMemory` trait to the `Bytes` trait.
13+
914
### Removed
1015

1116
- \[[#307](https://github.com/rust-vmm/vm-memory/pull/304)\] Remove deprecated functions `Bytes::read_from`, `Bytes::read_exact_from`,

src/bytes.rs

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use std::sync::atomic::Ordering;
1818

1919
use crate::atomic_integer::AtomicInteger;
2020
use crate::volatile_memory::VolatileSlice;
21+
use crate::{ReadVolatile, WriteVolatile};
2122

2223
/// Types for which it is safe to initialize from raw data.
2324
///
@@ -276,6 +277,102 @@ pub trait Bytes<A> {
276277
self.read_slice(result.as_mut_slice(), addr).map(|_| result)
277278
}
278279

280+
/// Reads up to `count` bytes from `src` and writes them into the container at `addr`.
281+
/// Unlike `VolatileRead::read_volatile`, this function retries on `EINTR` being returned from
282+
/// the underlying I/O `read` operation.
283+
///
284+
/// Returns the number of bytes written into the container.
285+
///
286+
/// # Arguments
287+
/// * `addr` - Begin writing at this address.
288+
/// * `src` - Copy from `src` into the container.
289+
/// * `count` - Copy `count` bytes from `src` into the container.
290+
///
291+
/// # Examples
292+
///
293+
/// * Read bytes from /dev/urandom (uses the `backend-mmap` feature)
294+
///
295+
/// ```
296+
/// # #[cfg(all(feature = "backend-mmap", feature = "rawfd"))]
297+
/// # {
298+
/// # use vm_memory::{Address, GuestMemory, Bytes, GuestAddress, GuestMemoryMmap};
299+
/// # use std::fs::File;
300+
/// # use std::path::Path;
301+
/// #
302+
/// # let start_addr = GuestAddress(0x1000);
303+
/// # let gm = GuestMemoryMmap::<()>::from_ranges(&vec![(start_addr, 0x400)])
304+
/// # .expect("Could not create guest memory");
305+
/// # let addr = GuestAddress(0x1010);
306+
/// # let mut file = if cfg!(unix) {
307+
/// let mut file = File::open(Path::new("/dev/urandom")).expect("Could not open /dev/urandom");
308+
/// # file
309+
/// # } else {
310+
/// # File::open(Path::new("c:\\Windows\\system32\\ntoskrnl.exe"))
311+
/// # .expect("Could not open c:\\Windows\\system32\\ntoskrnl.exe")
312+
/// # };
313+
///
314+
/// gm.read_volatile_from(addr, &mut file, 128)
315+
/// .expect("Could not read from /dev/urandom into guest memory");
316+
///
317+
/// let read_addr = addr.checked_add(8).expect("Could not compute read address");
318+
/// let rand_val: u32 = gm
319+
/// .read_obj(read_addr)
320+
/// .expect("Could not read u32 val from /dev/urandom");
321+
/// # }
322+
/// ```
323+
fn read_volatile_from<F>(&self, addr: A, src: &mut F, count: usize) -> Result<usize, Self::E>
324+
where
325+
F: ReadVolatile;
326+
327+
/// Reads exactly `count` bytes from an object and writes them into the container at `addr`.
328+
///
329+
/// # Errors
330+
///
331+
/// Returns an error if `count` bytes couldn't have been copied from `src` to the container.
332+
/// Part of the data may have been copied nevertheless.
333+
///
334+
/// # Arguments
335+
/// * `addr` - Begin writing at this address.
336+
/// * `src` - Copy from `src` into the container.
337+
/// * `count` - Copy exactly `count` bytes from `src` into the container.
338+
fn read_exact_volatile_from<F>(
339+
&self,
340+
addr: A,
341+
src: &mut F,
342+
count: usize,
343+
) -> Result<(), Self::E>
344+
where
345+
F: ReadVolatile;
346+
347+
/// Reads up to `count` bytes from the container at `addr` and writes them into `dst`.
348+
/// Unlike `VolatileWrite::write_volatile`, this function retries on `EINTR` being returned by
349+
/// the underlying I/O `write` operation.
350+
///
351+
/// Returns the number of bytes written into the object.
352+
///
353+
/// # Arguments
354+
/// * `addr` - Begin reading from this address.
355+
/// * `dst` - Copy from the container to `dst`.
356+
/// * `count` - Copy `count` bytes from the container to `dst`.
357+
fn write_volatile_to<F>(&self, addr: A, dst: &mut F, count: usize) -> Result<usize, Self::E>
358+
where
359+
F: WriteVolatile;
360+
361+
/// Reads exactly `count` bytes from the container at `addr` and writes them into an object.
362+
///
363+
/// # Errors
364+
///
365+
/// Returns an error if `count` bytes couldn't have been copied from the container to `dst`.
366+
/// Part of the data may have been copied nevertheless.
367+
///
368+
/// # Arguments
369+
/// * `addr` - Begin reading from this address.
370+
/// * `dst` - Copy from the container to `dst`.
371+
/// * `count` - Copy exactly `count` bytes from the container to `dst`.
372+
fn write_all_volatile_to<F>(&self, addr: A, dst: &mut F, count: usize) -> Result<(), Self::E>
373+
where
374+
F: WriteVolatile;
375+
279376
/// Atomically store a value at the specified address.
280377
fn store<T: AtomicAccess>(&self, val: T, addr: A, order: Ordering) -> Result<(), Self::E>;
281378

@@ -414,6 +511,54 @@ pub(crate) mod tests {
414511
Ok(())
415512
}
416513

514+
fn read_volatile_from<F>(
515+
&self,
516+
_addr: usize,
517+
_src: &mut F,
518+
_count: usize,
519+
) -> Result<usize, Self::E>
520+
where
521+
F: ReadVolatile,
522+
{
523+
unimplemented!()
524+
}
525+
526+
fn read_exact_volatile_from<F>(
527+
&self,
528+
_addr: usize,
529+
_src: &mut F,
530+
_count: usize,
531+
) -> Result<(), Self::E>
532+
where
533+
F: ReadVolatile,
534+
{
535+
unimplemented!()
536+
}
537+
538+
fn write_volatile_to<F>(
539+
&self,
540+
_addr: usize,
541+
_dst: &mut F,
542+
_count: usize,
543+
) -> Result<usize, Self::E>
544+
where
545+
F: WriteVolatile,
546+
{
547+
unimplemented!()
548+
}
549+
550+
fn write_all_volatile_to<F>(
551+
&self,
552+
_addr: usize,
553+
_dst: &mut F,
554+
_count: usize,
555+
) -> Result<(), Self::E>
556+
where
557+
F: WriteVolatile,
558+
{
559+
unimplemented!()
560+
}
561+
417562
fn store<T: AtomicAccess>(
418563
&self,
419564
_val: T,

src/guest_memory.rs

Lines changed: 53 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ use crate::bitmap::{Bitmap, BS, MS};
5454
use crate::bytes::{AtomicAccess, Bytes};
5555
use crate::io::{ReadVolatile, WriteVolatile};
5656
use crate::volatile_memory::{self, VolatileSlice};
57-
use crate::GuestMemoryError;
5857

5958
/// Errors associated with handling guest memory accesses.
6059
#[allow(missing_docs)]
@@ -538,137 +537,6 @@ pub trait GuestMemory {
538537
}
539538
}
540539

541-
/// Reads up to `count` bytes from an object and writes them into guest memory at `addr`.
542-
///
543-
/// Returns the number of bytes written into guest memory.
544-
///
545-
/// # Arguments
546-
/// * `addr` - Begin writing at this address.
547-
/// * `src` - Copy from `src` into the container.
548-
/// * `count` - Copy `count` bytes from `src` into the container.
549-
///
550-
/// # Examples
551-
///
552-
/// * Read bytes from /dev/urandom (uses the `backend-mmap` feature)
553-
///
554-
/// ```
555-
/// # #[cfg(all(feature = "backend-mmap", feature = "rawfd"))]
556-
/// # {
557-
/// # use vm_memory::{Address, GuestMemory, Bytes, GuestAddress, GuestMemoryMmap};
558-
/// # use std::fs::File;
559-
/// # use std::path::Path;
560-
/// #
561-
/// # let start_addr = GuestAddress(0x1000);
562-
/// # let gm = GuestMemoryMmap::<()>::from_ranges(&vec![(start_addr, 0x400)])
563-
/// # .expect("Could not create guest memory");
564-
/// # let addr = GuestAddress(0x1010);
565-
/// # let mut file = if cfg!(unix) {
566-
/// let mut file = File::open(Path::new("/dev/urandom")).expect("Could not open /dev/urandom");
567-
/// # file
568-
/// # } else {
569-
/// # File::open(Path::new("c:\\Windows\\system32\\ntoskrnl.exe"))
570-
/// # .expect("Could not open c:\\Windows\\system32\\ntoskrnl.exe")
571-
/// # };
572-
///
573-
/// gm.read_volatile_from(addr, &mut file, 128)
574-
/// .expect("Could not read from /dev/urandom into guest memory");
575-
///
576-
/// let read_addr = addr.checked_add(8).expect("Could not compute read address");
577-
/// let rand_val: u32 = gm
578-
/// .read_obj(read_addr)
579-
/// .expect("Could not read u32 val from /dev/urandom");
580-
/// # }
581-
/// ```
582-
fn read_volatile_from<F>(&self, addr: GuestAddress, src: &mut F, count: usize) -> Result<usize>
583-
where
584-
F: ReadVolatile,
585-
{
586-
self.try_access(count, addr, |_, len, caddr, region| -> Result<usize> {
587-
let mut vslice = region.get_slice(caddr, len)?;
588-
589-
src.read_volatile(&mut vslice)
590-
.map_err(GuestMemoryError::from)
591-
})
592-
}
593-
594-
/// Reads up to `count` bytes from guest memory at `addr` and writes them it into an object.
595-
///
596-
/// Returns the number of bytes copied from guest memory.
597-
///
598-
/// # Arguments
599-
/// * `addr` - Begin reading from this address.
600-
/// * `dst` - Copy from guest memory to `dst`.
601-
/// * `count` - Copy `count` bytes from guest memory to `dst`.
602-
fn write_volatile_to<F>(&self, addr: GuestAddress, dst: &mut F, count: usize) -> Result<usize>
603-
where
604-
F: WriteVolatile,
605-
{
606-
self.try_access(count, addr, |_, len, caddr, region| -> Result<usize> {
607-
let vslice = region.get_slice(caddr, len)?;
608-
609-
// For a non-RAM region, reading could have side effects, so we
610-
// must use write_all().
611-
dst.write_all_volatile(&vslice)?;
612-
613-
Ok(len)
614-
})
615-
}
616-
617-
/// Reads exactly `count` bytes from an object and writes them into guest memory at `addr`.
618-
///
619-
/// # Errors
620-
///
621-
/// Returns an error if `count` bytes couldn't have been copied from `src` to guest memory.
622-
/// Part of the data may have been copied nevertheless.
623-
///
624-
/// # Arguments
625-
/// * `addr` - Begin writing at this address.
626-
/// * `src` - Copy from `src` into guest memory.
627-
/// * `count` - Copy exactly `count` bytes from `src` into guest memory.
628-
fn read_exact_volatile_from<F>(
629-
&self,
630-
addr: GuestAddress,
631-
src: &mut F,
632-
count: usize,
633-
) -> Result<()>
634-
where
635-
F: ReadVolatile,
636-
{
637-
let res = self.read_volatile_from(addr, src, count)?;
638-
if res != count {
639-
return Err(Error::PartialBuffer {
640-
expected: count,
641-
completed: res,
642-
});
643-
}
644-
Ok(())
645-
}
646-
647-
/// Reads exactly `count` bytes from guest memory at `addr` and writes them into an object.
648-
///
649-
/// # Errors
650-
///
651-
/// Returns an error if `count` bytes couldn't have been copied from guest memory to `dst`.
652-
/// Part of the data may have been copied nevertheless.
653-
///
654-
/// # Arguments
655-
/// * `addr` - Begin reading from this address.
656-
/// * `dst` - Copy from guest memory to `dst`.
657-
/// * `count` - Copy exactly `count` bytes from guest memory to `dst`.
658-
fn write_all_volatile_to<F>(&self, addr: GuestAddress, dst: &mut F, count: usize) -> Result<()>
659-
where
660-
F: WriteVolatile,
661-
{
662-
let res = self.write_volatile_to(addr, dst, count)?;
663-
if res != count {
664-
return Err(Error::PartialBuffer {
665-
expected: count,
666-
completed: res,
667-
});
668-
}
669-
Ok(())
670-
}
671-
672540
/// Get the host virtual address corresponding to the guest address.
673541
///
674542
/// Some [`GuestMemory`](trait.GuestMemory.html) implementations, like `GuestMemoryMmap`,
@@ -796,6 +664,59 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
796664
Ok(())
797665
}
798666

667+
fn read_volatile_from<F>(&self, addr: GuestAddress, src: &mut F, count: usize) -> Result<usize>
668+
where
669+
F: ReadVolatile,
670+
{
671+
self.try_access(count, addr, |_, len, caddr, region| -> Result<usize> {
672+
region.read_volatile_from(caddr, src, len)
673+
})
674+
}
675+
676+
fn read_exact_volatile_from<F>(
677+
&self,
678+
addr: GuestAddress,
679+
src: &mut F,
680+
count: usize,
681+
) -> Result<()>
682+
where
683+
F: ReadVolatile,
684+
{
685+
let res = self.read_volatile_from(addr, src, count)?;
686+
if res != count {
687+
return Err(Error::PartialBuffer {
688+
expected: count,
689+
completed: res,
690+
});
691+
}
692+
Ok(())
693+
}
694+
695+
fn write_volatile_to<F>(&self, addr: GuestAddress, dst: &mut F, count: usize) -> Result<usize>
696+
where
697+
F: WriteVolatile,
698+
{
699+
self.try_access(count, addr, |_, len, caddr, region| -> Result<usize> {
700+
// For a non-RAM region, reading could have side effects, so we
701+
// must use write_all().
702+
region.write_all_volatile_to(caddr, dst, len).map(|()| len)
703+
})
704+
}
705+
706+
fn write_all_volatile_to<F>(&self, addr: GuestAddress, dst: &mut F, count: usize) -> Result<()>
707+
where
708+
F: WriteVolatile,
709+
{
710+
let res = self.write_volatile_to(addr, dst, count)?;
711+
if res != count {
712+
return Err(Error::PartialBuffer {
713+
expected: count,
714+
completed: res,
715+
});
716+
}
717+
Ok(())
718+
}
719+
799720
fn store<O: AtomicAccess>(&self, val: O, addr: GuestAddress, order: Ordering) -> Result<()> {
800721
// `find_region` should really do what `to_region_addr` is doing right now, except
801722
// it should keep returning a `Result`.

0 commit comments

Comments
 (0)