Skip to content

Commit e652da4

Browse files
committed
Switch to IoMemory as the primary memory type
Rust only allows us to give one trait the blanket implementations for `Bytes` and `GuestAddressSpace`. We want `IoMemory` to be our primary external interface becaue it has users specify the access permissions they need, and because we can (and do) provide a blanket `IoMemory` implementation for all `GuestMemory` types. Therefore, replace requirements of `GuestMemory` by `IoMemory` instead. Signed-off-by: Hanna Czenczek <[email protected]>
1 parent 1b60528 commit e652da4

File tree

2 files changed

+42
-29
lines changed

2 files changed

+42
-29
lines changed

src/atomic.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Copyright (C) 2020 Red Hat, Inc. All rights reserved.
33
// SPDX-License-Identifier: Apache-2.0
44

5-
//! A wrapper over an `ArcSwap<GuestMemory>` struct to support RCU-style mutability.
5+
//! A wrapper over an `ArcSwap<IoMemory>` struct to support RCU-style mutability.
66
//!
77
//! With the `backend-atomic` feature enabled, simply replacing `GuestMemoryMmap`
88
//! with `GuestMemoryAtomic<GuestMemoryMmap>` will enable support for mutable memory maps.
@@ -15,17 +15,17 @@ use arc_swap::{ArcSwap, Guard};
1515
use std::ops::Deref;
1616
use std::sync::{Arc, LockResult, Mutex, MutexGuard, PoisonError};
1717

18-
use crate::{GuestAddressSpace, GuestMemory};
18+
use crate::{GuestAddressSpace, IoMemory};
1919

