[Rust-VMM] RFC v2: propose to host memory-model crate under the rust-vm project

Paolo Bonzini pbonzini at redhat.com
Mon Feb 11 11:05:39 UTC 2019


On 10/02/19 07:00, Liu, Jiang wrote:
> Hi all,
> I have posted the first version of memory-model crate under
> rust-vmm/memory-model, which breaks the repository inclusion process of
> the rust-vmm community. So I have created a personal GitHub repository
> (https://github.com/jiangliu/memory-model) for v2 and the
> rust-vmm/memory-model repository will be deleted soon. Sorry for the
> inconvenience!

A memory model crate is certainly a very good starting point for
rust-vmm, but it shouldn't include the implementation of the backend.
Instead, for rust-vmm we should focus on defining common traits that can
be used by any VMM.

In this light, GuestMemory is composed of two parts:

- a way to convert a GuestAddress to a MemoryMapping and an offset,
which can be a very simple MemoryMap trait:

    pub trait MemoryMap {
      fn do_in_region<F, T>(&self, guest_addr: GuestAddress,
                            size: usize, cb: F) -> Result<T>
      where
        F: FnOnce(&MemoryMapping, usize) -> Result<T>;

      fn do_in_region_partial<F>(&self, guest_addr: GuestAddress,
                                     cb: F) -> Result<usize>
      where
        F: FnOnce(&MemoryMapping, usize) -> Result<usize>;
   }

This can be implemented with linear lookup as is currently the case in
firecracker, or it could use a binary search or a radix tree.  rust-vmm
shouldn't care.

- the convenience API to access memory as slices/streams/objects. This
part of the API is shared by MemoryMapping and GuestMemory:

 // From MemoryMapping
 pub fn read_to_memory<F>(&self, mem_offset: usize, src: &mut F,
                          count: usize) -> Result<()>
    where F: Read;

 // From GuestMemory
 pub fn read_to_memory<F>(&self, guest_addr: GuestAddress,
                          src: &mut F, count: usize) -> Result<()>
    where F: Read;

sometimes with different names:

 // From MemoryMapping
 pub fn write_slice(&self, buf: &[u8], offset: usize) -> Result<usize>;
 pub fn read_obj<T: DataInit>(&self, offset: usize) -> Result<T>;

 // From GuestMemory
 pub fn write_slice_at_addr(&self, buf: &[u8], guest_addr: GuestAddress)
     -> Result<usize>;
 pub fn read_obj_from_addr<T: DataInit>(&self, guest_addr: GuestAddress)
-> Result<T>;

and should be a separate trait.

For example if we call it Bytes, MemoryMapping would implement
Bytes<usize> for MemoryMapping and GuestMemory would implement
Bytes<GuestAddress>:

  // O for offset
  pub trait Bytes<O> {
   type Error;

   fn read_to_memory<F>(&self, offset: O, src: &mut F,
                        count: usize) -> Result<(), Self::Error>
    where F: Read;
   fn read_obj<T: DataInit>(&self, offset: O) -> Result<T, Self::Error>;
   ...
   fn read_slice(&self, buf: &[u8], mem_offset: O) ->
     Result<usize, Self::Error>;
   ..
  }

endian.rs should be part of this crate too, so that you can write

   let x: LE<u32> = mem.read_obj(ofs);

AddressSpace is also too specialized and I would leave it out completely
from the time being, while GuestMemory and MemoryMapping could be
provided in a separate crate ("rust-vmm-examples"?) as a reference
implementation of the traits.

No objections from me of course on other parts of the crate, for example
VolatileMemory or DataInit.

Thanks,



More information about the Rust-vmm mailing list