Skip to content

Commit 45985f4

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 5b0e1ae commit 45985f4

File tree

2 files changed

+42
-30
lines changed

2 files changed

+42
-30
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 & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ use crate::bitmap::MS;
5555
use crate::bytes::{AtomicAccess, Bytes};
5656
use crate::io::{ReadVolatile, WriteVolatile};
5757
use crate::volatile_memory::{self, VolatileSlice};
58-
use crate::GuestMemoryRegion;
58+
use crate::{GuestMemoryRegion, IoMemory, Permissions};
5959

6060
/// Errors associated with handling guest memory accesses.
6161
#[allow(missing_docs)]
@@ -222,7 +222,7 @@ impl FileOffset {
222222
/// ```
223223
pub trait GuestAddressSpace {
224224
/// The type that will be used to access guest memory.
225-
type M: GuestMemory;
225+
type M: IoMemory;
226226

227227
/// A type that provides access to the memory.
228228
type T: Clone + Deref<Target = Self::M>;
@@ -233,7 +233,7 @@ pub trait GuestAddressSpace {
233233
fn memory(&self) -> Self::T;
234234
}
235235

236-
impl<M: GuestMemory> GuestAddressSpace for &M {
236+
impl<M: IoMemory> GuestAddressSpace for &M {
237237
type M = M;
238238
type T = Self;
239239

@@ -242,7 +242,7 @@ impl<M: GuestMemory> GuestAddressSpace for &M {
242242
}
243243
}
244244

245-
impl<M: GuestMemory> GuestAddressSpace for Rc<M> {
245+
impl<M: IoMemory> GuestAddressSpace for Rc<M> {
246246
type M = M;
247247
type T = Self;
248248

@@ -251,7 +251,7 @@ impl<M: GuestMemory> GuestAddressSpace for Rc<M> {
251251
}
252252
}
253253

254-
impl<M: GuestMemory> GuestAddressSpace for Arc<M> {
254+
impl<M: IoMemory> GuestAddressSpace for Arc<M> {
255255
type M = M;
256256
type T = Self;
257257

@@ -458,13 +458,14 @@ pub trait GuestMemory {
458458
}
459459
}
460460

461-
impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
461+
impl<T: IoMemory + ?Sized> Bytes<GuestAddress> for T {
462462
type E = Error;
463463

464464
fn write(&self, buf: &[u8], addr: GuestAddress) -> Result<usize> {
465465
self.try_access(
466466
buf.len(),
467467
addr,
468+
Permissions::Write,
468469
|offset, count, caddr, region| -> Result<usize> {
469470
region.write(&buf[offset..(offset + count)], caddr)
470471
},
@@ -475,6 +476,7 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
475476
self.try_access(
476477
buf.len(),
477478
addr,
479+
Permissions::Read,
478480
|offset, count, caddr, region| -> Result<usize> {
479481
region.read(&mut buf[offset..(offset + count)], caddr)
480482
},
@@ -542,9 +544,12 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
542544
where
543545
F: ReadVolatile,
544546
{
545-
self.try_access(count, addr, |_, len, caddr, region| -> Result<usize> {
546-
region.read_volatile_from(caddr, src, len)
547-
})
547+
self.try_access(
548+
count,
549+
addr,
550+
Permissions::Write,
551+
|_, len, caddr, region| -> Result<usize> { region.read_volatile_from(caddr, src, len) },
552+
)
548553
}
549554

550555
fn read_exact_volatile_from<F>(
@@ -570,11 +575,16 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
570575
where
571576
F: WriteVolatile,
572577
{
573-
self.try_access(count, addr, |_, len, caddr, region| -> Result<usize> {
574-
// For a non-RAM region, reading could have side effects, so we
575-
// must use write_all().
576-
region.write_all_volatile_to(caddr, dst, len).map(|()| len)
577-
})
578+
self.try_access(
579+
count,
580+
addr,
581+
Permissions::Read,
582+
|_, len, caddr, region| -> Result<usize> {
583+
// For a non-RAM region, reading could have side effects, so we
584+
// must use write_all().
585+
region.write_all_volatile_to(caddr, dst, len).map(|()| len)
586+
},
587+
)
578588
}
579589

580590
fn write_all_volatile_to<F>(&self, addr: GuestAddress, dst: &mut F, count: usize) -> Result<()>
@@ -597,6 +607,7 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
597607
let completed = self.try_access(
598608
expected,
599609
addr,
610+
Permissions::Write,
600611
|offset, len, region_addr, region| -> Result<usize> {
601612
assert_eq!(offset, 0);
602613
if len < expected {
@@ -626,6 +637,7 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
626637
let completed = self.try_access(
627638
expected,
628639
addr,
640+
Permissions::Read,
629641
|offset, len, region_addr, region| -> Result<usize> {
630642
assert_eq!(offset, 0);
631643
if len < expected {

0 commit comments

Comments
 (0)