@@ -52,7 +52,9 @@ use std::sync::Arc;
52
52
use crate :: address:: { Address , AddressValue } ;
53
53
use crate :: bitmap:: { Bitmap , BS , MS } ;
54
54
use crate :: bytes:: { AtomicAccess , Bytes } ;
55
+ use crate :: io:: { ReadVolatile , WriteVolatile } ;
55
56
use crate :: volatile_memory:: { self , VolatileSlice } ;
57
+ use crate :: GuestMemoryError ;
56
58
57
59
static MAX_ACCESS_CHUNK : usize = 4096 ;
58
60
@@ -665,6 +667,146 @@ pub trait GuestMemory {
665
667
}
666
668
}
667
669
670
+ /// Reads up to `count` bytes from an object and writes them into guest memory at `addr`.
671
+ ///
672
+ /// Returns the number of bytes written into guest memory.
673
+ ///
674
+ /// # Arguments
675
+ /// * `addr` - Begin writing at this address.
676
+ /// * `src` - Copy from `src` into the container.
677
+ /// * `count` - Copy `count` bytes from `src` into the container.
678
+ ///
679
+ /// # Examples
680
+ ///
681
+ /// * Read bytes from /dev/urandom (uses the `backend-mmap` feature)
682
+ ///
683
+ /// ```
684
+ /// # #[cfg(feature = "backend-mmap")]
685
+ /// # {
686
+ /// # use vm_memory::{Address, GuestMemory, Bytes, GuestAddress, GuestMemoryMmap};
687
+ /// # use std::fs::File;
688
+ /// # use std::path::Path;
689
+ /// #
690
+ /// # let start_addr = GuestAddress(0x1000);
691
+ /// # let gm = GuestMemoryMmap::<()>::from_ranges(&vec![(start_addr, 0x400)])
692
+ /// # .expect("Could not create guest memory");
693
+ /// # let addr = GuestAddress(0x1010);
694
+ /// # let mut file = if cfg!(unix) {
695
+ /// let mut file = File::open(Path::new("/dev/urandom")).expect("Could not open /dev/urandom");
696
+ /// # file
697
+ /// # } else {
698
+ /// # File::open(Path::new("c:\\Windows\\system32\\ntoskrnl.exe"))
699
+ /// # .expect("Could not open c:\\Windows\\system32\\ntoskrnl.exe")
700
+ /// # };
701
+ ///
702
+ /// gm.read_volatile_from(addr, &mut file, 128)
703
+ /// .expect("Could not read from /dev/urandom into guest memory");
704
+ ///
705
+ /// let read_addr = addr.checked_add(8).expect("Could not compute read address");
706
+ /// let rand_val: u32 = gm
707
+ /// .read_obj(read_addr)
708
+ /// .expect("Could not read u32 val from /dev/urandom");
709
+ /// # }
710
+ /// ```
711
+ fn read_volatile_from < F > ( & self , addr : GuestAddress , src : & mut F , count : usize ) -> Result < usize >
712
+ where
713
+ F : ReadVolatile ,
714
+ {
715
+ self . try_access ( count, addr, |offset, len, caddr, region| -> Result < usize > {
716
+ // Check if something bad happened before doing unsafe things.
717
+ assert ! ( offset <= count) ;
718
+
719
+ let len = std:: cmp:: min ( len, MAX_ACCESS_CHUNK ) ;
720
+
721
+ let mut vslice = region. get_slice ( caddr, len) ?;
722
+
723
+ src. read_volatile ( & mut vslice)
724
+ . map_err ( GuestMemoryError :: from)
725
+ } )
726
+ }
727
+
728
+ /// Reads up to `count` bytes from the container at `addr` and writes them it into guest memory.
729
+ ///
730
+ /// Returns the number of bytes written into guest memory.
731
+ ///
732
+ /// # Arguments
733
+ /// * `addr` - Begin reading from this address.
734
+ /// * `dst` - Copy from guest memory to `dst`.
735
+ /// * `count` - Copy `count` bytes from guest memory to `dst`.
736
+ fn write_volatile_to < F > ( & self , addr : GuestAddress , dst : & mut F , count : usize ) -> Result < usize >
737
+ where
738
+ F : WriteVolatile ,
739
+ {
740
+ self . try_access ( count, addr, |offset, len, caddr, region| -> Result < usize > {
741
+ // Check if something bad happened before doing unsafe things.
742
+ assert ! ( offset <= count) ;
743
+
744
+ let len = std:: cmp:: min ( len, MAX_ACCESS_CHUNK ) ;
745
+ let vslice = region. get_slice ( caddr, len) ?;
746
+
747
+ // For a non-RAM region, reading could have side effects, so we
748
+ // must use write_all().
749
+ dst. write_all_volatile ( & vslice) ?;
750
+
751
+ Ok ( len)
752
+ } )
753
+ }
754
+
755
+ /// Reads exactly `count` bytes from an object and writes them into guest memory at `addr`.
756
+ ///
757
+ /// # Errors
758
+ ///
759
+ /// Returns an error if `count` bytes couldn't have been copied from `src` to guest memory.
760
+ /// Part of the data may have been copied nevertheless.
761
+ ///
762
+ /// # Arguments
763
+ /// * `addr` - Begin writing at this address.
764
+ /// * `src` - Copy from `src` into guest memory.
765
+ /// * `count` - Copy exactly `count` bytes from `src` into guest memory.
766
+ fn read_exact_volatile_from < F > (
767
+ & self ,
768
+ addr : GuestAddress ,
769
+ src : & mut F ,
770
+ count : usize ,
771
+ ) -> Result < ( ) >
772
+ where
773
+ F : ReadVolatile ,
774
+ {
775
+ let res = self . read_volatile_from ( addr, src, count) ?;
776
+ if res != count {
777
+ return Err ( Error :: PartialBuffer {
778
+ expected : count,
779
+ completed : res,
780
+ } ) ;
781
+ }
782
+ Ok ( ( ) )
783
+ }
784
+
785
+ /// Reads exactly `count` bytes from the container at `addr` and writes them into guest memory.
786
+ ///
787
+ /// # Errors
788
+ ///
789
+ /// Returns an error if `count` bytes couldn't have been copied from guest memory to `dst`.
790
+ /// Part of the data may have been copied nevertheless.
791
+ ///
792
+ /// # Arguments
793
+ /// * `addr` - Begin reading from this address.
794
+ /// * `dst` - Copy from guest memory to `dst`.
795
+ /// * `count` - Copy exactly `count` bytes from guest memory to `dst`.
796
+ fn write_all_volatile_to < F > ( & self , addr : GuestAddress , dst : & mut F , count : usize ) -> Result < ( ) >
797
+ where
798
+ F : WriteVolatile ,
799
+ {
800
+ let res = self . write_volatile_to ( addr, dst, count) ?;
801
+ if res != count {
802
+ return Err ( Error :: PartialBuffer {
803
+ expected : count,
804
+ completed : res,
805
+ } ) ;
806
+ }
807
+ Ok ( ( ) )
808
+ }
809
+
668
810
/// Get the host virtual address corresponding to the guest address.
669
811
///
670
812
/// Some [`GuestMemory`](trait.GuestMemory.html) implementations, like `GuestMemoryMmap`,
@@ -985,8 +1127,6 @@ mod tests {
985
1127
#[ cfg( feature = "backend-mmap" ) ]
986
1128
use crate :: GuestAddress ;
987
1129
#[ cfg( feature = "backend-mmap" ) ]
988
- use std:: io:: Cursor ;
989
- #[ cfg( feature = "backend-mmap" ) ]
990
1130
use std:: time:: { Duration , Instant } ;
991
1131
992
1132
use vmm_sys_util:: tempfile:: TempFile ;
@@ -1026,7 +1166,7 @@ mod tests {
1026
1166
let count: usize = 0x20 ;
1027
1167
assert_eq ! (
1028
1168
0x20_usize ,
1029
- mem. read_from ( offset, & mut Cursor :: new ( & image) , count)
1169
+ mem. read_volatile_from ( offset, & mut image. as_slice ( ) , count)
1030
1170
. unwrap( )
1031
1171
) ;
1032
1172
}
@@ -1181,19 +1321,24 @@ mod tests {
1181
1321
assert ! ( mem. write_obj( obj, addr) . is_ok( ) ) ;
1182
1322
assert ! ( mem. read_obj:: <ZeroSizedStruct >( addr) . is_ok( ) ) ;
1183
1323
1184
- assert_eq ! ( mem. read_from( addr, & mut Cursor :: new( & image) , 0 ) . unwrap( ) , 0 ) ;
1324
+ assert_eq ! (
1325
+ mem. read_volatile_from( addr, & mut image. as_slice( ) , 0 )
1326
+ . unwrap( ) ,
1327
+ 0
1328
+ ) ;
1185
1329
1186
1330
assert ! ( mem
1187
- . read_exact_from ( addr, & mut Cursor :: new ( & image) , 0 )
1331
+ . read_exact_volatile_from ( addr, & mut image. as_slice ( ) , 0 )
1188
1332
. is_ok( ) ) ;
1189
1333
1190
1334
assert_eq ! (
1191
- mem. write_to( addr, & mut Cursor :: new( & mut image) , 0 ) . unwrap( ) ,
1335
+ mem. write_volatile_to( addr, & mut image. as_mut_slice( ) , 0 )
1336
+ . unwrap( ) ,
1192
1337
0
1193
1338
) ;
1194
1339
1195
1340
assert ! ( mem
1196
- . write_all_to ( addr, & mut Cursor :: new ( & mut image) , 0 )
1341
+ . write_all_volatile_to ( addr, & mut image. as_mut_slice ( ) , 0 )
1197
1342
. is_ok( ) ) ;
1198
1343
}
1199
1344
0 commit comments