Inter-VM Shared Memory

Overview

As Zephyr is enabled to run as a guest OS on Qemu and ACRN it might be necessary to make VMs aware of each other, or aware of the host. This is made possible by exposing a shared memory among parties via a feature called ivshmem, which stands for inter-VM Shared Memory.

The Two types are supported: a plain shared memory (ivshmem-plain) or a shared memory with the ability for a VM to generate an interruption on another, and thus to be interrupted as well itself (ivshmem-doorbell).

Please refer to the official Qemu ivshmem documentation for more information.

Support

Zephyr supports both version: plain and doorbell. Ivshmem driver can be build by enabling CONFIG_IVSHMEM. By default, this will expose the plain version. CONFIG_IVSHMEM_DOORBELL needs no be enabled to get the doorbell version.

Because the doorbell version uses MSI-X vectors to support notification vectors, the CONFIG_IVSHMEM_MSI_X_VECTORS has to be tweaked to the amount of vectors that will be needed.

Note that a tiny shell module can be exposed to test the ivshmem feature by enabling CONFIG_IVSHMEM_SHELL.

API Reference

group ivshmem

ivshmem reference API

Typedefs

typedef size_t (*ivshmem_get_mem_f)(const struct device *dev, uintptr_t *memmap)
typedef uint32_t (*ivshmem_get_id_f)(const struct device *dev)
typedef uint16_t (*ivshmem_get_vectors_f)(const struct device *dev)
typedef int (*ivshmem_int_peer_f)(const struct device *dev, uint32_t peer_id, uint16_t vector)
typedef int (*ivshmem_register_handler_f)(const struct device *dev, struct k_poll_signal *signal, uint16_t vector)

Functions

size_t ivshmem_get_mem(const struct device *dev, uintptr_t *memmap)

Get the inter-VM shared memory.

Return

the size of the memory mapped, or 0

Parameters
  • dev: Pointer to the device structure for the driver instance

  • memmap: A pointer to fill in with the memory address

uint32_t ivshmem_get_id(const struct device *dev)

Get our VM ID.

Return

our VM ID or 0 if we are not running on doorbell version

Parameters
  • dev: Pointer to the device structure for the driver instance

uint16_t ivshmem_get_vectors(const struct device *dev)

Get the number of interrupt vectors we can use.

Return

the number of available interrupt vectors

Parameters
  • dev: Pointer to the device structure for the driver instance

int ivshmem_int_peer(const struct device *dev, uint32_t peer_id, uint16_t vector)

Interrupt another VM.

Return

0 on success, a negative errno otherwise

Parameters
  • dev: Pointer to the device structure for the driver instance

  • peer_id: The VM ID to interrupt

  • vector: The interrupt vector to use

int ivshmem_register_handler(const struct device *dev, struct k_poll_signal *signal, uint16_t vector)

Register a vector notification (interrupt) handler.

Note: The returned status, if positive, to a raised signal is the vector that generated the signal. This lets the possibility to the user to have one signal for all vectors, or one per-vector.

Parameters
  • dev: Pointer to the device structure for the driver instance

  • signal: A pointer to a valid and ready to be signaled struct k_poll_signal. Or NULL to unregister any handler registered for the given vector.

  • vector: The interrupt vector to get notification from

Return

0 on success, a negative errno otherwise

struct ivshmem_driver_api
#include <ivshmem.h>