2020
/// A fast implementation of a mutable collection of memory regions.
2121
///
2222
/// This implementation uses `ArcSwap` to provide RCU-like snapshotting of the memory map:
23-
/// every update of the memory map creates a completely new `GuestMemory` object, and
23+
/// every update of the memory map creates a completely new `IoMemory` object, and
2424
/// readers will not be blocked because the copies they retrieved will be collected once
2525
/// no one can access them anymore. Under the assumption that updates to the memory map
2626
/// are rare, this allows a very efficient implementation of the `memory()` method.
2727
#[derive(Clone, Debug)]
28-
pub struct GuestMemoryAtomic<M: GuestMemory> {
28+
pub struct GuestMemoryAtomic<M: IoMemory> {
2929
// GuestAddressSpace<M>, which we want to implement, is basically a drop-in
3030
// replacement for &M. Therefore, we need to pass to devices the `GuestMemoryAtomic`
3131
// rather than a reference to it. To obtain this effect we wrap the actual fields
@@ -34,9 +34,9 @@ pub struct GuestMemoryAtomic<M: GuestMemory> {
3434
inner: Arc<(ArcSwap<M>, Mutex<()>)>,
3535
}
3636

37-
impl<M: GuestMemory> From<Arc<M>> for GuestMemoryAtomic<M> {
37+
impl<M: IoMemory> From<Arc<M>> for GuestMemoryAtomic<M> {
3838
/// create a new `GuestMemoryAtomic` object whose initial contents come from
39-
/// the `map` reference counted `GuestMemory`.
39+
/// the `map` reference counted `IoMemory`.
4040
fn from(map: Arc<M>) -> Self {
4141
let inner = (ArcSwap::new(map), Mutex::new(()));
4242
GuestMemoryAtomic {
@@ -45,9 +45,9 @@ impl<M: GuestMemory> From<Arc<M>> for GuestMemoryAtomic<M> {
4545
}
4646
}
4747

48-
impl<M: GuestMemory> GuestMemoryAtomic<M> {
48+
impl<M: IoMemory> GuestMemoryAtomic<M> {
4949
/// create a new `GuestMemoryAtomic` object whose initial contents come from
50-
/// the `map` `GuestMemory`.
50+
/// the `map` `IoMemory`.
5151
pub fn new(map: M) -> Self {
5252
Arc::new(map).into()
5353
}
@@ -75,7 +75,7 @@ impl<M: GuestMemory> GuestMemoryAtomic<M> {
7575
}
7676
}
7777

78-
impl<M: GuestMemory> GuestAddressSpace for GuestMemoryAtomic<M> {
78+
impl<M: IoMemory> GuestAddressSpace for GuestMemoryAtomic<M> {
7979
type T = GuestMemoryLoadGuard<M>;
8080
type M = M;
8181

@@ -86,14 +86,14 @@ impl<M: GuestMemory> GuestAddressSpace for GuestMemoryAtomic<M> {
8686

8787
/// A guard that provides temporary access to a `GuestMemoryAtomic`. This
8888
/// object is returned from the `memory()` method. It dereference to
89-
/// a snapshot of the `GuestMemory`, so it can be used transparently to
89+
/// a snapshot of the `IoMemory`, so it can be used transparently to
9090
/// access memory.
9191
#[derive(Debug)]
92-
pub struct GuestMemoryLoadGuard<M: GuestMemory> {
92+
pub struct GuestMemoryLoadGuard<M: IoMemory> {
9393
guard: Guard<Arc<M>>,
9494
}
9595

96-
impl<M: GuestMemory> GuestMemoryLoadGuard<M> {
96+
impl<M: IoMemory> GuestMemoryLoadGuard<M> {
9797
/// Make a clone of the held pointer and returns it. This is more
9898
/// expensive than just using the snapshot, but it allows to hold on
9999
/// to the snapshot outside the scope of the guard. It also allows
@@ -104,15 +104,15 @@ impl<M: GuestMemory> GuestMemoryLoadGuard<M> {
104104
}
105105
}
106106

107-
impl<M: GuestMemory> Clone for GuestMemoryLoadGuard<M> {
107+
impl<M: IoMemory> Clone for GuestMemoryLoadGuard<M> {
108108
fn clone(&self) -> Self {
109109
GuestMemoryLoadGuard {
110110
guard: Guard::from_inner(Arc::clone(&*self.guard)),
111111
}
112112
}
113113
}
114114

115-
impl<M: GuestMemory> Deref for GuestMemoryLoadGuard<M> {
115+
impl<M: IoMemory> Deref for GuestMemoryLoadGuard<M> {
116116
type Target = M;
117117

118118
fn deref(&self) -> &Self::Target {
@@ -125,12 +125,12 @@ impl<M: GuestMemory> Deref for GuestMemoryLoadGuard<M> {
125125
/// possibly after updating the memory map represented by the
126126
/// `GuestMemoryAtomic` that created the guard.
127127
#[derive(Debug)]
128-
pub struct GuestMemoryExclusiveGuard<'a, M: GuestMemory> {
128+
pub struct GuestMemoryExclusiveGuard<'a, M: IoMemory> {
129129
parent: &'a GuestMemoryAtomic<M>,
130130
_guard: MutexGuard<'a, ()>,
131131
}
132132

133-
impl<M: GuestMemory> GuestMemoryExclusiveGuard<'_, M> {
133+
impl<M: IoMemory> GuestMemoryExclusiveGuard<'_, M> {
134134
/// Replace the memory map in the `GuestMemoryAtomic` that created the guard
135135
/// with the new memory map, `map`. The lock is then dropped since this
136136
/// method consumes the guard.

src/guest_memory.rs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ use crate::bitmap::{Bitmap, BS, MS};
5555
use crate::bytes::{AtomicAccess, Bytes};
5656
use crate::io::{ReadVolatile, WriteVolatile};
5757
use crate::volatile_memory::{self, VolatileSlice};
58+
use crate::{IoMemory, Permissions};
5859

5960
/// Errors associated with handling guest memory accesses.
6061
#[allow(missing_docs)]
@@ -354,7 +355,7 @@ pub trait GuestMemoryRegion: Bytes<MemoryRegionAddress, E = Error> {
354355
/// ```
355356
pub trait GuestAddressSpace {
356357
/// The type that will be used to access guest memory.
357-
type M: GuestMemory;
358+
type M: IoMemory;
358359

359360
/// A type that provides access to the memory.
360361
type T: Clone + Deref<Target = Self::M>;
@@ -365,7 +366,7 @@ pub trait GuestAddressSpace {
365366
fn memory(&self) -> Self::T;
366367
}
367368

368-
impl<M: GuestMemory> GuestAddressSpace for &M {
369+
impl<M: IoMemory> GuestAddressSpace for &M {
369370
type M = M;
370371
type T = Self;
371372

@@ -374,7 +375,7 @@ impl<M: GuestMemory> GuestAddressSpace for &M {
374375
}
375376
}
376377

377-
impl<M: GuestMemory> GuestAddressSpace for Rc<M> {
378+
impl<M: IoMemory> GuestAddressSpace for Rc<M> {
378379
type M = M;
379380
type T = Self;
380381

@@ -383,7 +384,7 @@ impl<M: GuestMemory> GuestAddressSpace for Rc<M> {
383384
}
384385
}
385386

386-
impl<M: GuestMemory> GuestAddressSpace for Arc<M> {
387+
impl<M: IoMemory> GuestAddressSpace for Arc<M> {
387388
type M = M;
388389
type T = Self;
389390

@@ -585,13 +586,14 @@ pub trait GuestMemory {
585586
}
586587
}
587588

588-
impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
589+
impl<T: IoMemory + ?Sized> Bytes<GuestAddress> for T {
589590
type E = Error;
590591

591592
fn write(&self, buf: &[u8], addr: GuestAddress) -> Result<usize> {
592593
self.try_access(
593594
buf.len(),
594595
addr,
596+
Permissions::Write,
595597
|offset, count, caddr, region| -> Result<usize> {
596598
region.write(&buf[offset..(offset + count)], caddr)
597599
},
@@ -602,6 +604,7 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
602604
self.try_access(
603605
buf.len(),
604606
addr,
607+
Permissions::Read,
605608
|offset, count, caddr, region| -> Result<usize> {
606609
region.read(&mut buf[offset..(offset + count)], caddr)
607610
},
@@ -669,9 +672,12 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
669672
where
670673
F: ReadVolatile,
671674
{
672-
self.try_access(count, addr, |_, len, caddr, region| -> Result<usize> {
673-
region.read_volatile_from(caddr, src, len)
674-
})
675+
self.try_access(
676+
count,
677+
addr,
678+
Permissions::Write,
679+
|_, len, caddr, region| -> Result<usize> { region.read_volatile_from(caddr, src, len) },
680+
)
675681
}
676682

677683
fn read_exact_volatile_from<F>(
@@ -697,11 +703,16 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
697703
where
698704
F: WriteVolatile,
699705
{
700-
self.try_access(count, addr, |_, len, caddr, region| -> Result<usize> {
701-
// For a non-RAM region, reading could have side effects, so we
702-
// must use write_all().
703-
region.write_all_volatile_to(caddr, dst, len).map(|()| len)
704-
})
706+
self.try_access(
707+
count,
708+
addr,
709+
Permissions::Read,
710+
|_, len, caddr, region| -> Result<usize> {
711+
// For a non-RAM region, reading could have side effects, so we
712+
// must use write_all().
713+
region.write_all_volatile_to(caddr, dst, len).map(|()| len)
714+
},
715+
)
705716
}
706717

707718
fn write_all_volatile_to<F>(&self, addr: GuestAddress, dst: &mut F, count: usize) -> Result<()>
@@ -724,6 +735,7 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
724735
let completed = self.try_access(
725736
expected,
726737
addr,
738+
Permissions::Write,
727739
|offset, len, region_addr, region| -> Result<usize> {
728740
assert_eq!(offset, 0);
729741
if len < expected {
@@ -753,6 +765,7 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
753765
let completed = self.try_access(
754766
expected,
755767
addr,
768+
Permissions::Read,
756769
|offset, len, region_addr, region| -> Result<usize> {
757770
assert_eq!(offset, 0);
758771
if len < expected {

0 commit comments

Comments
 (0)