32
32
//! Whenever a collection of `GuestMemoryRegion` objects is mutable,
33
33
//! [`GuestAddressSpace`](trait.GuestAddressSpace.html) should be implemented
34
34
//! for clients to obtain a [`GuestMemory`] reference or smart pointer.
35
+ //!
36
+ //! The `GuestMemoryRegion` trait has an associated `B: Bitmap` type which is used to handle
37
+ //! dirty bitmap tracking. Backends are free to define the granularity (or whether tracking is
38
+ //! actually performed at all). Those that do implement tracking functionality are expected to
39
+ //! ensure the correctness of the underlying `Bytes` implementation. The user has to explicitly
40
+ //! record (using the handle returned by `GuestRegionMmap::bitmap`) write accesses performed
41
+ //! via pointers, references, or slices returned by methods of `GuestMemory`,`GuestMemoryRegion`,
42
+ //! `VolatileSlice`, `VolatileRef`, or `VolatileArrayRef`.
35
43
36
44
use std:: convert:: From ;
37
45
use std:: fmt:: { self , Display } ;
@@ -43,8 +51,9 @@ use std::sync::atomic::Ordering;
43
51
use std:: sync:: Arc ;
44
52
45
53
use crate :: address:: { Address , AddressValue } ;
54
+ use crate :: bitmap:: { Bitmap , BS , MS } ;
46
55
use crate :: bytes:: { AtomicAccess , Bytes } ;
47
- use crate :: volatile_memory;
56
+ use crate :: volatile_memory:: { self , VolatileSlice } ;
48
57
49
58
static MAX_ACCESS_CHUNK : usize = 4096 ;
50
59
@@ -165,6 +174,9 @@ impl FileOffset {
165
174
/// Represents a continuous region of guest physical memory.
166
175
#[ allow( clippy:: len_without_is_empty) ]
167
176
pub trait GuestMemoryRegion : Bytes < MemoryRegionAddress , E = Error > {
177
+ /// Type used for dirty memory tracking.
178
+ type B : Bitmap ;
179
+
168
180
/// Returns the size of the region.
169
181
fn len ( & self ) -> GuestUsize ;
170
182
@@ -177,6 +189,9 @@ pub trait GuestMemoryRegion: Bytes<MemoryRegionAddress, E = Error> {
177
189
self . start_addr ( ) . unchecked_add ( self . len ( ) - 1 )
178
190
}
179
191
192
+ /// Borrow the associated `Bitmap` object.
193
+ fn bitmap ( & self ) -> & Self :: B ;
194
+
180
195
/// Returns the given address if it is within this region.
181
196
fn check_address ( & self , addr : MemoryRegionAddress ) -> Option < MemoryRegionAddress > {
182
197
if self . address_in_range ( addr) {
@@ -245,7 +260,9 @@ pub trait GuestMemoryRegion: Bytes<MemoryRegionAddress, E = Error> {
245
260
///
246
261
/// # Safety
247
262
///
248
- /// Unsafe because of possible aliasing.
263
+ /// Unsafe because of possible aliasing. Mutable accesses performed through the
264
+ /// returned slice are not visible to the dirty bitmap tracking functionality of
265
+ /// the region, and must be manually recorded using the associated bitmap object.
249
266
unsafe fn as_mut_slice ( & self ) -> Option < & mut [ u8 ] > {
250
267
None
251
268
}
@@ -257,7 +274,7 @@ pub trait GuestMemoryRegion: Bytes<MemoryRegionAddress, E = Error> {
257
274
& self ,
258
275
offset : MemoryRegionAddress ,
259
276
count : usize ,
260
- ) -> Result < volatile_memory :: VolatileSlice > {
277
+ ) -> Result < VolatileSlice < BS < Self :: B > > > {
261
278
Err ( Error :: HostAddressNotAvailable )
262
279
}
263
280
@@ -286,7 +303,7 @@ pub trait GuestMemoryRegion: Bytes<MemoryRegionAddress, E = Error> {
286
303
/// assert_eq!(r.load(), v);
287
304
/// # }
288
305
/// ```
289
- fn as_volatile_slice ( & self ) -> Result < volatile_memory :: VolatileSlice > {
306
+ fn as_volatile_slice ( & self ) -> Result < VolatileSlice < BS < Self :: B > > > {
290
307
self . get_slice ( MemoryRegionAddress ( 0 ) , self . len ( ) as usize )
291
308
}
292
309
@@ -386,26 +403,26 @@ pub trait GuestAddressSpace {
386
403
}
387
404
388
405
impl < M : GuestMemory > GuestAddressSpace for & M {
389
- type T = Self ;
390
406
type M = M ;
407
+ type T = Self ;
391
408
392
409
fn memory ( & self ) -> Self {
393
410
self
394
411
}
395
412
}
396
413
397
414
impl < M : GuestMemory > GuestAddressSpace for Rc < M > {
398
- type T = Self ;
399
415
type M = M ;
416
+ type T = Self ;
400
417
401
418
fn memory ( & self ) -> Self {
402
419
self . clone ( )
403
420
}
404
421
}
405
422
406
423
impl < M : GuestMemory > GuestAddressSpace for Arc < M > {
407
- type T = Self ;
408
424
type M = M ;
425
+ type T = Self ;
409
426
410
427
fn memory ( & self ) -> Self {
411
428
self . clone ( )
@@ -705,11 +722,7 @@ pub trait GuestMemory {
705
722
706
723
/// Returns a [`VolatileSlice`](struct.VolatileSlice.html) of `count` bytes starting at
707
724
/// `addr`.
708
- fn get_slice (
709
- & self ,
710
- addr : GuestAddress ,
711
- count : usize ,
712
- ) -> Result < volatile_memory:: VolatileSlice > {
725
+ fn get_slice ( & self , addr : GuestAddress , count : usize ) -> Result < VolatileSlice < MS < Self > > > {
713
726
self . to_region_addr ( addr)
714
727
. ok_or ( Error :: InvalidGuestAddress ( addr) )
715
728
. and_then ( |( r, addr) | r. get_slice ( addr, count) )
@@ -836,22 +849,29 @@ impl<T: GuestMemory> Bytes<GuestAddress> for T {
836
849
// Check if something bad happened before doing unsafe things.
837
850
assert ! ( offset <= count) ;
838
851
if let Some ( dst) = unsafe { region. as_mut_slice ( ) } {
839
- // This is safe cause `start` and `len` are within the `region`.
852
+ // This is safe cause `start` and `len` are within the `region`, and we manually
853
+ // record the dirty status of the written range below.
840
854
let start = caddr. raw_value ( ) as usize ;
841
855
let end = start + len;
842
- loop {
856
+ let result = loop {
843
857
match src. read ( & mut dst[ start..end] ) {
844
858
Ok ( n) => break Ok ( n) ,
845
859
Err ( ref e) if e. kind ( ) == std:: io:: ErrorKind :: Interrupted => continue ,
846
860
Err ( e) => break Err ( Error :: IOError ( e) ) ,
847
861
}
848
- }
862
+ } ;
863
+
864
+ region. bitmap ( ) . mark_dirty ( start, len) ;
865
+ result
849
866
} else {
850
867
let len = std:: cmp:: min ( len, MAX_ACCESS_CHUNK ) ;
851
868
let mut buf = vec ! [ 0u8 ; len] . into_boxed_slice ( ) ;
852
869
loop {
853
870
match src. read ( & mut buf[ ..] ) {
854
871
Ok ( bytes_read) => {
872
+ // We don't need to update the dirty bitmap manually here because it's
873
+ // expected to be handled by the logic within the `Bytes`
874
+ // implementation for the region object.
855
875
let bytes_written = region. write ( & buf[ 0 ..bytes_read] , caddr) ?;
856
876
assert_eq ! ( bytes_written, bytes_read) ;
857
877
break Ok ( bytes_read) ;
@@ -1008,14 +1028,17 @@ mod tests {
1008
1028
#[ cfg( feature = "backend-mmap" ) ]
1009
1029
use crate :: bytes:: ByteValued ;
1010
1030
#[ cfg( feature = "backend-mmap" ) ]
1011
- use crate :: { GuestAddress , GuestMemoryMmap } ;
1031
+ use crate :: GuestAddress ;
1012
1032
#[ cfg( feature = "backend-mmap" ) ]
1013
1033
use std:: io:: Cursor ;
1014
1034
#[ cfg( feature = "backend-mmap" ) ]
1015
1035
use std:: time:: { Duration , Instant } ;
1016
1036
1017
1037
use vmm_sys_util:: tempfile:: TempFile ;
1018
1038
1039
+ #[ cfg( feature = "backend-mmap" ) ]
1040
+ type GuestMemoryMmap = crate :: GuestMemoryMmap < ( ) > ;
1041
+
1019
1042
#[ cfg( feature = "backend-mmap" ) ]
1020
1043
fn make_image ( size : u8 ) -> Vec < u8 > {
1021
1044
let mut image: Vec < u8 > = Vec :: with_capacity ( size as usize ) ;
0 commit comments