@@ -12,8 +12,9 @@ use libc::{c_void, size_t};
12
12
13
13
use winapi:: um:: errhandlingapi:: GetLastError ;
14
14
15
+ use crate :: bitmap:: { Bitmap , BS } ;
15
16
use crate :: guest_memory:: FileOffset ;
16
- use crate :: mmap:: AsSlice ;
17
+ use crate :: mmap:: { AsSlice , NewBitmap } ;
17
18
use crate :: volatile_memory:: { self , compute_offset, VolatileMemory , VolatileSlice } ;
18
19
19
20
#[ allow( non_snake_case) ]
@@ -70,20 +71,21 @@ pub const ERROR_INVALID_PARAMETER: i32 = 87;
70
71
/// physical memory may be mapped into the current process due to the limited virtual address
71
72
/// space size of the process.
72
73
#[ derive( Debug ) ]
73
- pub struct MmapRegion {
74
+ pub struct MmapRegion < B > {
74
75
addr : * mut u8 ,
75
76
size : usize ,
77
+ bitmap : B ,
76
78
file_offset : Option < FileOffset > ,
77
79
}
78
80
79
81
// Send and Sync aren't automatically inherited for the raw address pointer.
80
82
// Accessing that pointer is only done through the stateless interface which
81
83
// allows the object to be shared by multiple threads without a decrease in
82
84
// safety.
83
- unsafe impl Send for MmapRegion { }
84
- unsafe impl Sync for MmapRegion { }
85
+ unsafe impl < B : Send > Send for MmapRegion < B > { }
86
+ unsafe impl < B : Sync > Sync for MmapRegion < B > { }
85
87
86
- impl MmapRegion {
88
+ impl < B : NewBitmap > MmapRegion < B > {
87
89
/// Creates a shared anonymous mapping of `size` bytes.
88
90
///
89
91
/// # Arguments
@@ -101,6 +103,7 @@ impl MmapRegion {
101
103
Ok ( Self {
102
104
addr : addr as * mut u8 ,
103
105
size,
106
+ bitmap : B :: with_len ( size) ,
104
107
file_offset : None ,
105
108
} )
106
109
}
@@ -155,11 +158,16 @@ impl MmapRegion {
155
158
Ok ( Self {
156
159
addr : addr as * mut u8 ,
157
160
size,
161
+ bitmap : B :: with_len ( size) ,
158
162
file_offset : Some ( file_offset) ,
159
163
} )
160
164
}
165
+ }
161
166
162
- /// Returns a pointer to the beginning of the memory region.
167
+ impl < B : Bitmap > MmapRegion < B > {
168
+ /// Returns a pointer to the beginning of the memory region. Mutable accesses performed
169
+ /// using the resulting pointer are not automatically accounted for by the dirty bitmap
170
+ /// tracking functionality.
163
171
///
164
172
/// Should only be used for passing this region to ioctls for setting guest memory.
165
173
pub fn as_ptr ( & self ) -> * mut u8 {
@@ -175,9 +183,14 @@ impl MmapRegion {
175
183
pub fn file_offset ( & self ) -> Option < & FileOffset > {
176
184
self . file_offset . as_ref ( )
177
185
}
186
+
187
+ /// Returns a reference to the inner bitmap object.
188
+ pub fn bitmap ( & self ) -> & B {
189
+ & self . bitmap
190
+ }
178
191
}
179
192
180
- impl AsSlice for MmapRegion {
193
+ impl < B > AsSlice for MmapRegion < B > {
181
194
unsafe fn as_slice ( & self ) -> & [ u8 ] {
182
195
// This is safe because we mapped the area at addr ourselves, so this slice will not
183
196
// overflow. However, it is possible to alias.
@@ -192,24 +205,36 @@ impl AsSlice for MmapRegion {
192
205
}
193
206
}
194
207
195
- impl VolatileMemory for MmapRegion {
208
+ impl < B : Bitmap > VolatileMemory for MmapRegion < B > {
209
+ type B = B ;
210
+
196
211
fn len ( & self ) -> usize {
197
212
self . size
198
213
}
199
214
200
- fn get_slice ( & self , offset : usize , count : usize ) -> volatile_memory:: Result < VolatileSlice > {
215
+ fn get_slice (
216
+ & self ,
217
+ offset : usize ,
218
+ count : usize ,
219
+ ) -> volatile_memory:: Result < VolatileSlice < BS < Self :: B > > > {
201
220
let end = compute_offset ( offset, count) ?;
202
221
if end > self . size {
203
222
return Err ( volatile_memory:: Error :: OutOfBounds { addr : end } ) ;
204
223
}
205
224
206
225
// Safe because we checked that offset + count was within our range and we only ever hand
207
226
// out volatile accessors.
208
- Ok ( unsafe { VolatileSlice :: new ( ( self . addr as usize + offset) as * mut _ , count) } )
227
+ Ok ( unsafe {
228
+ VolatileSlice :: with_bitmap (
229
+ ( self . addr as usize + offset) as * mut _ ,
230
+ count,
231
+ self . bitmap . slice_at ( offset) ,
232
+ )
233
+ } )
209
234
}
210
235
}
211
236
212
- impl Drop for MmapRegion {
237
+ impl < B > Drop for MmapRegion < B > {
213
238
fn drop ( & mut self ) {
214
239
// This is safe because we mmap the area at addr ourselves, and nobody
215
240
// else is holding a reference to it.
@@ -233,15 +258,27 @@ impl Drop for MmapRegion {
233
258
234
259
#[ cfg( test) ]
235
260
mod tests {
236
- use crate :: guest_memory:: FileOffset ;
237
- use crate :: mmap_windows:: { MmapRegion , INVALID_HANDLE_VALUE } ;
238
261
use std:: os:: windows:: io:: FromRawHandle ;
239
262
263
+ use crate :: bitmap:: AtomicBitmap ;
264
+ use crate :: guest_memory:: FileOffset ;
265
+ use crate :: mmap_windows:: INVALID_HANDLE_VALUE ;
266
+
267
+ type MmapRegion = super :: MmapRegion < ( ) > ;
268
+
240
269
#[ test]
241
270
fn map_invalid_handle ( ) {
242
271
let file = unsafe { std:: fs:: File :: from_raw_handle ( INVALID_HANDLE_VALUE ) } ;
243
272
let file_offset = FileOffset :: new ( file, 0 ) ;
244
273
let e = MmapRegion :: from_file ( file_offset, 1024 ) . unwrap_err ( ) ;
245
274
assert_eq ! ( e. raw_os_error( ) , Some ( libc:: EBADF ) ) ;
246
275
}
276
+
277
+ #[ test]
278
+ fn test_dirty_tracking ( ) {
279
+ // Using the `crate` prefix because we aliased `MmapRegion` to `MmapRegion<()>` for
280
+ // the rest of the unit tests above.
281
+ let m = crate :: MmapRegion :: < AtomicBitmap > :: new ( 0x1_0000 ) . unwrap ( ) ;
282
+ crate :: bitmap:: tests:: test_volatile_memory ( & m) ;
283
+ }
247
284
}
0 commit comments