Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iron out the GuestMemory interface #102

Open
alexandruag opened this issue Jul 15, 2020 · 0 comments
Open

Iron out the GuestMemory interface #102

alexandruag opened this issue Jul 15, 2020 · 0 comments

Comments

@alexandruag
Copy link
Collaborator

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant