rust-vmm/vm-memory

Iron out the GuestMemory interface

alexandruag opened this issue · 0 comments

We should clarify some aspects of the GuestMemory interface, and a good starting point is around atomicity semantics. As Gerry mentioned in this comment, there are a couple of ways to do an atomic access, but I think all of them have some downsides right now.

get_atomic_ref/array_ref are a bit unwieldy, but more important, they're only available when the address falls within a guest region that's backed by host memory. This means that users of generic M: GuestMemory objects must either add a fallback code path, or rely exclusively on read/write_obj.

The main issue with read/write_obj is they don't have well-defined semantics at the interface level. One simple contract we could go for is "read/write_obj provide atomic accesses for certain sizes at aligned memory locations" (with the caveat that different archs provide atomicity guarantees up to different widths). A more verbose (but clearer and overall safer IMO) alternative is to expand the interface around read/write_obj to something like the following pseudocode:

// A type (easily convertible to/from GuestAddress) which guarantees the
// inner value is aligned with respect to T.
pub struct AlignedGuestAddress<T>(/*...*/);

// Just a marker.
pub unsafe trait AtomicAccess: ByteValued { }

impl GuestMemory {
    // ...

    // Always atomic!
    fn read_atomic<T: AtomicAccess>(addr: AlignedGuestAddress<T>) -> Result<T>;

    // The next two methods are not guaranteed to be atomic.
    fn read_obj<T: ByteValued>(addr: AlignedGuestAddress<T>) -> Result<T>;

    fn read_obj_unaligned<T: ByteValued>(addr: GuestAddress) -> Result<T>;

    // Similar for write ...
}

I think adding something like AlignedGuestAddress is a useful abstraction, because many implementations (i.e. device model building blocks) provide/demand alignment guarantees for certain addresses, and it makes sense to explicitly leverage the additional information or model the extra requirement. It also helps with making operation semantics more explicit.

WDYT?