vm_memory/
volatile_memory.rs

1// Portions Copyright 2019 Red Hat, Inc.
2//
3// Copyright 2017 The Chromium OS Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style license that can be
5// found in the THIRT-PARTY file.
6//
7// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
8
9//! Types for volatile access to memory.
10//!
11//! Two of the core rules for safe rust is no data races and no aliased mutable references.
12//! `VolatileRef` and `VolatileSlice`, along with types that produce those which implement
13//! `VolatileMemory`, allow us to sidestep that rule by wrapping pointers that absolutely have to be
14//! accessed volatile. Some systems really do need to operate on shared memory and can't have the
15//! compiler reordering or eliding access because it has no visibility into what other systems are
16//! doing with that hunk of memory.
17//!
18//! For the purposes of maintaining safety, volatile memory has some rules of its own:
19//! 1. No references or slices to volatile memory (`&` or `&mut`).
20//! 2. Access should always been done with a volatile read or write.
21//!    The First rule is because having references of any kind to memory considered volatile would
22//!    violate pointer aliasing. The second is because unvolatile accesses are inherently undefined if
23//!    done concurrently without synchronization. With volatile access we know that the compiler has
24//!    not reordered or elided the access.
25
26use std::cmp::min;
27use std::io::{self, Read, Write};
28use std::marker::PhantomData;
29use std::mem::{align_of, size_of};
30use std::ptr::copy;
31use std::ptr::{read_volatile, write_volatile};
32use std::result;
33use std::sync::atomic::Ordering;
34
35use crate::atomic_integer::AtomicInteger;
36use crate::bitmap::{Bitmap, BitmapSlice, BS};
37use crate::{AtomicAccess, ByteValued, Bytes};
38
39#[cfg(all(feature = "backend-mmap", feature = "xen", unix))]
40use crate::mmap_xen::{MmapXen as MmapInfo, MmapXenSlice};
41
42#[cfg(not(feature = "xen"))]
43type MmapInfo = std::marker::PhantomData<()>;
44
45use crate::io::{ReadVolatile, WriteVolatile};
46use copy_slice_impl::{copy_from_volatile_slice, copy_to_volatile_slice};
47
48/// `VolatileMemory` related errors.
49#[allow(missing_docs)]
50#[derive(Debug, thiserror::Error)]
51pub enum Error {
52    /// `addr` is out of bounds of the volatile memory slice.
53    #[error("address 0x{addr:x} is out of bounds")]
54    OutOfBounds { addr: usize },
55    /// Taking a slice at `base` with `offset` would overflow `usize`.
56    #[error("address 0x{base:x} offset by 0x{offset:x} would overflow")]
57    Overflow { base: usize, offset: usize },
58    /// Taking a slice whose size overflows `usize`.
59    #[error("{nelements:?} elements of size {size:?} would overflow a usize")]
60    TooBig { nelements: usize, size: usize },
61    /// Trying to obtain a misaligned reference.
62    #[error("address 0x{addr:x} is not aligned to {alignment:?}")]
63    Misaligned { addr: usize, alignment: usize },
64    /// Writing to memory failed
65    #[error("{0}")]
66    IOError(io::Error),
67    /// Incomplete read or write
68    #[error("only used {completed} bytes in {expected} long buffer")]
69    PartialBuffer { expected: usize, completed: usize },
70}
71
72/// Result of volatile memory operations.
73pub type Result<T> = result::Result<T, Error>;
74
75/// Convenience function for computing `base + offset`.
76///
77/// # Errors
78///
79/// Returns [`Err(Error::Overflow)`](enum.Error.html#variant.Overflow) in case `base + offset`
80/// exceeds `usize::MAX`.
81///
82/// # Examples
83///
84/// ```
85/// # use vm_memory::volatile_memory::compute_offset;
86/// #
87/// assert_eq!(108, compute_offset(100, 8).unwrap());
88/// assert!(compute_offset(std::usize::MAX, 6).is_err());
89/// ```
90pub fn compute_offset(base: usize, offset: usize) -> Result<usize> {
91    match base.checked_add(offset) {
92        None => Err(Error::Overflow { base, offset }),
93        Some(m) => Ok(m),
94    }
95}
96
97/// Types that support raw volatile access to their data.
98pub trait VolatileMemory {
99    /// Type used for dirty memory tracking.
100    type B: Bitmap;
101
102    /// Gets the size of this slice.
103    fn len(&self) -> usize;
104
105    /// Check whether the region is empty.
106    fn is_empty(&self) -> bool {
107        self.len() == 0
108    }
109
110    /// Returns a [`VolatileSlice`](struct.VolatileSlice.html) of `count` bytes starting at
111    /// `offset`.
112    ///
113    /// Note that the property `get_slice(offset, count).len() == count` MUST NOT be
114    /// relied on for the correctness of unsafe code. This is a safe function inside of a
115    /// safe trait, and implementors are under no obligation to follow its documentation.
116    fn get_slice(&self, offset: usize, count: usize) -> Result<VolatileSlice<BS<Self::B>>>;
117
118    /// Gets a slice of memory for the entire region that supports volatile access.
119    fn as_volatile_slice(&self) -> VolatileSlice<BS<Self::B>> {
120        self.get_slice(0, self.len()).unwrap()
121    }
122
123    /// Gets a `VolatileRef` at `offset`.
124    fn get_ref<T: ByteValued>(&self, offset: usize) -> Result<VolatileRef<T, BS<Self::B>>> {
125        let slice = self.get_slice(offset, size_of::<T>())?;
126
127        assert_eq!(
128            slice.len(),
129            size_of::<T>(),
130            "VolatileMemory::get_slice(offset, count) returned slice of length != count."
131        );
132
133        // SAFETY: This is safe because the invariants of the constructors of VolatileSlice ensure that
134        // slice.addr is valid memory of size slice.len(). The assert above ensures that
135        // the length of the slice is exactly enough to hold one `T`. Lastly, the lifetime of the
136        // returned VolatileRef match that of the VolatileSlice returned by get_slice and thus the
137        // lifetime one `self`.
138        unsafe {
139            Ok(VolatileRef::with_bitmap(
140                slice.addr,
141                slice.bitmap,
142                slice.mmap,
143            ))
144        }
145    }
146
147    /// Returns a [`VolatileArrayRef`](struct.VolatileArrayRef.html) of `n` elements starting at
148    /// `offset`.
149    fn get_array_ref<T: ByteValued>(
150        &self,
151        offset: usize,
152        n: usize,
153    ) -> Result<VolatileArrayRef<T, BS<Self::B>>> {
154        // Use isize to avoid problems with ptr::offset and ptr::add down the line.
155        let nbytes = isize::try_from(n)
156            .ok()
157            .and_then(|n| n.checked_mul(size_of::<T>() as isize))
158            .ok_or(Error::TooBig {
159                nelements: n,
160                size: size_of::<T>(),
161            })?;
162        let slice = self.get_slice(offset, nbytes as usize)?;
163
164        assert_eq!(
165            slice.len(),
166            nbytes as usize,
167            "VolatileMemory::get_slice(offset, count) returned slice of length != count."
168        );
169
170        // SAFETY: This is safe because the invariants of the constructors of VolatileSlice ensure that
171        // slice.addr is valid memory of size slice.len(). The assert above ensures that
172        // the length of the slice is exactly enough to hold `n` instances of `T`. Lastly, the lifetime of the
173        // returned VolatileArrayRef match that of the VolatileSlice returned by get_slice and thus the
174        // lifetime one `self`.
175        unsafe {
176            Ok(VolatileArrayRef::with_bitmap(
177                slice.addr,
178                n,
179                slice.bitmap,
180                slice.mmap,
181            ))
182        }
183    }
184
185    /// Returns a reference to an instance of `T` at `offset`.
186    ///
187    /// # Safety
188    /// To use this safely, the caller must guarantee that there are no other
189    /// users of the given chunk of memory for the lifetime of the result.
190    ///
191    /// # Errors
192    ///
193    /// If the resulting pointer is not aligned, this method will return an
194    /// [`Error`](enum.Error.html).
195    unsafe fn aligned_as_ref<T: ByteValued>(&self, offset: usize) -> Result<&T> {
196        let slice = self.get_slice(offset, size_of::<T>())?;
197        slice.check_alignment(align_of::<T>())?;
198
199        assert_eq!(
200            slice.len(),
201            size_of::<T>(),
202            "VolatileMemory::get_slice(offset, count) returned slice of length != count."
203        );
204
205        // SAFETY: This is safe because the invariants of the constructors of VolatileSlice ensure that
206        // slice.addr is valid memory of size slice.len(). The assert above ensures that
207        // the length of the slice is exactly enough to hold one `T`.
208        // Dereferencing the pointer is safe because we check the alignment above, and the invariants
209        // of this function ensure that no aliasing pointers exist. Lastly, the lifetime of the
210        // returned VolatileArrayRef match that of the VolatileSlice returned by get_slice and thus the
211        // lifetime one `self`.
212        unsafe { Ok(&*(slice.addr as *const T)) }
213    }
214
215    /// Returns a mutable reference to an instance of `T` at `offset`. Mutable accesses performed
216    /// using the resulting reference are not automatically accounted for by the dirty bitmap
217    /// tracking functionality.
218    ///
219    /// # Safety
220    ///
221    /// To use this safely, the caller must guarantee that there are no other
222    /// users of the given chunk of memory for the lifetime of the result.
223    ///
224    /// # Errors
225    ///
226    /// If the resulting pointer is not aligned, this method will return an
227    /// [`Error`](enum.Error.html).
228    unsafe fn aligned_as_mut<T: ByteValued>(&self, offset: usize) -> Result<&mut T> {
229        let slice = self.get_slice(offset, size_of::<T>())?;
230        slice.check_alignment(align_of::<T>())?;
231
232        assert_eq!(
233            slice.len(),
234            size_of::<T>(),
235            "VolatileMemory::get_slice(offset, count) returned slice of length != count."
236        );
237
238        // SAFETY: This is safe because the invariants of the constructors of VolatileSlice ensure that
239        // slice.addr is valid memory of size slice.len(). The assert above ensures that
240        // the length of the slice is exactly enough to hold one `T`.
241        // Dereferencing the pointer is safe because we check the alignment above, and the invariants
242        // of this function ensure that no aliasing pointers exist. Lastly, the lifetime of the
243        // returned VolatileArrayRef match that of the VolatileSlice returned by get_slice and thus the
244        // lifetime one `self`.
245
246        unsafe { Ok(&mut *(slice.addr as *mut T)) }
247    }
248
249    /// Returns a reference to an instance of `T` at `offset`. Mutable accesses performed
250    /// using the resulting reference are not automatically accounted for by the dirty bitmap
251    /// tracking functionality.
252    ///
253    /// # Errors
254    ///
255    /// If the resulting pointer is not aligned, this method will return an
256    /// [`Error`](enum.Error.html).
257    fn get_atomic_ref<T: AtomicInteger>(&self, offset: usize) -> Result<&T> {
258        let slice = self.get_slice(offset, size_of::<T>())?;
259        slice.check_alignment(align_of::<T>())?;
260
261        assert_eq!(
262            slice.len(),
263            size_of::<T>(),
264            "VolatileMemory::get_slice(offset, count) returned slice of length != count."
265        );
266
267        // SAFETY: This is safe because the invariants of the constructors of VolatileSlice ensure that
268        // slice.addr is valid memory of size slice.len(). The assert above ensures that
269        // the length of the slice is exactly enough to hold one `T`.
270        // Dereferencing the pointer is safe because we check the alignment above. Lastly, the lifetime of the
271        // returned VolatileArrayRef match that of the VolatileSlice returned by get_slice and thus the
272        // lifetime one `self`.
273        unsafe { Ok(&*(slice.addr as *const T)) }
274    }
275
276    /// Returns the sum of `base` and `offset` if the resulting address is valid.
277    fn compute_end_offset(&self, base: usize, offset: usize) -> Result<usize> {
278        let mem_end = compute_offset(base, offset)?;
279        if mem_end > self.len() {
280            return Err(Error::OutOfBounds { addr: mem_end });
281        }
282        Ok(mem_end)
283    }
284}
285
286impl<'a> From<&'a mut [u8]> for VolatileSlice<'a, ()> {
287    fn from(value: &'a mut [u8]) -> Self {
288        // SAFETY: Since we construct the VolatileSlice from a rust slice, we know that
289        // the memory at addr `value as *mut u8` is valid for reads and writes (because mutable
290        // reference) of len `value.len()`. Since the `VolatileSlice` inherits the lifetime `'a`,
291        // it is not possible to access/mutate `value` while the VolatileSlice is alive.
292        //
293        // Note that it is possible for multiple aliasing sub slices of this `VolatileSlice`s to
294        // be created through `VolatileSlice::subslice`. This is OK, as pointers are allowed to
295        // alias, and it is impossible to get rust-style references from a `VolatileSlice`.
296        unsafe { VolatileSlice::new(value.as_mut_ptr(), value.len()) }
297    }
298}
299
300#[repr(C, packed)]
301struct Packed<T>(T);
302
303/// A guard to perform mapping and protect unmapping of the memory.
304#[derive(Debug)]
305pub struct PtrGuard {
306    addr: *mut u8,
307    len: usize,
308
309    // This isn't used anymore, but it protects the slice from getting unmapped while in use.
310    // Once this goes out of scope, the memory is unmapped automatically.
311    #[cfg(all(feature = "xen", unix))]
312    _slice: MmapXenSlice,
313}
314
315#[allow(clippy::len_without_is_empty)]
316impl PtrGuard {
317    #[allow(unused_variables)]
318    fn new(mmap: Option<&MmapInfo>, addr: *mut u8, prot: i32, len: usize) -> Self {
319        #[cfg(all(feature = "xen", unix))]
320        let (addr, _slice) = {
321            let slice = MmapInfo::mmap(mmap, addr, prot, len);
322            (slice.addr(), slice)
323        };
324
325        Self {
326            addr,
327            len,
328
329            #[cfg(all(feature = "xen", unix))]
330            _slice,
331        }
332    }
333
334    fn read(mmap: Option<&MmapInfo>, addr: *mut u8, len: usize) -> Self {
335        Self::new(mmap, addr, libc::PROT_READ, len)
336    }
337
338    /// Returns a non-mutable pointer to the beginning of the slice.
339    pub fn as_ptr(&self) -> *const u8 {
340        self.addr
341    }
342
343    /// Gets the length of the mapped region.
344    pub fn len(&self) -> usize {
345        self.len
346    }
347}
348
349/// A mutable guard to perform mapping and protect unmapping of the memory.
350#[derive(Debug)]
351pub struct PtrGuardMut(PtrGuard);
352
353#[allow(clippy::len_without_is_empty)]
354impl PtrGuardMut {
355    fn write(mmap: Option<&MmapInfo>, addr: *mut u8, len: usize) -> Self {
356        Self(PtrGuard::new(mmap, addr, libc::PROT_WRITE, len))
357    }
358
359    /// Returns a mutable pointer to the beginning of the slice. Mutable accesses performed
360    /// using the resulting pointer are not automatically accounted for by the dirty bitmap
361    /// tracking functionality.
362    pub fn as_ptr(&self) -> *mut u8 {
363        self.0.addr
364    }
365
366    /// Gets the length of the mapped region.
367    pub fn len(&self) -> usize {
368        self.0.len
369    }
370}
371
372/// A slice of raw memory that supports volatile access.
373#[derive(Clone, Copy, Debug)]
374pub struct VolatileSlice<'a, B = ()> {
375    addr: *mut u8,
376    size: usize,
377    bitmap: B,
378    mmap: Option<&'a MmapInfo>,
379}
380
381impl<'a> VolatileSlice<'a, ()> {
382    /// Creates a slice of raw memory that must support volatile access.
383    ///
384    /// # Safety
385    ///
386    /// To use this safely, the caller must guarantee that the memory at `addr` is `size` bytes long
387    /// and is available for the duration of the lifetime of the new `VolatileSlice`. The caller
388    /// must also guarantee that all other users of the given chunk of memory are using volatile
389    /// accesses.
390    pub unsafe fn new(addr: *mut u8, size: usize) -> VolatileSlice<'a> {
391        Self::with_bitmap(addr, size, (), None)
392    }
393}
394
395impl<'a, B: BitmapSlice> VolatileSlice<'a, B> {
396    /// Creates a slice of raw memory that must support volatile access, and uses the provided
397    /// `bitmap` object for dirty page tracking.
398    ///
399    /// # Safety
400    ///
401    /// To use this safely, the caller must guarantee that the memory at `addr` is `size` bytes long
402    /// and is available for the duration of the lifetime of the new `VolatileSlice`. The caller
403    /// must also guarantee that all other users of the given chunk of memory are using volatile
404    /// accesses.
405    pub unsafe fn with_bitmap(
406        addr: *mut u8,
407        size: usize,
408        bitmap: B,
409        mmap: Option<&'a MmapInfo>,
410    ) -> VolatileSlice<'a, B> {
411        VolatileSlice {
412            addr,
413            size,
414            bitmap,
415            mmap,
416        }
417    }
418
419    /// Returns a pointer to the beginning of the slice. Mutable accesses performed
420    /// using the resulting pointer are not automatically accounted for by the dirty bitmap
421    /// tracking functionality.
422    #[deprecated(
423        since = "0.12.1",
424        note = "Use `.ptr_guard()` or `.ptr_guard_mut()` instead"
425    )]
426    #[cfg(not(all(feature = "xen", unix)))]
427    pub fn as_ptr(&self) -> *mut u8 {
428        self.addr
429    }
430
431    /// Returns a guard for the pointer to the underlying memory.
432    pub fn ptr_guard(&self) -> PtrGuard {
433        PtrGuard::read(self.mmap, self.addr, self.len())
434    }
435
436    /// Returns a mutable guard for the pointer to the underlying memory.
437    pub fn ptr_guard_mut(&self) -> PtrGuardMut {
438        PtrGuardMut::write(self.mmap, self.addr, self.len())
439    }
440
441    /// Gets the size of this slice.
442    pub fn len(&self) -> usize {
443        self.size
444    }
445
446    /// Checks if the slice is empty.
447    pub fn is_empty(&self) -> bool {
448        self.size == 0
449    }
450
451    /// Borrows the inner `BitmapSlice`.
452    pub fn bitmap(&self) -> &B {
453        &self.bitmap
454    }
455
456    /// Divides one slice into two at an index.
457    ///
458    /// # Example
459    ///
460    /// ```
461    /// # use vm_memory::{VolatileMemory, VolatileSlice};
462    /// #
463    /// # // Create a buffer
464    /// # let mut mem = [0u8; 32];
465    /// #
466    /// # // Get a `VolatileSlice` from the buffer
467    /// let vslice = VolatileSlice::from(&mut mem[..]);
468    ///
469    /// let (start, end) = vslice.split_at(8).expect("Could not split VolatileSlice");
470    /// assert_eq!(8, start.len());
471    /// assert_eq!(24, end.len());
472    /// ```
473    pub fn split_at(&self, mid: usize) -> Result<(Self, Self)> {
474        let end = self.offset(mid)?;
475        let start =
476            // SAFETY: safe because self.offset() already checked the bounds
477            unsafe { VolatileSlice::with_bitmap(self.addr, mid, self.bitmap.clone(), self.mmap) };
478
479        Ok((start, end))
480    }
481
482    /// Returns a subslice of this [`VolatileSlice`](struct.VolatileSlice.html) starting at
483    /// `offset` with `count` length.
484    ///
485    /// The returned subslice is a copy of this slice with the address increased by `offset` bytes
486    /// and the size set to `count` bytes.
487    pub fn subslice(&self, offset: usize, count: usize) -> Result<Self> {
488        let _ = self.compute_end_offset(offset, count)?;
489
490        // SAFETY: This is safe because the pointer is range-checked by compute_end_offset, and
491        // the lifetime is the same as the original slice.
492        unsafe {
493            Ok(VolatileSlice::with_bitmap(
494                self.addr.add(offset),
495                count,
496                self.bitmap.slice_at(offset),
497                self.mmap,
498            ))
499        }
500    }
501
502    /// Returns a subslice of this [`VolatileSlice`](struct.VolatileSlice.html) starting at
503    /// `offset`.
504    ///
505    /// The returned subslice is a copy of this slice with the address increased by `count` bytes
506    /// and the size reduced by `count` bytes.
507    pub fn offset(&self, count: usize) -> Result<VolatileSlice<'a, B>> {
508        let new_addr = (self.addr as usize)
509            .checked_add(count)
510            .ok_or(Error::Overflow {
511                base: self.addr as usize,
512                offset: count,
513            })?;
514        let new_size = self
515            .size
516            .checked_sub(count)
517            .ok_or(Error::OutOfBounds { addr: new_addr })?;
518        // SAFETY: Safe because the memory has the same lifetime and points to a subset of the
519        // memory of the original slice.
520        unsafe {
521            Ok(VolatileSlice::with_bitmap(
522                self.addr.add(count),
523                new_size,
524                self.bitmap.slice_at(count),
525                self.mmap,
526            ))
527        }
528    }
529
530    /// Copies as many elements of type `T` as possible from this slice to `buf`.
531    ///
532    /// Copies `self.len()` or `buf.len()` times the size of `T` bytes, whichever is smaller,
533    /// to `buf`. The copy happens from smallest to largest address in `T` sized chunks
534    /// using volatile reads.
535    ///
536    /// # Examples
537    ///
538    /// ```
539    /// # use vm_memory::{VolatileMemory, VolatileSlice};
540    /// #
541    /// let mut mem = [0u8; 32];
542    /// let vslice = VolatileSlice::from(&mut mem[..]);
543    /// let mut buf = [5u8; 16];
544    /// let res = vslice.copy_to(&mut buf[..]);
545    ///
546    /// assert_eq!(16, res);
547    /// for &v in &buf[..] {
548    ///     assert_eq!(v, 0);
549    /// }
550    /// ```
551    pub fn copy_to<T>(&self, buf: &mut [T]) -> usize
552    where
553        T: ByteValued,
554    {
555        // A fast path for u8/i8
556        if size_of::<T>() == 1 {
557            let total = buf.len().min(self.len());
558
559            // SAFETY:
560            // - dst is valid for writes of at least `total`, since total <= buf.len()
561            // - src is valid for reads of at least `total` as total <= self.len()
562            // - The regions are non-overlapping as `src` points to guest memory and `buf` is
563            //   a slice and thus has to live outside of guest memory (there can be more slices to
564            //   guest memory without violating rust's aliasing rules)
565            // - size is always a multiple of alignment, so treating *mut T as *mut u8 is fine
566            unsafe { copy_from_volatile_slice(buf.as_mut_ptr() as *mut u8, self, total) }
567        } else {
568            let count = self.size / size_of::<T>();
569            let source = self.get_array_ref::<T>(0, count).unwrap();
570            source.copy_to(buf)
571        }
572    }
573
574    /// Copies as many bytes as possible from this slice to the provided `slice`.
575    ///
576    /// The copies happen in an undefined order.
577    ///
578    /// # Examples
579    ///
580    /// ```
581    /// # use vm_memory::{VolatileMemory, VolatileSlice};
582    /// #
583    /// # // Create a buffer
584    /// # let mut mem = [0u8; 32];
585    /// #
586    /// # // Get a `VolatileSlice` from the buffer
587    /// # let vslice = VolatileSlice::from(&mut mem[..]);
588    /// #
589    /// vslice.copy_to_volatile_slice(
590    ///     vslice
591    ///         .get_slice(16, 16)
592    ///         .expect("Could not get VolatileSlice"),
593    /// );
594    /// ```
595    pub fn copy_to_volatile_slice<S: BitmapSlice>(&self, slice: VolatileSlice<S>) {
596        // SAFETY: Safe because the pointers are range-checked when the slices
597        // are created, and they never escape the VolatileSlices.
598        // FIXME: ... however, is it really okay to mix non-volatile
599        // operations such as copy with read_volatile and write_volatile?
600        unsafe {
601            let count = min(self.size, slice.size);
602            copy(self.addr, slice.addr, count);
603            slice.bitmap.mark_dirty(0, count);
604        }
605    }
606
607    /// Copies as many elements of type `T` as possible from `buf` to this slice.
608    ///
609    /// The copy happens from smallest to largest address in `T` sized chunks using volatile writes.
610    ///
611    /// # Examples
612    ///
613    /// ```
614    /// # use vm_memory::{VolatileMemory, VolatileSlice};
615    /// #
616    /// let mut mem = [0u8; 32];
617    /// let vslice = VolatileSlice::from(&mut mem[..]);
618    ///
619    /// let buf = [5u8; 64];
620    /// vslice.copy_from(&buf[..]);
621    ///
622    /// for i in 0..4 {
623    ///     let val = vslice
624    ///         .get_ref::<u32>(i * 4)
625    ///         .expect("Could not get value")
626    ///         .load();
627    ///     assert_eq!(val, 0x05050505);
628    /// }
629    /// ```
630    pub fn copy_from<T>(&self, buf: &[T])
631    where
632        T: ByteValued,
633    {
634        // A fast path for u8/i8
635        if size_of::<T>() == 1 {
636            let total = buf.len().min(self.len());
637            // SAFETY:
638            // - dst is valid for writes of at least `total`, since total <= self.len()
639            // - src is valid for reads of at least `total` as total <= buf.len()
640            // - The regions are non-overlapping as `dst` points to guest memory and `buf` is
641            //   a slice and thus has to live outside of guest memory (there can be more slices to
642            //   guest memory without violating rust's aliasing rules)
643            // - size is always a multiple of alignment, so treating *mut T as *mut u8 is fine
644            unsafe { copy_to_volatile_slice(self, buf.as_ptr() as *const u8, total) };
645        } else {
646            let count = self.size / size_of::<T>();
647            // It's ok to use unwrap here because `count` was computed based on the current
648            // length of `self`.
649            let dest = self.get_array_ref::<T>(0, count).unwrap();
650
651            // No need to explicitly call `mark_dirty` after this call because
652            // `VolatileArrayRef::copy_from` already takes care of that.
653            dest.copy_from(buf);
654        };
655    }
656
657    /// Checks if the current slice is aligned at `alignment` bytes.
658    fn check_alignment(&self, alignment: usize) -> Result<()> {
659        // Check that the desired alignment is a power of two.
660        debug_assert!((alignment & (alignment - 1)) == 0);
661        if ((self.addr as usize) & (alignment - 1)) != 0 {
662            return Err(Error::Misaligned {
663                addr: self.addr as usize,
664                alignment,
665            });
666        }
667        Ok(())
668    }
669}
670
671impl<B: BitmapSlice> Bytes<usize> for VolatileSlice<'_, B> {
672    type E = Error;
673
674    /// # Examples
675    /// * Write a slice of size 5 at offset 1020 of a 1024-byte `VolatileSlice`.
676    ///
677    /// ```
678    /// # use vm_memory::{Bytes, VolatileMemory, VolatileSlice};
679    /// #
680    /// let mut mem = [0u8; 1024];
681    /// let vslice = VolatileSlice::from(&mut mem[..]);
682    /// let res = vslice.write(&[1, 2, 3, 4, 5], 1020);
683    ///
684    /// assert!(res.is_ok());
685    /// assert_eq!(res.unwrap(), 4);
686    /// ```
687    fn write(&self, mut buf: &[u8], addr: usize) -> Result<usize> {
688        if buf.is_empty() {
689            return Ok(0);
690        }
691
692        if addr >= self.size {
693            return Err(Error::OutOfBounds { addr });
694        }
695
696        // NOTE: the duality of read <-> write here is correct. This is because we translate a call
697        // "volatile_slice.write(buf)" (e.g. "write to volatile_slice from buf") into
698        // "buf.read_volatile(volatile_slice)" (e.g. read from buf into volatile_slice)
699        buf.read_volatile(&mut self.offset(addr)?)
700    }
701
702    /// # Examples
703    /// * Read a slice of size 16 at offset 1010 of a 1024-byte `VolatileSlice`.
704    ///
705    /// ```
706    /// # use vm_memory::{Bytes, VolatileMemory, VolatileSlice};
707    /// #
708    /// let mut mem = [0u8; 1024];
709    /// let vslice = VolatileSlice::from(&mut mem[..]);
710    /// let buf = &mut [0u8; 16];
711    /// let res = vslice.read(buf, 1010);
712    ///
713    /// assert!(res.is_ok());
714    /// assert_eq!(res.unwrap(), 14);
715    /// ```
716    fn read(&self, mut buf: &mut [u8], addr: usize) -> Result<usize> {
717        if buf.is_empty() {
718            return Ok(0);
719        }
720
721        if addr >= self.size {
722            return Err(Error::OutOfBounds { addr });
723        }
724
725        // NOTE: The duality of read <-> write here is correct. This is because we translate a call
726        // volatile_slice.read(buf) (e.g. read from volatile_slice into buf) into
727        // "buf.write_volatile(volatile_slice)" (e.g. write into buf from volatile_slice)
728        // Both express data transfer from volatile_slice to buf.
729        buf.write_volatile(&self.offset(addr)?)
730    }
731
732    /// # Examples
733    /// * Write a slice at offset 256.
734    ///
735    /// ```
736    /// # use vm_memory::{Bytes, VolatileMemory, VolatileSlice};
737    /// #
738    /// # // Create a buffer
739    /// # let mut mem = [0u8; 1024];
740    /// #
741    /// # // Get a `VolatileSlice` from the buffer
742    /// # let vslice = VolatileSlice::from(&mut mem[..]);
743    /// #
744    /// let res = vslice.write_slice(&[1, 2, 3, 4, 5], 256);
745    ///
746    /// assert!(res.is_ok());
747    /// assert_eq!(res.unwrap(), ());
748    /// ```
749    fn write_slice(&self, buf: &[u8], addr: usize) -> Result<()> {
750        // `mark_dirty` called within `self.write`.
751        let len = self.write(buf, addr)?;
752        if len != buf.len() {
753            return Err(Error::PartialBuffer {
754                expected: buf.len(),
755                completed: len,
756            });
757        }
758        Ok(())
759    }
760
761    /// # Examples
762    /// * Read a slice of size 16 at offset 256.
763    ///
764    /// ```
765    /// # use vm_memory::{Bytes, VolatileMemory, VolatileSlice};
766    /// #
767    /// # // Create a buffer
768    /// # let mut mem = [0u8; 1024];
769    /// #
770    /// # // Get a `VolatileSlice` from the buffer
771    /// # let vslice = VolatileSlice::from(&mut mem[..]);
772    /// #
773    /// let buf = &mut [0u8; 16];
774    /// let res = vslice.read_slice(buf, 256);
775    ///
776    /// assert!(res.is_ok());
777    /// ```
778    fn read_slice(&self, buf: &mut [u8], addr: usize) -> Result<()> {
779        let len = self.read(buf, addr)?;
780        if len != buf.len() {
781            return Err(Error::PartialBuffer {
782                expected: buf.len(),
783                completed: len,
784            });
785        }
786        Ok(())
787    }
788
789    /// # Examples
790    ///
791    /// * Read bytes from /dev/urandom
792    ///
793    /// ```
794    /// # use vm_memory::{Bytes, VolatileMemory, VolatileSlice};
795    /// # use std::fs::File;
796    /// # use std::path::Path;
797    /// #
798    /// # if cfg!(unix) {
799    /// # let mut mem = [0u8; 1024];
800    /// # let vslice = VolatileSlice::from(&mut mem[..]);
801    /// let mut file = File::open(Path::new("/dev/urandom")).expect("Could not open /dev/urandom");
802    ///
803    /// vslice
804    ///     .read_from(32, &mut file, 128)
805    ///     .expect("Could not read bytes from file into VolatileSlice");
806    ///
807    /// let rand_val: u32 = vslice
808    ///     .read_obj(40)
809    ///     .expect("Could not read value from VolatileSlice");
810    /// # }
811    /// ```
812    fn read_from<F>(&self, addr: usize, src: &mut F, count: usize) -> Result<usize>
813    where
814        F: Read,
815    {
816        let _ = self.compute_end_offset(addr, count)?;
817
818        let mut dst = vec![0; count];
819
820        let bytes_read = loop {
821            match src.read(&mut dst) {
822                Ok(n) => break n,
823                Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
824                Err(e) => return Err(Error::IOError(e)),
825            }
826        };
827
828        // There is no guarantee that the read implementation is well-behaved, see the docs for
829        // Read::read.
830        assert!(bytes_read <= count);
831
832        let slice = self.subslice(addr, bytes_read)?;
833
834        // SAFETY: We have checked via compute_end_offset that accessing the specified
835        // region of guest memory is valid. We asserted that the value returned by `read` is between
836        // 0 and count (the length of the buffer passed to it), and that the
837        // regions don't overlap because we allocated the Vec outside of guest memory.
838        Ok(unsafe { copy_to_volatile_slice(&slice, dst.as_ptr(), bytes_read) })
839    }
840
841    /// # Examples
842    ///
843    /// * Read bytes from /dev/urandom
844    ///
845    /// ```
846    /// # use vm_memory::{Bytes, VolatileMemory, VolatileSlice};
847    /// # use std::fs::File;
848    /// # use std::path::Path;
849    /// #
850    /// # if cfg!(unix) {
851    /// # let mut mem = [0u8; 1024];
852    /// # let vslice = VolatileSlice::from(&mut mem[..]);
853    /// let mut file = File::open(Path::new("/dev/urandom")).expect("Could not open /dev/urandom");
854    ///
855    /// vslice
856    ///     .read_exact_from(32, &mut file, 128)
857    ///     .expect("Could not read bytes from file into VolatileSlice");
858    ///
859    /// let rand_val: u32 = vslice
860    ///     .read_obj(40)
861    ///     .expect("Could not read value from VolatileSlice");
862    /// # }
863    /// ```
864    fn read_exact_from<F>(&self, addr: usize, src: &mut F, count: usize) -> Result<()>
865    where
866        F: Read,
867    {
868        let _ = self.compute_end_offset(addr, count)?;
869
870        let mut dst = vec![0; count];
871
872        // Read into buffer that can be copied into guest memory
873        src.read_exact(&mut dst).map_err(Error::IOError)?;
874
875        let slice = self.subslice(addr, count)?;
876
877        // SAFETY: We have checked via compute_end_offset that accessing the specified
878        // region of guest memory is valid. We know that `dst` has len `count`, and that the
879        // regions don't overlap because we allocated the Vec outside of guest memory
880        unsafe { copy_to_volatile_slice(&slice, dst.as_ptr(), count) };
881        Ok(())
882    }
883
884    /// # Examples
885    ///
886    /// * Write 128 bytes to /dev/null
887    ///
888    /// ```
889    /// # use vm_memory::{Bytes, VolatileMemory, VolatileSlice};
890    /// # use std::fs::OpenOptions;
891    /// # use std::path::Path;
892    /// #
893    /// # if cfg!(unix) {
894    /// # let mut mem = [0u8; 1024];
895    /// # let vslice = VolatileSlice::from(&mut mem[..]);
896    /// let mut file = OpenOptions::new()
897    ///     .write(true)
898    ///     .open("/dev/null")
899    ///     .expect("Could not open /dev/null");
900    ///
901    /// vslice
902    ///     .write_to(32, &mut file, 128)
903    ///     .expect("Could not write value from VolatileSlice to /dev/null");
904    /// # }
905    /// ```
906    fn write_to<F>(&self, addr: usize, dst: &mut F, count: usize) -> Result<usize>
907    where
908        F: Write,
909    {
910        let _ = self.compute_end_offset(addr, count)?;
911        let mut src = Vec::with_capacity(count);
912
913        let slice = self.subslice(addr, count)?;
914
915        // SAFETY: We checked the addr and count so accessing the slice is safe.
916        // It is safe to read from volatile memory. The Vec has capacity for exactly `count`
917        // many bytes, and the memory regions pointed to definitely do not overlap, as we
918        // allocated src outside of guest memory.
919        // The call to set_len is safe because the bytes between 0 and count have been initialized
920        // via copying from guest memory, and the Vec's capacity is `count`
921        unsafe {
922            copy_from_volatile_slice(src.as_mut_ptr(), &slice, count);
923            src.set_len(count);
924        }
925
926        loop {
927            match dst.write(&src) {
928                Ok(n) => break Ok(n),
929                Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
930                Err(e) => break Err(Error::IOError(e)),
931            }
932        }
933    }
934
935    /// # Examples
936    ///
937    /// * Write 128 bytes to /dev/null
938    ///
939    /// ```
940    /// # use vm_memory::{Bytes, VolatileMemory, VolatileSlice};
941    /// # use std::fs::OpenOptions;
942    /// # use std::path::Path;
943    /// #
944    /// # if cfg!(unix) {
945    /// # let mut mem = [0u8; 1024];
946    /// # let vslice = VolatileSlice::from(&mut mem[..]);
947    /// let mut file = OpenOptions::new()
948    ///     .write(true)
949    ///     .open("/dev/null")
950    ///     .expect("Could not open /dev/null");
951    ///
952    /// vslice
953    ///     .write_all_to(32, &mut file, 128)
954    ///     .expect("Could not write value from VolatileSlice to /dev/null");
955    /// # }
956    /// ```
957    fn write_all_to<F>(&self, addr: usize, dst: &mut F, count: usize) -> Result<()>
958    where
959        F: Write,
960    {
961        let _ = self.compute_end_offset(addr, count)?;
962        let mut src = Vec::with_capacity(count);
963
964        let slice = self.subslice(addr, count)?;
965
966        // SAFETY: We checked the addr and count so accessing the slice is safe.
967        // It is safe to read from volatile memory. The Vec has capacity for exactly `count`
968        // many bytes, and the memory regions pointed to definitely do not overlap, as we
969        // allocated src outside of guest memory.
970        // The call to set_len is safe because the bytes between 0 and count have been initialized
971        // via copying from guest memory, and the Vec's capacity is `count`
972        unsafe {
973            copy_from_volatile_slice(src.as_mut_ptr(), &slice, count);
974            src.set_len(count);
975        }
976
977        dst.write_all(&src).map_err(Error::IOError)?;
978
979        Ok(())
980    }
981
982    fn store<T: AtomicAccess>(&self, val: T, addr: usize, order: Ordering) -> Result<()> {
983        self.get_atomic_ref::<T::A>(addr).map(|r| {
984            r.store(val.into(), order);
985            self.bitmap.mark_dirty(addr, size_of::<T>())
986        })
987    }
988
989    fn load<T: AtomicAccess>(&self, addr: usize, order: Ordering) -> Result<T> {
990        self.get_atomic_ref::<T::A>(addr)
991            .map(|r| r.load(order).into())
992    }
993}
994
995impl<B: BitmapSlice> VolatileMemory for VolatileSlice<'_, B> {
996    type B = B;
997
998    fn len(&self) -> usize {
999        self.size
1000    }
1001
1002    fn get_slice(&self, offset: usize, count: usize) -> Result<VolatileSlice<B>> {
1003        let _ = self.compute_end_offset(offset, count)?;
1004        Ok(
1005            // SAFETY: This is safe because the pointer is range-checked by compute_end_offset, and
1006            // the lifetime is the same as self.
1007            unsafe {
1008                VolatileSlice::with_bitmap(
1009                    self.addr.add(offset),
1010                    count,
1011                    self.bitmap.slice_at(offset),
1012                    self.mmap,
1013                )
1014            },
1015        )
1016    }
1017}
1018
1019/// A memory location that supports volatile access to an instance of `T`.
1020///
1021/// # Examples
1022///
1023/// ```
1024/// # use vm_memory::VolatileRef;
1025/// #
1026/// let mut v = 5u32;
1027/// let v_ref = unsafe { VolatileRef::new(&mut v as *mut u32 as *mut u8) };
1028///
1029/// assert_eq!(v, 5);
1030/// assert_eq!(v_ref.load(), 5);
1031/// v_ref.store(500);
1032/// assert_eq!(v, 500);
1033/// ```
1034#[derive(Clone, Copy, Debug)]
1035pub struct VolatileRef<'a, T, B = ()> {
1036    addr: *mut Packed<T>,
1037    bitmap: B,
1038    mmap: Option<&'a MmapInfo>,
1039}
1040
1041impl<T> VolatileRef<'_, T, ()>
1042where
1043    T: ByteValued,
1044{
1045    /// Creates a [`VolatileRef`](struct.VolatileRef.html) to an instance of `T`.
1046    ///
1047    /// # Safety
1048    ///
1049    /// To use this safely, the caller must guarantee that the memory at `addr` is big enough for a
1050    /// `T` and is available for the duration of the lifetime of the new `VolatileRef`. The caller
1051    /// must also guarantee that all other users of the given chunk of memory are using volatile
1052    /// accesses.
1053    pub unsafe fn new(addr: *mut u8) -> Self {
1054        Self::with_bitmap(addr, (), None)
1055    }
1056}
1057
1058#[allow(clippy::len_without_is_empty)]
1059impl<'a, T, B> VolatileRef<'a, T, B>
1060where
1061    T: ByteValued,
1062    B: BitmapSlice,
1063{
1064    /// Creates a [`VolatileRef`](struct.VolatileRef.html) to an instance of `T`, using the
1065    /// provided `bitmap` object for dirty page tracking.
1066    ///
1067    /// # Safety
1068    ///
1069    /// To use this safely, the caller must guarantee that the memory at `addr` is big enough for a
1070    /// `T` and is available for the duration of the lifetime of the new `VolatileRef`. The caller
1071    /// must also guarantee that all other users of the given chunk of memory are using volatile
1072    /// accesses.
1073    pub unsafe fn with_bitmap(addr: *mut u8, bitmap: B, mmap: Option<&'a MmapInfo>) -> Self {
1074        VolatileRef {
1075            addr: addr as *mut Packed<T>,
1076            bitmap,
1077            mmap,
1078        }
1079    }
1080
1081    /// Returns a pointer to the underlying memory. Mutable accesses performed
1082    /// using the resulting pointer are not automatically accounted for by the dirty bitmap
1083    /// tracking functionality.
1084    #[deprecated(
1085        since = "0.12.1",
1086        note = "Use `.ptr_guard()` or `.ptr_guard_mut()` instead"
1087    )]
1088    #[cfg(not(all(feature = "xen", unix)))]
1089    pub fn as_ptr(&self) -> *mut u8 {
1090        self.addr as *mut u8
1091    }
1092
1093    /// Returns a guard for the pointer to the underlying memory.
1094    pub fn ptr_guard(&self) -> PtrGuard {
1095        PtrGuard::read(self.mmap, self.addr as *mut u8, self.len())
1096    }
1097
1098    /// Returns a mutable guard for the pointer to the underlying memory.
1099    pub fn ptr_guard_mut(&self) -> PtrGuardMut {
1100        PtrGuardMut::write(self.mmap, self.addr as *mut u8, self.len())
1101    }
1102
1103    /// Gets the size of the referenced type `T`.
1104    ///
1105    /// # Examples
1106    ///
1107    /// ```
1108    /// # use std::mem::size_of;
1109    /// # use vm_memory::VolatileRef;
1110    /// #
1111    /// let v_ref = unsafe { VolatileRef::<u32>::new(0 as *mut _) };
1112    /// assert_eq!(v_ref.len(), size_of::<u32>() as usize);
1113    /// ```
1114    pub fn len(&self) -> usize {
1115        size_of::<T>()
1116    }
1117
1118    /// Borrows the inner `BitmapSlice`.
1119    pub fn bitmap(&self) -> &B {
1120        &self.bitmap
1121    }
1122
1123    /// Does a volatile write of the value `v` to the address of this ref.
1124    #[inline(always)]
1125    pub fn store(&self, v: T) {
1126        let guard = self.ptr_guard_mut();
1127
1128        // SAFETY: Safe because we checked the address and size when creating this VolatileRef.
1129        unsafe { write_volatile(guard.as_ptr() as *mut Packed<T>, Packed::<T>(v)) };
1130        self.bitmap.mark_dirty(0, self.len())
1131    }
1132
1133    /// Does a volatile read of the value at the address of this ref.
1134    #[inline(always)]
1135    pub fn load(&self) -> T {
1136        let guard = self.ptr_guard();
1137
1138        // SAFETY: Safe because we checked the address and size when creating this VolatileRef.
1139        // For the purposes of demonstrating why read_volatile is necessary, try replacing the code
1140        // in this function with the commented code below and running `cargo test --release`.
1141        // unsafe { *(self.addr as *const T) }
1142        unsafe { read_volatile(guard.as_ptr() as *const Packed<T>).0 }
1143    }
1144
1145    /// Converts this to a [`VolatileSlice`](struct.VolatileSlice.html) with the same size and
1146    /// address.
1147    pub fn to_slice(&self) -> VolatileSlice<'a, B> {
1148        // SAFETY: Safe because we checked the address and size when creating this VolatileRef.
1149        unsafe {
1150            VolatileSlice::with_bitmap(
1151                self.addr as *mut u8,
1152                size_of::<T>(),
1153                self.bitmap.clone(),
1154                self.mmap,
1155            )
1156        }
1157    }
1158}
1159
1160/// A memory location that supports volatile access to an array of elements of type `T`.
1161///
1162/// # Examples
1163///
1164/// ```
1165/// # use vm_memory::VolatileArrayRef;
1166/// #
1167/// let mut v = [5u32; 1];
1168/// let v_ref = unsafe { VolatileArrayRef::new(&mut v[0] as *mut u32 as *mut u8, v.len()) };
1169///
1170/// assert_eq!(v[0], 5);
1171/// assert_eq!(v_ref.load(0), 5);
1172/// v_ref.store(0, 500);
1173/// assert_eq!(v[0], 500);
1174/// ```
1175#[derive(Clone, Copy, Debug)]
1176pub struct VolatileArrayRef<'a, T, B = ()> {
1177    addr: *mut u8,
1178    nelem: usize,
1179    bitmap: B,
1180    phantom: PhantomData<&'a T>,
1181    mmap: Option<&'a MmapInfo>,
1182}
1183
1184impl<T> VolatileArrayRef<'_, T>
1185where
1186    T: ByteValued,
1187{
1188    /// Creates a [`VolatileArrayRef`](struct.VolatileArrayRef.html) to an array of elements of
1189    /// type `T`.
1190    ///
1191    /// # Safety
1192    ///
1193    /// To use this safely, the caller must guarantee that the memory at `addr` is big enough for
1194    /// `nelem` values of type `T` and is available for the duration of the lifetime of the new
1195    /// `VolatileRef`. The caller must also guarantee that all other users of the given chunk of
1196    /// memory are using volatile accesses.
1197    pub unsafe fn new(addr: *mut u8, nelem: usize) -> Self {
1198        Self::with_bitmap(addr, nelem, (), None)
1199    }
1200}
1201
1202impl<'a, T, B> VolatileArrayRef<'a, T, B>
1203where
1204    T: ByteValued,
1205    B: BitmapSlice,
1206{
1207    /// Creates a [`VolatileArrayRef`](struct.VolatileArrayRef.html) to an array of elements of
1208    /// type `T`, using the provided `bitmap` object for dirty page tracking.
1209    ///
1210    /// # Safety
1211    ///
1212    /// To use this safely, the caller must guarantee that the memory at `addr` is big enough for
1213    /// `nelem` values of type `T` and is available for the duration of the lifetime of the new
1214    /// `VolatileRef`. The caller must also guarantee that all other users of the given chunk of
1215    /// memory are using volatile accesses.
1216    pub unsafe fn with_bitmap(
1217        addr: *mut u8,
1218        nelem: usize,
1219        bitmap: B,
1220        mmap: Option<&'a MmapInfo>,
1221    ) -> Self {
1222        VolatileArrayRef {
1223            addr,
1224            nelem,
1225            bitmap,
1226            phantom: PhantomData,
1227            mmap,
1228        }
1229    }
1230
1231    /// Returns `true` if this array is empty.
1232    ///
1233    /// # Examples
1234    ///
1235    /// ```
1236    /// # use vm_memory::VolatileArrayRef;
1237    /// #
1238    /// let v_array = unsafe { VolatileArrayRef::<u32>::new(0 as *mut _, 0) };
1239    /// assert!(v_array.is_empty());
1240    /// ```
1241    pub fn is_empty(&self) -> bool {
1242        self.nelem == 0
1243    }
1244
1245    /// Returns the number of elements in the array.
1246    ///
1247    /// # Examples
1248    ///
1249    /// ```
1250    /// # use vm_memory::VolatileArrayRef;
1251    /// #
1252    /// # let v_array = unsafe { VolatileArrayRef::<u32>::new(0 as *mut _, 1) };
1253    /// assert_eq!(v_array.len(), 1);
1254    /// ```
1255    pub fn len(&self) -> usize {
1256        self.nelem
1257    }
1258
1259    /// Returns the size of `T`.
1260    ///
1261    /// # Examples
1262    ///
1263    /// ```
1264    /// # use std::mem::size_of;
1265    /// # use vm_memory::VolatileArrayRef;
1266    /// #
1267    /// let v_ref = unsafe { VolatileArrayRef::<u32>::new(0 as *mut _, 0) };
1268    /// assert_eq!(v_ref.element_size(), size_of::<u32>() as usize);
1269    /// ```
1270    pub fn element_size(&self) -> usize {
1271        size_of::<T>()
1272    }
1273
1274    /// Returns a pointer to the underlying memory. Mutable accesses performed
1275    /// using the resulting pointer are not automatically accounted for by the dirty bitmap
1276    /// tracking functionality.
1277    #[deprecated(
1278        since = "0.12.1",
1279        note = "Use `.ptr_guard()` or `.ptr_guard_mut()` instead"
1280    )]
1281    #[cfg(not(all(feature = "xen", unix)))]
1282    pub fn as_ptr(&self) -> *mut u8 {
1283        self.addr
1284    }
1285
1286    /// Returns a guard for the pointer to the underlying memory.
1287    pub fn ptr_guard(&self) -> PtrGuard {
1288        PtrGuard::read(self.mmap, self.addr, self.len())
1289    }
1290
1291    /// Returns a mutable guard for the pointer to the underlying memory.
1292    pub fn ptr_guard_mut(&self) -> PtrGuardMut {
1293        PtrGuardMut::write(self.mmap, self.addr, self.len())
1294    }
1295
1296    /// Borrows the inner `BitmapSlice`.
1297    pub fn bitmap(&self) -> &B {
1298        &self.bitmap
1299    }
1300
1301    /// Converts this to a `VolatileSlice` with the same size and address.
1302    pub fn to_slice(&self) -> VolatileSlice<'a, B> {
1303        // SAFETY: Safe as long as the caller validated addr when creating this object.
1304        unsafe {
1305            VolatileSlice::with_bitmap(
1306                self.addr,
1307                self.nelem * self.element_size(),
1308                self.bitmap.clone(),
1309                self.mmap,
1310            )
1311        }
1312    }
1313
1314    /// Does a volatile read of the element at `index`.
1315    ///
1316    /// # Panics
1317    ///
1318    /// Panics if `index` is less than the number of elements of the array to which `&self` points.
1319    pub fn ref_at(&self, index: usize) -> VolatileRef<'a, T, B> {
1320        assert!(index < self.nelem);
1321        // SAFETY: Safe because the memory has the same lifetime and points to a subset of the
1322        // memory of the VolatileArrayRef.
1323        unsafe {
1324            // byteofs must fit in an isize as it was checked in get_array_ref.
1325            let byteofs = (self.element_size() * index) as isize;
1326            let ptr = self.addr.offset(byteofs);
1327            VolatileRef::with_bitmap(ptr, self.bitmap.slice_at(byteofs as usize), self.mmap)
1328        }
1329    }
1330
1331    /// Does a volatile read of the element at `index`.
1332    pub fn load(&self, index: usize) -> T {
1333        self.ref_at(index).load()
1334    }
1335
1336    /// Does a volatile write of the element at `index`.
1337    pub fn store(&self, index: usize, value: T) {
1338        // The `VolatileRef::store` call below implements the required dirty bitmap tracking logic,
1339        // so no need to do that in this method as well.
1340        self.ref_at(index).store(value)
1341    }
1342
1343    /// Copies as many elements of type `T` as possible from this array to `buf`.
1344    ///
1345    /// Copies `self.len()` or `buf.len()` times the size of `T` bytes, whichever is smaller,
1346    /// to `buf`. The copy happens from smallest to largest address in `T` sized chunks
1347    /// using volatile reads.
1348    ///
1349    /// # Examples
1350    ///
1351    /// ```
1352    /// # use vm_memory::VolatileArrayRef;
1353    /// #
1354    /// let mut v = [0u8; 32];
1355    /// let v_ref = unsafe { VolatileArrayRef::new(v.as_mut_ptr(), v.len()) };
1356    ///
1357    /// let mut buf = [5u8; 16];
1358    /// v_ref.copy_to(&mut buf[..]);
1359    /// for &v in &buf[..] {
1360    ///     assert_eq!(v, 0);
1361    /// }
1362    /// ```
1363    pub fn copy_to(&self, buf: &mut [T]) -> usize {
1364        // A fast path for u8/i8
1365        if size_of::<T>() == 1 {
1366            let source = self.to_slice();
1367            let total = buf.len().min(source.len());
1368
1369            // SAFETY:
1370            // - dst is valid for writes of at least `total`, since total <= buf.len()
1371            // - src is valid for reads of at least `total` as total <= source.len()
1372            // - The regions are non-overlapping as `src` points to guest memory and `buf` is
1373            //   a slice and thus has to live outside of guest memory (there can be more slices to
1374            //   guest memory without violating rust's aliasing rules)
1375            // - size is always a multiple of alignment, so treating *mut T as *mut u8 is fine
1376            return unsafe {
1377                copy_from_volatile_slice(buf.as_mut_ptr() as *mut u8, &source, total)
1378            };
1379        }
1380
1381        let guard = self.ptr_guard();
1382        let mut ptr = guard.as_ptr() as *const Packed<T>;
1383        let start = ptr;
1384
1385        for v in buf.iter_mut().take(self.len()) {
1386            // SAFETY: read_volatile is safe because the pointers are range-checked when
1387            // the slices are created, and they never escape the VolatileSlices.
1388            // ptr::add is safe because get_array_ref() validated that
1389            // size_of::<T>() * self.len() fits in an isize.
1390            unsafe {
1391                *v = read_volatile(ptr).0;
1392                ptr = ptr.add(1);
1393            }
1394        }
1395
1396        // SAFETY: It is guaranteed that start and ptr point to the regions of the same slice.
1397        unsafe { ptr.offset_from(start) as usize }
1398    }
1399
1400    /// Copies as many bytes as possible from this slice to the provided `slice`.
1401    ///
1402    /// The copies happen in an undefined order.
1403    ///
1404    /// # Examples
1405    ///
1406    /// ```
1407    /// # use vm_memory::VolatileArrayRef;
1408    /// #
1409    /// let mut v = [0u8; 32];
1410    /// let v_ref = unsafe { VolatileArrayRef::<u8>::new(v.as_mut_ptr(), v.len()) };
1411    /// let mut buf = [5u8; 16];
1412    /// let v_ref2 = unsafe { VolatileArrayRef::<u8>::new(buf.as_mut_ptr(), buf.len()) };
1413    ///
1414    /// v_ref.copy_to_volatile_slice(v_ref2.to_slice());
1415    /// for &v in &buf[..] {
1416    ///     assert_eq!(v, 0);
1417    /// }
1418    /// ```
1419    pub fn copy_to_volatile_slice<S: BitmapSlice>(&self, slice: VolatileSlice<S>) {
1420        // SAFETY: Safe because the pointers are range-checked when the slices
1421        // are created, and they never escape the VolatileSlices.
1422        // FIXME: ... however, is it really okay to mix non-volatile
1423        // operations such as copy with read_volatile and write_volatile?
1424        unsafe {
1425            let count = min(self.len() * self.element_size(), slice.size);
1426            copy(self.addr, slice.addr, count);
1427            slice.bitmap.mark_dirty(0, count);
1428        }
1429    }
1430
1431    /// Copies as many elements of type `T` as possible from `buf` to this slice.
1432    ///
1433    /// Copies `self.len()` or `buf.len()` times the size of `T` bytes, whichever is smaller,
1434    /// to this slice's memory. The copy happens from smallest to largest address in
1435    /// `T` sized chunks using volatile writes.
1436    ///
1437    /// # Examples
1438    ///
1439    /// ```
1440    /// # use vm_memory::VolatileArrayRef;
1441    /// #
1442    /// let mut v = [0u8; 32];
1443    /// let v_ref = unsafe { VolatileArrayRef::<u8>::new(v.as_mut_ptr(), v.len()) };
1444    ///
1445    /// let buf = [5u8; 64];
1446    /// v_ref.copy_from(&buf[..]);
1447    /// for &val in &v[..] {
1448    ///     assert_eq!(5u8, val);
1449    /// }
1450    /// ```
1451    pub fn copy_from(&self, buf: &[T]) {
1452        // A fast path for u8/i8
1453        if size_of::<T>() == 1 {
1454            let destination = self.to_slice();
1455            let total = buf.len().min(destination.len());
1456
1457            // absurd formatting brought to you by clippy
1458            // SAFETY:
1459            // - dst is valid for writes of at least `total`, since total <= destination.len()
1460            // - src is valid for reads of at least `total` as total <= buf.len()
1461            // - The regions are non-overlapping as `dst` points to guest memory and `buf` is
1462            //   a slice and thus has to live outside of guest memory (there can be more slices to
1463            //   guest memory without violating rust's aliasing rules)
1464            // - size is always a multiple of alignment, so treating *const T as *const u8 is fine
1465            unsafe { copy_to_volatile_slice(&destination, buf.as_ptr() as *const u8, total) };
1466        } else {
1467            let guard = self.ptr_guard_mut();
1468            let start = guard.as_ptr();
1469            let mut ptr = start as *mut Packed<T>;
1470
1471            for &v in buf.iter().take(self.len()) {
1472                // SAFETY: write_volatile is safe because the pointers are range-checked when
1473                // the slices are created, and they never escape the VolatileSlices.
1474                // ptr::add is safe because get_array_ref() validated that
1475                // size_of::<T>() * self.len() fits in an isize.
1476                unsafe {
1477                    write_volatile(ptr, Packed::<T>(v));
1478                    ptr = ptr.add(1);
1479                }
1480            }
1481
1482            self.bitmap.mark_dirty(0, ptr as usize - start as usize);
1483        }
1484    }
1485}
1486
1487impl<'a, B: BitmapSlice> From<VolatileSlice<'a, B>> for VolatileArrayRef<'a, u8, B> {
1488    fn from(slice: VolatileSlice<'a, B>) -> Self {
1489        // SAFETY: Safe because the result has the same lifetime and points to the same
1490        // memory as the incoming VolatileSlice.
1491        unsafe { VolatileArrayRef::with_bitmap(slice.addr, slice.len(), slice.bitmap, slice.mmap) }
1492    }
1493}
1494
1495// Return the largest value that `addr` is aligned to. Forcing this function to return 1 will
1496// cause test_non_atomic_access to fail.
1497fn alignment(addr: usize) -> usize {
1498    // Rust is silly and does not let me write addr & -addr.
1499    addr & (!addr + 1)
1500}
1501
1502pub(crate) mod copy_slice_impl {
1503    use super::*;
1504
1505    // SAFETY: Has the same safety requirements as `read_volatile` + `write_volatile`, namely:
1506    // - `src_addr` and `dst_addr` must be valid for reads/writes.
1507    // - `src_addr` and `dst_addr` must be properly aligned with respect to `align`.
1508    // - `src_addr` must point to a properly initialized value, which is true here because
1509    //   we're only using integer primitives.
1510    unsafe fn copy_single(align: usize, src_addr: *const u8, dst_addr: *mut u8) {
1511        match align {
1512            8 => write_volatile(dst_addr as *mut u64, read_volatile(src_addr as *const u64)),
1513            4 => write_volatile(dst_addr as *mut u32, read_volatile(src_addr as *const u32)),
1514            2 => write_volatile(dst_addr as *mut u16, read_volatile(src_addr as *const u16)),
1515            1 => write_volatile(dst_addr, read_volatile(src_addr)),
1516            _ => unreachable!(),
1517        }
1518    }
1519
1520    /// Copies `total` bytes from `src` to `dst` using a loop of volatile reads and writes
1521    ///
1522    /// SAFETY: `src` and `dst` must be point to a contiguously allocated memory region of at least
1523    /// length `total`. The regions must not overlap
1524    unsafe fn copy_slice_volatile(mut dst: *mut u8, mut src: *const u8, total: usize) -> usize {
1525        let mut left = total;
1526
1527        let align = min(alignment(src as usize), alignment(dst as usize));
1528
1529        let mut copy_aligned_slice = |min_align| {
1530            if align < min_align {
1531                return;
1532            }
1533
1534            while left >= min_align {
1535                // SAFETY: Safe because we check alignment beforehand, the memory areas are valid
1536                // for reads/writes, and the source always contains a valid value.
1537                unsafe { copy_single(min_align, src, dst) };
1538
1539                left -= min_align;
1540
1541                if left == 0 {
1542                    break;
1543                }
1544
1545                // SAFETY: We only explain the invariants for `src`, the argument for `dst` is
1546                // analogous.
1547                // - `src` and `src + min_align` are within (or one byte past) the same allocated object
1548                //   This is given by the invariant on this function ensuring that [src, src + total)
1549                //   are part of the same allocated object, and the condition on the while loop
1550                //   ensures that we do not go outside this object
1551                // - The computed offset in bytes cannot overflow isize, because `min_align` is at
1552                //   most 8 when the closure is called (see below)
1553                // - The sum `src as usize + min_align` can only wrap around if src as usize + min_align - 1 == usize::MAX,
1554                //   however in this case, left == 0, and we'll have exited the loop above.
1555                unsafe {
1556                    src = src.add(min_align);
1557                    dst = dst.add(min_align);
1558                }
1559            }
1560        };
1561
1562        if size_of::<usize>() > 4 {
1563            copy_aligned_slice(8);
1564        }
1565        copy_aligned_slice(4);
1566        copy_aligned_slice(2);
1567        copy_aligned_slice(1);
1568
1569        total
1570    }
1571
1572    /// Copies `total` bytes from `src` to `dst`
1573    ///
1574    /// SAFETY: `src` and `dst` must be point to a contiguously allocated memory region of at least
1575    /// length `total`. The regions must not overlap
1576    unsafe fn copy_slice(dst: *mut u8, src: *const u8, total: usize) -> usize {
1577        if total <= size_of::<usize>() {
1578            // SAFETY: Invariants of copy_slice_volatile are the same as invariants of copy_slice
1579            unsafe {
1580                copy_slice_volatile(dst, src, total);
1581            };
1582        } else {
1583            // SAFETY:
1584            // - Both src and dst are allocated for reads/writes of length `total` by function
1585            //   invariant
1586            // - src and dst are properly aligned, as any alignment is valid for u8
1587            // - The regions are not overlapping by function invariant
1588            unsafe {
1589                std::ptr::copy_nonoverlapping(src, dst, total);
1590            }
1591        }
1592
1593        total
1594    }
1595
1596    /// Copies `total` bytes from `slice` to `dst`
1597    ///
1598    /// SAFETY: `slice` and `dst` must be point to a contiguously allocated memory region of at
1599    /// least length `total`. The regions must not overlap.
1600    pub(crate) unsafe fn copy_from_volatile_slice<B: BitmapSlice>(
1601        dst: *mut u8,
1602        slice: &VolatileSlice<'_, B>,
1603        total: usize,
1604    ) -> usize {
1605        let guard = slice.ptr_guard();
1606
1607        // SAFETY: guaranteed by function invariants.
1608        copy_slice(dst, guard.as_ptr(), total)
1609    }
1610
1611    /// Copies `total` bytes from 'src' to `slice`
1612    ///
1613    /// SAFETY: `slice` and `src` must be point to a contiguously allocated memory region of at
1614    /// least length `total`. The regions must not overlap.
1615    pub(crate) unsafe fn copy_to_volatile_slice<B: BitmapSlice>(
1616        slice: &VolatileSlice<'_, B>,
1617        src: *const u8,
1618        total: usize,
1619    ) -> usize {
1620        let guard = slice.ptr_guard_mut();
1621
1622        // SAFETY: guaranteed by function invariants.
1623        let count = copy_slice(guard.as_ptr(), src, total);
1624        slice.bitmap.mark_dirty(0, count);
1625        count
1626    }
1627}
1628
1629#[cfg(test)]
1630mod tests {
1631    #![allow(clippy::undocumented_unsafe_blocks)]
1632
1633    use super::*;
1634    use std::alloc::Layout;
1635
1636    use std::fs::File;
1637    use std::mem::size_of_val;
1638    use std::path::Path;
1639    use std::sync::atomic::{AtomicUsize, Ordering};
1640    use std::sync::{Arc, Barrier};
1641    use std::thread::spawn;
1642
1643    use matches::assert_matches;
1644    use std::num::NonZeroUsize;
1645    use vmm_sys_util::tempfile::TempFile;
1646
1647    use crate::bitmap::tests::{
1648        check_range, range_is_clean, range_is_dirty, test_bytes, test_volatile_memory,
1649    };
1650    use crate::bitmap::{AtomicBitmap, RefSlice};
1651
1652    const DEFAULT_PAGE_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(0x1000) };
1653
1654    #[test]
1655    fn test_display_error() {
1656        assert_eq!(
1657            format!("{}", Error::OutOfBounds { addr: 0x10 }),
1658            "address 0x10 is out of bounds"
1659        );
1660
1661        assert_eq!(
1662            format!(
1663                "{}",
1664                Error::Overflow {
1665                    base: 0x0,
1666                    offset: 0x10
1667                }
1668            ),
1669            "address 0x0 offset by 0x10 would overflow"
1670        );
1671
1672        assert_eq!(
1673            format!(
1674                "{}",
1675                Error::TooBig {
1676                    nelements: 100_000,
1677                    size: 1_000_000_000
1678                }
1679            ),
1680            "100000 elements of size 1000000000 would overflow a usize"
1681        );
1682
1683        assert_eq!(
1684            format!(
1685                "{}",
1686                Error::Misaligned {
1687                    addr: 0x4,
1688                    alignment: 8
1689                }
1690            ),
1691            "address 0x4 is not aligned to 8"
1692        );
1693
1694        assert_eq!(
1695            format!(
1696                "{}",
1697                Error::PartialBuffer {
1698                    expected: 100,
1699                    completed: 90
1700                }
1701            ),
1702            "only used 90 bytes in 100 long buffer"
1703        );
1704    }
1705
1706    #[test]
1707    fn misaligned_ref() {
1708        let mut a = [0u8; 3];
1709        let a_ref = VolatileSlice::from(&mut a[..]);
1710        unsafe {
1711            assert!(
1712                a_ref.aligned_as_ref::<u16>(0).is_err() ^ a_ref.aligned_as_ref::<u16>(1).is_err()
1713            );
1714            assert!(
1715                a_ref.aligned_as_mut::<u16>(0).is_err() ^ a_ref.aligned_as_mut::<u16>(1).is_err()
1716            );
1717        }
1718    }
1719
1720    #[test]
1721    fn atomic_store() {
1722        let mut a = [0usize; 1];
1723        {
1724            let a_ref = unsafe {
1725                VolatileSlice::new(&mut a[0] as *mut usize as *mut u8, size_of::<usize>())
1726            };
1727            let atomic = a_ref.get_atomic_ref::<AtomicUsize>(0).unwrap();
1728            atomic.store(2usize, Ordering::Relaxed)
1729        }
1730        assert_eq!(a[0], 2);
1731    }
1732
1733    #[test]
1734    fn atomic_load() {
1735        let mut a = [5usize; 1];
1736        {
1737            let a_ref = unsafe {
1738                VolatileSlice::new(&mut a[0] as *mut usize as *mut u8,
1739                                   size_of::<usize>())
1740            };
1741            let atomic = {
1742                let atomic = a_ref.get_atomic_ref::<AtomicUsize>(0).unwrap();
1743                assert_eq!(atomic.load(Ordering::Relaxed), 5usize);
1744                atomic
1745            };
1746            // To make sure we can take the atomic out of the scope we made it in:
1747            atomic.load(Ordering::Relaxed);
1748            // but not too far:
1749            // atomicu8
1750        } //.load(std::sync::atomic::Ordering::Relaxed)
1751        ;
1752    }
1753
1754    #[test]
1755    fn misaligned_atomic() {
1756        let mut a = [5usize, 5usize];
1757        let a_ref =
1758            unsafe { VolatileSlice::new(&mut a[0] as *mut usize as *mut u8, size_of::<usize>()) };
1759        assert!(a_ref.get_atomic_ref::<AtomicUsize>(0).is_ok());
1760        assert!(a_ref.get_atomic_ref::<AtomicUsize>(1).is_err());
1761    }
1762
1763    #[test]
1764    fn ref_store() {
1765        let mut a = [0u8; 1];
1766        {
1767            let a_ref = VolatileSlice::from(&mut a[..]);
1768            let v_ref = a_ref.get_ref(0).unwrap();
1769            v_ref.store(2u8);
1770        }
1771        assert_eq!(a[0], 2);
1772    }
1773
1774    #[test]
1775    fn ref_load() {
1776        let mut a = [5u8; 1];
1777        {
1778            let a_ref = VolatileSlice::from(&mut a[..]);
1779            let c = {
1780                let v_ref = a_ref.get_ref::<u8>(0).unwrap();
1781                assert_eq!(v_ref.load(), 5u8);
1782                v_ref
1783            };
1784            // To make sure we can take a v_ref out of the scope we made it in:
1785            c.load();
1786            // but not too far:
1787            // c
1788        } //.load()
1789        ;
1790    }
1791
1792    #[test]
1793    fn ref_to_slice() {
1794        let mut a = [1u8; 5];
1795        let a_ref = VolatileSlice::from(&mut a[..]);
1796        let v_ref = a_ref.get_ref(1).unwrap();
1797        v_ref.store(0x1234_5678u32);
1798        let ref_slice = v_ref.to_slice();
1799        assert_eq!(v_ref.addr as usize, ref_slice.addr as usize);
1800        assert_eq!(v_ref.len(), ref_slice.len());
1801        assert!(!ref_slice.is_empty());
1802    }
1803
1804    #[test]
1805    fn observe_mutate() {
1806        struct RawMemory(*mut u8);
1807
1808        // SAFETY: we use property synchronization below
1809        unsafe impl Send for RawMemory {}
1810        unsafe impl Sync for RawMemory {}
1811
1812        let mem = Arc::new(RawMemory(unsafe {
1813            std::alloc::alloc(Layout::from_size_align(1, 1).unwrap())
1814        }));
1815
1816        let outside_slice = unsafe { VolatileSlice::new(Arc::clone(&mem).0, 1) };
1817        let inside_arc = Arc::clone(&mem);
1818
1819        let v_ref = outside_slice.get_ref::<u8>(0).unwrap();
1820        let barrier = Arc::new(Barrier::new(2));
1821        let barrier1 = barrier.clone();
1822
1823        v_ref.store(99);
1824        spawn(move || {
1825            barrier1.wait();
1826            let inside_slice = unsafe { VolatileSlice::new(inside_arc.0, 1) };
1827            let clone_v_ref = inside_slice.get_ref::<u8>(0).unwrap();
1828            clone_v_ref.store(0);
1829            barrier1.wait();
1830        });
1831
1832        assert_eq!(v_ref.load(), 99);
1833        barrier.wait();
1834        barrier.wait();
1835        assert_eq!(v_ref.load(), 0);
1836
1837        unsafe { std::alloc::dealloc(mem.0, Layout::from_size_align(1, 1).unwrap()) }
1838    }
1839
1840    #[test]
1841    fn mem_is_empty() {
1842        let mut backing = vec![0u8; 100];
1843        let a = VolatileSlice::from(backing.as_mut_slice());
1844        assert!(!a.is_empty());
1845
1846        let mut backing = vec![];
1847        let a = VolatileSlice::from(backing.as_mut_slice());
1848        assert!(a.is_empty());
1849    }
1850
1851    #[test]
1852    fn slice_len() {
1853        let mut backing = vec![0u8; 100];
1854        let mem = VolatileSlice::from(backing.as_mut_slice());
1855        let slice = mem.get_slice(0, 27).unwrap();
1856        assert_eq!(slice.len(), 27);
1857        assert!(!slice.is_empty());
1858
1859        let slice = mem.get_slice(34, 27).unwrap();
1860        assert_eq!(slice.len(), 27);
1861        assert!(!slice.is_empty());
1862
1863        let slice = slice.get_slice(20, 5).unwrap();
1864        assert_eq!(slice.len(), 5);
1865        assert!(!slice.is_empty());
1866
1867        let slice = mem.get_slice(34, 0).unwrap();
1868        assert!(slice.is_empty());
1869    }
1870
1871    #[test]
1872    fn slice_subslice() {
1873        let mut backing = vec![0u8; 100];
1874        let mem = VolatileSlice::from(backing.as_mut_slice());
1875        let slice = mem.get_slice(0, 100).unwrap();
1876        assert!(slice.write(&[1; 80], 10).is_ok());
1877
1878        assert!(slice.subslice(0, 0).is_ok());
1879        assert!(slice.subslice(0, 101).is_err());
1880
1881        assert!(slice.subslice(99, 0).is_ok());
1882        assert!(slice.subslice(99, 1).is_ok());
1883        assert!(slice.subslice(99, 2).is_err());
1884
1885        assert!(slice.subslice(100, 0).is_ok());
1886        assert!(slice.subslice(100, 1).is_err());
1887
1888        assert!(slice.subslice(101, 0).is_err());
1889        assert!(slice.subslice(101, 1).is_err());
1890
1891        assert!(slice.subslice(usize::MAX, 2).is_err());
1892        assert!(slice.subslice(2, usize::MAX).is_err());
1893
1894        let maybe_offset_slice = slice.subslice(10, 80);
1895        assert!(maybe_offset_slice.is_ok());
1896        let offset_slice = maybe_offset_slice.unwrap();
1897        assert_eq!(offset_slice.len(), 80);
1898
1899        let mut buf = [0; 80];
1900        assert!(offset_slice.read(&mut buf, 0).is_ok());
1901        assert_eq!(&buf[0..80], &[1; 80][0..80]);
1902    }
1903
1904    #[test]
1905    fn slice_offset() {
1906        let mut backing = vec![0u8; 100];
1907        let mem = VolatileSlice::from(backing.as_mut_slice());
1908        let slice = mem.get_slice(0, 100).unwrap();
1909        assert!(slice.write(&[1; 80], 10).is_ok());
1910
1911        assert!(slice.offset(101).is_err());
1912
1913        let maybe_offset_slice = slice.offset(10);
1914        assert!(maybe_offset_slice.is_ok());
1915        let offset_slice = maybe_offset_slice.unwrap();
1916        assert_eq!(offset_slice.len(), 90);
1917        let mut buf = [0; 90];
1918        assert!(offset_slice.read(&mut buf, 0).is_ok());
1919        assert_eq!(&buf[0..80], &[1; 80][0..80]);
1920        assert_eq!(&buf[80..90], &[0; 10][0..10]);
1921    }
1922
1923    #[test]
1924    fn slice_copy_to_u8() {
1925        let mut a = [2u8, 4, 6, 8, 10];
1926        let mut b = [0u8; 4];
1927        let mut c = [0u8; 6];
1928        let a_ref = VolatileSlice::from(&mut a[..]);
1929        let v_ref = a_ref.get_slice(0, a_ref.len()).unwrap();
1930        v_ref.copy_to(&mut b[..]);
1931        v_ref.copy_to(&mut c[..]);
1932        assert_eq!(b[0..4], a[0..4]);
1933        assert_eq!(c[0..5], a[0..5]);
1934    }
1935
1936    #[test]
1937    fn slice_copy_to_u16() {
1938        let mut a = [0x01u16, 0x2, 0x03, 0x4, 0x5];
1939        let mut b = [0u16; 4];
1940        let mut c = [0u16; 6];
1941        let a_ref = &mut a[..];
1942        let v_ref = unsafe { VolatileSlice::new(a_ref.as_mut_ptr() as *mut u8, 9) };
1943
1944        v_ref.copy_to(&mut b[..]);
1945        v_ref.copy_to(&mut c[..]);
1946        assert_eq!(b[0..4], a_ref[0..4]);
1947        assert_eq!(c[0..4], a_ref[0..4]);
1948        assert_eq!(c[4], 0);
1949    }
1950
1951    #[test]
1952    fn slice_copy_from_u8() {
1953        let a = [2u8, 4, 6, 8, 10];
1954        let mut b = [0u8; 4];
1955        let mut c = [0u8; 6];
1956        let b_ref = VolatileSlice::from(&mut b[..]);
1957        let v_ref = b_ref.get_slice(0, b_ref.len()).unwrap();
1958        v_ref.copy_from(&a[..]);
1959        assert_eq!(b[0..4], a[0..4]);
1960
1961        let c_ref = VolatileSlice::from(&mut c[..]);
1962        let v_ref = c_ref.get_slice(0, c_ref.len()).unwrap();
1963        v_ref.copy_from(&a[..]);
1964        assert_eq!(c[0..5], a[0..5]);
1965    }
1966
1967    #[test]
1968    fn slice_copy_from_u16() {
1969        let a = [2u16, 4, 6, 8, 10];
1970        let mut b = [0u16; 4];
1971        let mut c = [0u16; 6];
1972        let b_ref = &mut b[..];
1973        let v_ref = unsafe { VolatileSlice::new(b_ref.as_mut_ptr() as *mut u8, 8) };
1974        v_ref.copy_from(&a[..]);
1975        assert_eq!(b_ref[0..4], a[0..4]);
1976
1977        let c_ref = &mut c[..];
1978        let v_ref = unsafe { VolatileSlice::new(c_ref.as_mut_ptr() as *mut u8, 9) };
1979        v_ref.copy_from(&a[..]);
1980        assert_eq!(c_ref[0..4], a[0..4]);
1981        assert_eq!(c_ref[4], 0);
1982    }
1983
1984    #[test]
1985    fn slice_copy_to_volatile_slice() {
1986        let mut a = [2u8, 4, 6, 8, 10];
1987        let a_ref = VolatileSlice::from(&mut a[..]);
1988        let a_slice = a_ref.get_slice(0, a_ref.len()).unwrap();
1989
1990        let mut b = [0u8; 4];
1991        let b_ref = VolatileSlice::from(&mut b[..]);
1992        let b_slice = b_ref.get_slice(0, b_ref.len()).unwrap();
1993
1994        a_slice.copy_to_volatile_slice(b_slice);
1995        assert_eq!(b, [2, 4, 6, 8]);
1996    }
1997
1998    #[test]
1999    fn slice_overflow_error() {
2000        let mut backing = vec![0u8];
2001        let a = VolatileSlice::from(backing.as_mut_slice());
2002        let res = a.get_slice(usize::MAX, 1).unwrap_err();
2003        assert_matches!(
2004            res,
2005            Error::Overflow {
2006                base: usize::MAX,
2007                offset: 1,
2008            }
2009        );
2010    }
2011
2012    #[test]
2013    fn slice_oob_error() {
2014        let mut backing = vec![0u8; 100];
2015        let a = VolatileSlice::from(backing.as_mut_slice());
2016        a.get_slice(50, 50).unwrap();
2017        let res = a.get_slice(55, 50).unwrap_err();
2018        assert_matches!(res, Error::OutOfBounds { addr: 105 });
2019    }
2020
2021    #[test]
2022    fn ref_overflow_error() {
2023        let mut backing = vec![0u8];
2024        let a = VolatileSlice::from(backing.as_mut_slice());
2025        let res = a.get_ref::<u8>(usize::MAX).unwrap_err();
2026        assert_matches!(
2027            res,
2028            Error::Overflow {
2029                base: usize::MAX,
2030                offset: 1,
2031            }
2032        );
2033    }
2034
2035    #[test]
2036    fn ref_oob_error() {
2037        let mut backing = vec![0u8; 100];
2038        let a = VolatileSlice::from(backing.as_mut_slice());
2039        a.get_ref::<u8>(99).unwrap();
2040        let res = a.get_ref::<u16>(99).unwrap_err();
2041        assert_matches!(res, Error::OutOfBounds { addr: 101 });
2042    }
2043
2044    #[test]
2045    fn ref_oob_too_large() {
2046        let mut backing = vec![0u8; 3];
2047        let a = VolatileSlice::from(backing.as_mut_slice());
2048        let res = a.get_ref::<u32>(0).unwrap_err();
2049        assert_matches!(res, Error::OutOfBounds { addr: 4 });
2050    }
2051
2052    #[test]
2053    fn slice_store() {
2054        let mut backing = vec![0u8; 5];
2055        let a = VolatileSlice::from(backing.as_mut_slice());
2056        let s = a.as_volatile_slice();
2057        let r = a.get_ref(2).unwrap();
2058        r.store(9u16);
2059        assert_eq!(s.read_obj::<u16>(2).unwrap(), 9);
2060    }
2061
2062    #[test]
2063    fn test_write_past_end() {
2064        let mut backing = vec![0u8; 5];
2065        let a = VolatileSlice::from(backing.as_mut_slice());
2066        let s = a.as_volatile_slice();
2067        let res = s.write(&[1, 2, 3, 4, 5, 6], 0);
2068        assert!(res.is_ok());
2069        assert_eq!(res.unwrap(), 5);
2070    }
2071
2072    #[test]
2073    fn slice_read_and_write() {
2074        let mut backing = vec![0u8; 5];
2075        let a = VolatileSlice::from(backing.as_mut_slice());
2076        let s = a.as_volatile_slice();
2077        let sample_buf = [1, 2, 3];
2078        assert!(s.write(&sample_buf, 5).is_err());
2079        assert!(s.write(&sample_buf, 2).is_ok());
2080        let mut buf = [0u8; 3];
2081        assert!(s.read(&mut buf, 5).is_err());
2082        assert!(s.read_slice(&mut buf, 2).is_ok());
2083        assert_eq!(buf, sample_buf);
2084
2085        // Writing an empty buffer at the end of the volatile slice works.
2086        assert_eq!(s.write(&[], 100).unwrap(), 0);
2087        let buf: &mut [u8] = &mut [];
2088        assert_eq!(s.read(buf, 4).unwrap(), 0);
2089
2090        // Check that reading and writing an empty buffer does not yield an error.
2091        let mut backing = Vec::new();
2092        let empty_mem = VolatileSlice::from(backing.as_mut_slice());
2093        let empty = empty_mem.as_volatile_slice();
2094        assert_eq!(empty.write(&[], 1).unwrap(), 0);
2095        assert_eq!(empty.read(buf, 1).unwrap(), 0);
2096    }
2097
2098    #[test]
2099    fn obj_read_and_write() {
2100        let mut backing = vec![0u8; 5];
2101        let a = VolatileSlice::from(backing.as_mut_slice());
2102        let s = a.as_volatile_slice();
2103        assert!(s.write_obj(55u16, 4).is_err());
2104        assert!(s.write_obj(55u16, usize::MAX).is_err());
2105        assert!(s.write_obj(55u16, 2).is_ok());
2106        assert_eq!(s.read_obj::<u16>(2).unwrap(), 55u16);
2107        assert!(s.read_obj::<u16>(4).is_err());
2108        assert!(s.read_obj::<u16>(usize::MAX).is_err());
2109    }
2110
2111    #[test]
2112    fn mem_read_and_write() {
2113        let mut backing = vec![0u8; 5];
2114        let a = VolatileSlice::from(backing.as_mut_slice());
2115        let s = a.as_volatile_slice();
2116        assert!(s.write_obj(!0u32, 1).is_ok());
2117        let mut file = if cfg!(unix) {
2118            File::open(Path::new("/dev/zero")).unwrap()
2119        } else {
2120            File::open(Path::new("c:\\Windows\\system32\\ntoskrnl.exe")).unwrap()
2121        };
2122
2123        assert!(file
2124            .read_exact_volatile(&mut s.get_slice(1, size_of::<u32>()).unwrap())
2125            .is_ok());
2126
2127        let mut f = TempFile::new().unwrap().into_file();
2128        assert!(f
2129            .read_exact_volatile(&mut s.get_slice(1, size_of::<u32>()).unwrap())
2130            .is_err());
2131
2132        let value = s.read_obj::<u32>(1).unwrap();
2133        if cfg!(unix) {
2134            assert_eq!(value, 0);
2135        } else {
2136            assert_eq!(value, 0x0090_5a4d);
2137        }
2138
2139        let mut sink = vec![0; size_of::<u32>()];
2140        assert!(sink
2141            .as_mut_slice()
2142            .write_all_volatile(&s.get_slice(1, size_of::<u32>()).unwrap())
2143            .is_ok());
2144
2145        if cfg!(unix) {
2146            assert_eq!(sink, vec![0; size_of::<u32>()]);
2147        } else {
2148            assert_eq!(sink, vec![0x4d, 0x5a, 0x90, 0x00]);
2149        };
2150    }
2151
2152    #[test]
2153    fn unaligned_read_and_write() {
2154        let mut backing = vec![0u8; 7];
2155        let a = VolatileSlice::from(backing.as_mut_slice());
2156        let s = a.as_volatile_slice();
2157        let sample_buf: [u8; 7] = [1, 2, 0xAA, 0xAA, 0xAA, 0xAA, 4];
2158        assert!(s.write_slice(&sample_buf, 0).is_ok());
2159        let r = a.get_ref::<u32>(2).unwrap();
2160        assert_eq!(r.load(), 0xAAAA_AAAA);
2161
2162        r.store(0x5555_5555);
2163        let sample_buf: [u8; 7] = [1, 2, 0x55, 0x55, 0x55, 0x55, 4];
2164        let mut buf: [u8; 7] = Default::default();
2165        assert!(s.read_slice(&mut buf, 0).is_ok());
2166        assert_eq!(buf, sample_buf);
2167    }
2168
2169    #[test]
2170    fn test_read_from_exceeds_size() {
2171        #[derive(Debug, Default, Copy, Clone)]
2172        struct BytesToRead {
2173            _val1: u128, // 16 bytes
2174            _val2: u128, // 16 bytes
2175        }
2176        unsafe impl ByteValued for BytesToRead {}
2177        let cursor_size = 20;
2178        let image = vec![1u8; cursor_size];
2179
2180        // Trying to read more bytes than we have space for in image
2181        // make the read_from function return maximum vec size (i.e. 20).
2182        let mut bytes_to_read = BytesToRead::default();
2183        assert_eq!(
2184            image
2185                .as_slice()
2186                .read_volatile(&mut bytes_to_read.as_bytes())
2187                .unwrap(),
2188            cursor_size
2189        );
2190    }
2191
2192    #[test]
2193    fn ref_array_from_slice() {
2194        let mut a = [2, 4, 6, 8, 10];
2195        let a_vec = a.to_vec();
2196        let a_ref = VolatileSlice::from(&mut a[..]);
2197        let a_slice = a_ref.get_slice(0, a_ref.len()).unwrap();
2198        let a_array_ref: VolatileArrayRef<u8, ()> = a_slice.into();
2199        for (i, entry) in a_vec.iter().enumerate() {
2200            assert_eq!(&a_array_ref.load(i), entry);
2201        }
2202    }
2203
2204    #[test]
2205    fn ref_array_store() {
2206        let mut a = [0u8; 5];
2207        {
2208            let a_ref = VolatileSlice::from(&mut a[..]);
2209            let v_ref = a_ref.get_array_ref(1, 4).unwrap();
2210            v_ref.store(1, 2u8);
2211            v_ref.store(2, 4u8);
2212            v_ref.store(3, 6u8);
2213        }
2214        let expected = [2u8, 4u8, 6u8];
2215        assert_eq!(a[2..=4], expected);
2216    }
2217
2218    #[test]
2219    fn ref_array_load() {
2220        let mut a = [0, 0, 2, 3, 10];
2221        {
2222            let a_ref = VolatileSlice::from(&mut a[..]);
2223            let c = {
2224                let v_ref = a_ref.get_array_ref::<u8>(1, 4).unwrap();
2225                assert_eq!(v_ref.load(1), 2u8);
2226                assert_eq!(v_ref.load(2), 3u8);
2227                assert_eq!(v_ref.load(3), 10u8);
2228                v_ref
2229            };
2230            // To make sure we can take a v_ref out of the scope we made it in:
2231            c.load(0);
2232            // but not too far:
2233            // c
2234        } //.load()
2235        ;
2236    }
2237
2238    #[test]
2239    fn ref_array_overflow() {
2240        let mut a = [0, 0, 2, 3, 10];
2241        let a_ref = VolatileSlice::from(&mut a[..]);
2242        let res = a_ref.get_array_ref::<u32>(4, usize::MAX).unwrap_err();
2243        assert_matches!(
2244            res,
2245            Error::TooBig {
2246                nelements: usize::MAX,
2247                size: 4,
2248            }
2249        );
2250    }
2251
2252    #[test]
2253    fn alignment() {
2254        let a = [0u8; 64];
2255        let a = &a[a.as_ptr().align_offset(32)] as *const u8 as usize;
2256        assert!(super::alignment(a) >= 32);
2257        assert_eq!(super::alignment(a + 9), 1);
2258        assert_eq!(super::alignment(a + 30), 2);
2259        assert_eq!(super::alignment(a + 12), 4);
2260        assert_eq!(super::alignment(a + 8), 8);
2261    }
2262
2263    #[test]
2264    fn test_atomic_accesses() {
2265        let len = 0x1000;
2266        let buf = unsafe { std::alloc::alloc_zeroed(Layout::from_size_align(len, 8).unwrap()) };
2267        let a = unsafe { VolatileSlice::new(buf, len) };
2268
2269        crate::bytes::tests::check_atomic_accesses(a, 0, 0x1000);
2270        unsafe {
2271            std::alloc::dealloc(buf, Layout::from_size_align(len, 8).unwrap());
2272        }
2273    }
2274
2275    #[test]
2276    fn split_at() {
2277        let mut mem = [0u8; 32];
2278        let mem_ref = VolatileSlice::from(&mut mem[..]);
2279        let vslice = mem_ref.get_slice(0, 32).unwrap();
2280        let (start, end) = vslice.split_at(8).unwrap();
2281        assert_eq!(start.len(), 8);
2282        assert_eq!(end.len(), 24);
2283        let (start, end) = vslice.split_at(0).unwrap();
2284        assert_eq!(start.len(), 0);
2285        assert_eq!(end.len(), 32);
2286        let (start, end) = vslice.split_at(31).unwrap();
2287        assert_eq!(start.len(), 31);
2288        assert_eq!(end.len(), 1);
2289        let (start, end) = vslice.split_at(32).unwrap();
2290        assert_eq!(start.len(), 32);
2291        assert_eq!(end.len(), 0);
2292        let err = vslice.split_at(33).unwrap_err();
2293        assert_matches!(err, Error::OutOfBounds { addr: _ })
2294    }
2295
2296    #[test]
2297    fn test_volatile_slice_dirty_tracking() {
2298        let val = 123u64;
2299        let dirty_offset = 0x1000;
2300        let dirty_len = size_of_val(&val);
2301
2302        let len = 0x10000;
2303        let buf = unsafe { std::alloc::alloc_zeroed(Layout::from_size_align(len, 8).unwrap()) };
2304
2305        // Invoke the `Bytes` test helper function.
2306        {
2307            let bitmap = AtomicBitmap::new(len, DEFAULT_PAGE_SIZE);
2308            let slice = unsafe { VolatileSlice::with_bitmap(buf, len, bitmap.slice_at(0), None) };
2309
2310            test_bytes(
2311                &slice,
2312                |s: &VolatileSlice<RefSlice<AtomicBitmap>>,
2313                 start: usize,
2314                 len: usize,
2315                 clean: bool| { check_range(s.bitmap(), start, len, clean) },
2316                |offset| offset,
2317                0x1000,
2318            );
2319        }
2320
2321        // Invoke the `VolatileMemory` test helper function.
2322        {
2323            let bitmap = AtomicBitmap::new(len, DEFAULT_PAGE_SIZE);
2324            let slice = unsafe { VolatileSlice::with_bitmap(buf, len, bitmap.slice_at(0), None) };
2325            test_volatile_memory(&slice);
2326        }
2327
2328        let bitmap = AtomicBitmap::new(len, DEFAULT_PAGE_SIZE);
2329        let slice = unsafe { VolatileSlice::with_bitmap(buf, len, bitmap.slice_at(0), None) };
2330
2331        let bitmap2 = AtomicBitmap::new(len, DEFAULT_PAGE_SIZE);
2332        let slice2 = unsafe { VolatileSlice::with_bitmap(buf, len, bitmap2.slice_at(0), None) };
2333
2334        let bitmap3 = AtomicBitmap::new(len, DEFAULT_PAGE_SIZE);
2335        let slice3 = unsafe { VolatileSlice::with_bitmap(buf, len, bitmap3.slice_at(0), None) };
2336
2337        assert!(range_is_clean(slice.bitmap(), 0, slice.len()));
2338        assert!(range_is_clean(slice2.bitmap(), 0, slice2.len()));
2339
2340        slice.write_obj(val, dirty_offset).unwrap();
2341        assert!(range_is_dirty(slice.bitmap(), dirty_offset, dirty_len));
2342
2343        slice.copy_to_volatile_slice(slice2);
2344        assert!(range_is_dirty(slice2.bitmap(), 0, slice2.len()));
2345
2346        {
2347            let (s1, s2) = slice.split_at(dirty_offset).unwrap();
2348            assert!(range_is_clean(s1.bitmap(), 0, s1.len()));
2349            assert!(range_is_dirty(s2.bitmap(), 0, dirty_len));
2350        }
2351
2352        {
2353            let s = slice.subslice(dirty_offset, dirty_len).unwrap();
2354            assert!(range_is_dirty(s.bitmap(), 0, s.len()));
2355        }
2356
2357        {
2358            let s = slice.offset(dirty_offset).unwrap();
2359            assert!(range_is_dirty(s.bitmap(), 0, dirty_len));
2360        }
2361
2362        // Test `copy_from` for size_of::<T> == 1.
2363        {
2364            let buf = vec![1u8; dirty_offset];
2365
2366            assert!(range_is_clean(slice.bitmap(), 0, dirty_offset));
2367            slice.copy_from(&buf);
2368            assert!(range_is_dirty(slice.bitmap(), 0, dirty_offset));
2369        }
2370
2371        // Test `copy_from` for size_of::<T> > 1.
2372        {
2373            let val = 1u32;
2374            let buf = vec![val; dirty_offset / size_of_val(&val)];
2375
2376            assert!(range_is_clean(slice3.bitmap(), 0, dirty_offset));
2377            slice3.copy_from(&buf);
2378            assert!(range_is_dirty(slice3.bitmap(), 0, dirty_offset));
2379        }
2380
2381        unsafe {
2382            std::alloc::dealloc(buf, Layout::from_size_align(len, 8).unwrap());
2383        }
2384    }
2385
2386    #[test]
2387    fn test_volatile_ref_dirty_tracking() {
2388        let val = 123u64;
2389        let mut buf = vec![val];
2390
2391        let bitmap = AtomicBitmap::new(size_of_val(&val), DEFAULT_PAGE_SIZE);
2392        let vref = unsafe {
2393            VolatileRef::with_bitmap(buf.as_mut_ptr() as *mut u8, bitmap.slice_at(0), None)
2394        };
2395
2396        assert!(range_is_clean(vref.bitmap(), 0, vref.len()));
2397        vref.store(val);
2398        assert!(range_is_dirty(vref.bitmap(), 0, vref.len()));
2399    }
2400
2401    fn test_volatile_array_ref_copy_from_tracking<T>(
2402        buf: &mut [T],
2403        index: usize,
2404        page_size: NonZeroUsize,
2405    ) where
2406        T: ByteValued + From<u8>,
2407    {
2408        let bitmap = AtomicBitmap::new(size_of_val(buf), page_size);
2409        let arr = unsafe {
2410            VolatileArrayRef::with_bitmap(
2411                buf.as_mut_ptr() as *mut u8,
2412                index + 1,
2413                bitmap.slice_at(0),
2414                None,
2415            )
2416        };
2417
2418        let val = T::from(123);
2419        let copy_buf = vec![val; index + 1];
2420
2421        assert!(range_is_clean(arr.bitmap(), 0, arr.len() * size_of::<T>()));
2422        arr.copy_from(copy_buf.as_slice());
2423        assert!(range_is_dirty(arr.bitmap(), 0, size_of_val(buf)));
2424    }
2425
2426    #[test]
2427    fn test_volatile_array_ref_dirty_tracking() {
2428        let val = 123u64;
2429        let dirty_len = size_of_val(&val);
2430        let index = 0x1000;
2431        let dirty_offset = dirty_len * index;
2432
2433        let mut buf = vec![0u64; index + 1];
2434        let mut byte_buf = vec![0u8; index + 1];
2435
2436        // Test `ref_at`.
2437        {
2438            let bitmap = AtomicBitmap::new(buf.len() * size_of_val(&val), DEFAULT_PAGE_SIZE);
2439            let arr = unsafe {
2440                VolatileArrayRef::with_bitmap(
2441                    buf.as_mut_ptr() as *mut u8,
2442                    index + 1,
2443                    bitmap.slice_at(0),
2444                    None,
2445                )
2446            };
2447
2448            assert!(range_is_clean(arr.bitmap(), 0, arr.len() * dirty_len));
2449            arr.ref_at(index).store(val);
2450            assert!(range_is_dirty(arr.bitmap(), dirty_offset, dirty_len));
2451        }
2452
2453        // Test `store`.
2454        {
2455            let bitmap = AtomicBitmap::new(buf.len() * size_of_val(&val), DEFAULT_PAGE_SIZE);
2456            let arr = unsafe {
2457                VolatileArrayRef::with_bitmap(
2458                    buf.as_mut_ptr() as *mut u8,
2459                    index + 1,
2460                    bitmap.slice_at(0),
2461                    None,
2462                )
2463            };
2464
2465            let slice = arr.to_slice();
2466            assert!(range_is_clean(slice.bitmap(), 0, slice.len()));
2467            arr.store(index, val);
2468            assert!(range_is_dirty(slice.bitmap(), dirty_offset, dirty_len));
2469        }
2470
2471        // Test `copy_from` when size_of::<T>() == 1.
2472        test_volatile_array_ref_copy_from_tracking(&mut byte_buf, index, DEFAULT_PAGE_SIZE);
2473        // Test `copy_from` when size_of::<T>() > 1.
2474        test_volatile_array_ref_copy_from_tracking(&mut buf, index, DEFAULT_PAGE_SIZE);
2475    }
2476}