pub trait MemoryMapper: Send {
    // Required methods
    fn add_map(&mut self, new_map: MappingInfo) -> Result<AddMapResult>;
    fn remove_map(
        &mut self,
        iova_start: u64,
        size: u64
    ) -> Result<RemoveMapResult>;
    fn get_mask(&self) -> Result<u64>;
    fn supports_detach(&self) -> bool;
    fn id(&self) -> u32;

    // Provided methods
    fn reset_domain(&mut self) -> Option<EventAsync> { ... }
    fn start_export_session(&mut self, _ex: &Executor) -> Result<Event> { ... }
    unsafe fn vfio_dma_map(
        &mut self,
        _iova: u64,
        _hva: u64,
        _size: u64,
        _prot: Protection
    ) -> Result<AddMapResult> { ... }
    fn export(&mut self, _iova: u64, _size: u64) -> Result<Vec<MemRegion>> { ... }
    fn release(&mut self, _iova: u64, _size: u64) -> Result<()> { ... }
}
Expand description

A generic interface for vfio and other iommu backends

This interface includes APIs to supports allowing clients within crosvm (e.g. the VVU proxy) which are configured to sit behind a virtio-iommu device to access memory via IO virtual address (IOVA). This is done by exporting mapped memory to the client. The virtio-iommu device can manage many mappers simultaneously. The current implementation has a 1-to-1 relationship between mappers and clients, although this may be extended to 1-to-N to fully support the virtio-iommu API.

Clients must only access memory while it is mapped into the virtio-iommu device. As such, this interface has a concept of an “IOMMU fault”. An IOMMU fault is triggered when the guest removes a mapping that includes memory that is exported but not yet released. This includes if |reset_domain| is called while any memory is exported. When an IOMMU fault occurs, the event returned by |start_export_session| is signaled, and the client must immediately release any exported memory.

From the virtio-iommu’s perspective, if |remove_map| or |reset_domain| triggers an IOMMU fault, then an eventfd will be returned. It must wait on that event until all exported regions have been released, at which point it can complete the virtio request that triggered the fault.

As such, the flow of a fault is:

  1. The guest sends an virtio-iommu message that triggers a fault. Faults can be triggered by unmap or detach messages, or by attach messages if such messages are re-attaching an endpoint to a new domain. One example of a guest event that can trigger such a message is a userspace VVU device process crashing and triggering the guest kernel to re-attach the VVU device to the null endpoint.
  2. The viommu device removes an exported mapping from the mapper.
  3. The mapper signals the IOMMU fault eventfd and returns the fault resolution event to the viommu device.
  4. The viommu device starts waiting on the fault resolution event. Note that although the viommu device and mapper are both running on the same executor, this wait is async. This means that although further processing of virtio-iommu requests is paused, the mapper continues to run.
  5. The client receives the IOMMU fault.
  6. The client releases all exported regions.
  7. Once the mapper receives the final release message from the client, it signals the fault resolution event that the viommu device is waiting on.
  8. The viommu device finishes processing the original virtio iommu request and sends a reply to the guest.

Required Methods§

source

fn add_map(&mut self, new_map: MappingInfo) -> Result<AddMapResult>

Creates a new mapping. If the mapping overlaps with an existing mapping, return Ok(false).

source

fn remove_map(&mut self, iova_start: u64, size: u64) -> Result<RemoveMapResult>

Removes all mappings within the specified range.

source

fn get_mask(&self) -> Result<u64>

source

fn supports_detach(&self) -> bool

Whether or not endpoints can be safely detached from this mapper.

source

fn id(&self) -> u32

Gets an identifier for the MemoryMapper instance. Must be unique among instances of the same trait implementation.

Provided Methods§

source

fn reset_domain(&mut self) -> Option<EventAsync>

Resets the mapper’s domain back into its initial state. Only necessary if |supports_detach| returns true.

source

fn start_export_session(&mut self, _ex: &Executor) -> Result<Event>

Starts an export session with the mapper.

Returns an event which is signaled if exported memory is unmapped (i.e. if a fault occurs). Once a fault occurs, no new regions may be exported for that session. The client must watch for this event and immediately release all exported regions.

Only one session can be active at a time. A new session can only be created if the previous session has no remaining exported regions.

source

unsafe fn vfio_dma_map( &mut self, _iova: u64, _hva: u64, _size: u64, _prot: Protection ) -> Result<AddMapResult>

Exports the specified IO region.

§Safety

The memory in the region specified by hva and size must be memory external to rust.

source

fn export(&mut self, _iova: u64, _size: u64) -> Result<Vec<MemRegion>>

Multiple MemRegions should be returned when the gpa is discontiguous or perms are different.

source

fn release(&mut self, _iova: u64, _size: u64) -> Result<()>

Releases a previously exported region.

If a given IO region is exported multiple times, it must be released multiple times.

Implementors§