@@ -37,7 +37,7 @@ use crate::atomic_integer::AtomicInteger;
37
37
use crate :: bitmap:: { Bitmap , BitmapSlice , BS } ;
38
38
use crate :: { AtomicAccess , ByteValued , Bytes } ;
39
39
40
- use copy_slice_impl:: copy_slice ;
40
+ use copy_slice_impl:: { copy_from_volatile_slice , copy_to_volatile_slice } ;
41
41
42
42
/// `VolatileMemory` related errors.
43
43
#[ allow( missing_docs) ]
@@ -390,7 +390,7 @@ impl<'a, B: BitmapSlice> VolatileSlice<'a, B> {
390
390
// a slice and thus has to live outside of guest memory (there can be more slices to
391
391
// guest memory without violating rust's aliasing rules)
392
392
// - size is always a multiple of alignment, so treating *mut T as *mut u8 is fine
393
- unsafe { copy_slice ( buf. as_mut_ptr ( ) as * mut u8 , self . as_ptr ( ) , total) }
393
+ unsafe { copy_from_volatile_slice ( buf. as_mut_ptr ( ) as * mut u8 , self , total) }
394
394
} else {
395
395
let count = self . size / size_of :: < T > ( ) ;
396
396
let source = self . get_array_ref :: < T > ( 0 , count) . unwrap ( ) ;
@@ -468,9 +468,7 @@ impl<'a, B: BitmapSlice> VolatileSlice<'a, B> {
468
468
// a slice and thus has to live outside of guest memory (there can be more slices to
469
469
// guest memory without violating rust's aliasing rules)
470
470
// - size is always a multiple of alignment, so treating *mut T as *mut u8 is fine
471
- let count = unsafe { copy_slice ( self . as_ptr ( ) , buf. as_ptr ( ) as * const u8 , total) } ;
472
-
473
- self . bitmap . mark_dirty ( 0 , count * size_of :: < T > ( ) ) ;
471
+ unsafe { copy_to_volatile_slice ( self , buf. as_ptr ( ) as * const u8 , total) } ;
474
472
} else {
475
473
let count = self . size / size_of :: < T > ( ) ;
476
474
// It's ok to use unwrap here because `count` was computed based on the current
@@ -523,22 +521,17 @@ impl<B: BitmapSlice> Bytes<usize> for VolatileSlice<'_, B> {
523
521
}
524
522
525
523
let total = buf. len ( ) . min ( self . len ( ) - addr) ;
524
+ let dst = self . subslice ( addr, total) ?;
526
525
527
526
// SAFETY:
528
527
// We check above that `addr` is a valid offset within this volatile slice, and by
529
528
// the invariants of `VolatileSlice::new`, this volatile slice points to contiguous
530
- // memory of length self.len(). Furthermore, both src and dst of the call to copy_slice
531
- // are valid for reads and writes respectively of length `total` since total is the minimum
532
- // of lengths of the memory areas pointed to. The areas do not overlap, since `dst` is
533
- // inside guest memory, and buf is a slice (no slices to guest memory are possible without
534
- // violating rust's aliasing rules).
535
- let count = unsafe {
536
- let dst = self . as_ptr ( ) . add ( addr) ;
537
- copy_slice ( dst, buf. as_ptr ( ) , total)
538
- } ;
539
-
540
- self . bitmap . mark_dirty ( addr, count) ;
541
- Ok ( count)
529
+ // memory of length self.len(). Furthermore, both src and dst of the call to
530
+ // copy_to_volatile_slice are valid for reads and writes respectively of length `total`
531
+ // since total is the minimum of lengths of the memory areas pointed to. The areas do not
532
+ // overlap, since `dst` is inside guest memory, and buf is a slice (no slices to guest
533
+ // memory are possible without violating rust's aliasing rules).
534
+ Ok ( unsafe { copy_to_volatile_slice ( & dst, buf. as_ptr ( ) , total) } )
542
535
}
543
536
544
537
/// # Examples
@@ -565,19 +558,17 @@ impl<B: BitmapSlice> Bytes<usize> for VolatileSlice<'_, B> {
565
558
}
566
559
567
560
let total = buf. len ( ) . min ( self . len ( ) - addr) ;
561
+ let src = self . subslice ( addr, total) ?;
568
562
569
563
// SAFETY:
570
564
// We check above that `addr` is a valid offset within this volatile slice, and by
571
565
// the invariants of `VolatileSlice::new`, this volatile slice points to contiguous
572
- // memory of length self.len(). Furthermore, both src and dst of the call to copy_slice
573
- // are valid for reads and writes respectively of length `total` since total is the minimum
574
- // of lengths of the memory areas pointed to. The areas do not overlap, since `dst` is
575
- // inside guest memory, and buf is a slice (no slices to guest memory are possible without
576
- // violating rust's aliasing rules).
577
- unsafe {
578
- let src = self . as_ptr ( ) . add ( addr) ;
579
- Ok ( copy_slice ( buf. as_mut_ptr ( ) , src, total) )
580
- }
566
+ // memory of length self.len(). Furthermore, both src and dst of the call to
567
+ // copy_from_volatile_slice are valid for reads and writes respectively of length `total`
568
+ // since total is the minimum of lengths of the memory areas pointed to. The areas do not
569
+ // overlap, since `dst` is inside guest memory, and buf is a slice (no slices to guest
570
+ // memory are possible without violating rust's aliasing rules).
571
+ unsafe { Ok ( copy_from_volatile_slice ( buf. as_mut_ptr ( ) , & src, total) ) }
581
572
}
582
573
583
574
/// # Examples
@@ -680,16 +671,13 @@ impl<B: BitmapSlice> Bytes<usize> for VolatileSlice<'_, B> {
680
671
// Read::read.
681
672
assert ! ( bytes_read <= count) ;
682
673
674
+ let slice = self . subslice ( addr, bytes_read) ?;
675
+
683
676
// SAFETY: We have checked via compute_end_offset that accessing the specified
684
677
// region of guest memory is valid. We asserted that the value returned by `read` is between
685
678
// 0 and count (the length of the buffer passed to it), and that the
686
679
// regions don't overlap because we allocated the Vec outside of guest memory.
687
- unsafe {
688
- copy_slice ( self . as_ptr ( ) . add ( addr) , dst. as_ptr ( ) , bytes_read) ;
689
- }
690
-
691
- self . bitmap . mark_dirty ( addr, bytes_read) ;
692
- Ok ( bytes_read)
680
+ Ok ( unsafe { copy_to_volatile_slice ( & slice, dst. as_ptr ( ) , bytes_read) } )
693
681
}
694
682
695
683
/// # Examples
@@ -726,14 +714,12 @@ impl<B: BitmapSlice> Bytes<usize> for VolatileSlice<'_, B> {
726
714
// Read into buffer that can be copied into guest memory
727
715
src. read_exact ( & mut dst) . map_err ( Error :: IOError ) ?;
728
716
717
+ let slice = self . subslice ( addr, count) ?;
718
+
729
719
// SAFETY: We have checked via compute_end_offset that accessing the specified
730
720
// region of guest memory is valid. We know that `dst` has len `count`, and that the
731
721
// regions don't overlap because we allocated the Vec outside of guest memory
732
- unsafe {
733
- copy_slice ( self . as_ptr ( ) . add ( addr) , dst. as_ptr ( ) , count) ;
734
- }
735
-
736
- self . bitmap . mark_dirty ( addr, count) ;
722
+ unsafe { copy_to_volatile_slice ( & slice, dst. as_ptr ( ) , count) } ;
737
723
Ok ( ( ) )
738
724
}
739
725
@@ -765,14 +751,17 @@ impl<B: BitmapSlice> Bytes<usize> for VolatileSlice<'_, B> {
765
751
{
766
752
let _ = self . compute_end_offset ( addr, count) ?;
767
753
let mut src = Vec :: with_capacity ( count) ;
754
+
755
+ let slice = self . subslice ( addr, count) ?;
756
+
768
757
// SAFETY: We checked the addr and count so accessing the slice is safe.
769
758
// It is safe to read from volatile memory. The Vec has capacity for exactly `count`
770
759
// many bytes, and the memory regions pointed to definitely do not overlap, as we
771
760
// allocated src outside of guest memory.
772
761
// The call to set_len is safe because the bytes between 0 and count have been initialized
773
762
// via copying from guest memory, and the Vec's capacity is `count`
774
763
unsafe {
775
- copy_slice ( src. as_mut_ptr ( ) , self . as_ptr ( ) . add ( addr ) , count) ;
764
+ copy_from_volatile_slice ( src. as_mut_ptr ( ) , & slice , count) ;
776
765
src. set_len ( count) ;
777
766
}
778
767
@@ -814,14 +803,16 @@ impl<B: BitmapSlice> Bytes<usize> for VolatileSlice<'_, B> {
814
803
let _ = self . compute_end_offset ( addr, count) ?;
815
804
let mut src = Vec :: with_capacity ( count) ;
816
805
806
+ let slice = self . subslice ( addr, count) ?;
807
+
817
808
// SAFETY: We checked the addr and count so accessing the slice is safe.
818
809
// It is safe to read from volatile memory. The Vec has capacity for exactly `count`
819
810
// many bytes, and the memory regions pointed to definitely do not overlap, as we
820
811
// allocated src outside of guest memory.
821
812
// The call to set_len is safe because the bytes between 0 and count have been initialized
822
813
// via copying from guest memory, and the Vec's capacity is `count`
823
814
unsafe {
824
- copy_slice ( src. as_mut_ptr ( ) , self . as_ptr ( ) . add ( addr ) , count) ;
815
+ copy_from_volatile_slice ( src. as_mut_ptr ( ) , & slice , count) ;
825
816
src. set_len ( count) ;
826
817
}
827
818
@@ -1176,7 +1167,9 @@ where
1176
1167
// a slice and thus has to live outside of guest memory (there can be more slices to
1177
1168
// guest memory without violating rust's aliasing rules)
1178
1169
// - size is always a multiple of alignment, so treating *mut T as *mut u8 is fine
1179
- return unsafe { copy_slice ( buf. as_mut_ptr ( ) as * mut u8 , source. as_ptr ( ) , total) } ;
1170
+ return unsafe {
1171
+ copy_from_volatile_slice ( buf. as_mut_ptr ( ) as * mut u8 , & source, total)
1172
+ } ;
1180
1173
}
1181
1174
1182
1175
let mut addr = self . addr ;
@@ -1253,16 +1246,14 @@ where
1253
1246
let total = buf. len ( ) . min ( destination. len ( ) ) ;
1254
1247
1255
1248
// absurd formatting brought to you by clippy
1256
- let count =
1257
1249
// SAFETY:
1258
1250
// - dst is valid for writes of at least `total`, since total <= destination.len()
1259
1251
// - src is valid for reads of at least `total` as total <= buf.len()
1260
1252
// - The regions are non-overlapping as `dst` points to guest memory and `buf` is
1261
1253
// a slice and thus has to live outside of guest memory (there can be more slices to
1262
1254
// guest memory without violating rust's aliasing rules)
1263
1255
// - size is always a multiple of alignment, so treating *const T as *const u8 is fine
1264
- unsafe { copy_slice ( destination. as_ptr ( ) , buf. as_ptr ( ) as * const u8 , total) } ;
1265
- self . bitmap . mark_dirty ( 0 , count) ;
1256
+ unsafe { copy_to_volatile_slice ( & destination, buf. as_ptr ( ) as * const u8 , total) } ;
1266
1257
} else {
1267
1258
let mut addr = self . addr ;
1268
1259
for & v in buf. iter ( ) . take ( self . len ( ) ) {
@@ -1371,7 +1362,7 @@ mod copy_slice_impl {
1371
1362
///
1372
1363
/// SAFETY: `src` and `dst` must be point to a contiguously allocated memory region of at least
1373
1364
/// length `total`. The regions must not overlap
1374
- pub ( super ) unsafe fn copy_slice ( dst : * mut u8 , src : * const u8 , total : usize ) -> usize {
1365
+ unsafe fn copy_slice ( dst : * mut u8 , src : * const u8 , total : usize ) -> usize {
1375
1366
if total <= size_of :: < usize > ( ) {
1376
1367
// SAFETY: Invariants of copy_slice_volatile are the same as invariants of copy_slice
1377
1368
unsafe {
@@ -1390,6 +1381,34 @@ mod copy_slice_impl {
1390
1381
1391
1382
total
1392
1383
}
1384
+
1385
+ /// Copies `total` bytes from `slice` to `dst`
1386
+ ///
1387
+ /// SAFETY: `slice` and `dst` must be point to a contiguously allocated memory region of at
1388
+ /// least length `total`. The regions must not overlap.
1389
+ pub ( super ) unsafe fn copy_from_volatile_slice < B : BitmapSlice > (
1390
+ dst : * mut u8 ,
1391
+ slice : & VolatileSlice < ' _ , B > ,
1392
+ total : usize ,
1393
+ ) -> usize {
1394
+ // SAFETY: guaranteed by function invariants.
1395
+ copy_slice ( dst, slice. as_ptr ( ) , total)
1396
+ }
1397
+
1398
+ /// Copies `total` bytes from 'src' to `slice`
1399
+ ///
1400
+ /// SAFETY: `slice` and `src` must be point to a contiguously allocated memory region of at
1401
+ /// least length `total`. The regions must not overlap.
1402
+ pub ( super ) unsafe fn copy_to_volatile_slice < B : BitmapSlice > (
1403
+ slice : & VolatileSlice < ' _ , B > ,
1404
+ src : * const u8 ,
1405
+ total : usize ,
1406
+ ) -> usize {
1407
+ // SAFETY: guaranteed by function invariants.
1408
+ let count = copy_slice ( slice. as_ptr ( ) , src, total) ;
1409
+ slice. bitmap . mark_dirty ( 0 , count) ;
1410
+ count
1411
+ }
1393
1412
}
1394
1413
1395
1414
#[ cfg( test) ]
0 commit comments