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 versions: plain and doorbell. Ivshmem driver can be built
by enabling CONFIG_IVSHMEM. By default, this will expose the plain
version. CONFIG_IVSHMEM_DOORBELL needs to 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 number 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.
ivshmem-v2
Zephyr also supports ivshmem-v2:
https://github.com/siemens/jailhouse/blob/master/Documentation/ivshmem-v2-specification.md
This is primarily used for IPC in the Jailhouse hypervisor (e.g. Inter-VM Shared Memory (ivshmem) Ethernet). It is also possible to use ivshmem-v2 without Jailhouse by building the Siemens fork of QEMU, and modifying the QEMU launch flags:
API Reference
Related code samples
- IVSHMEM doorbell
- Use Inter-VM Shared Memory to exchange messages between two processes running on different operating systems. 
- Inter-VM Shared Memory (ivshmem) Ethernet
- Communicate with another "cell" in the Jailhouse hypervisor using IVSHMEM Ethernet. 
- group ivshmem
- Inter-VM Shared Memory (ivshmem) reference API. - Typedefs - 
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. - Note: This API is not supported for ivshmem-v2, as the R/W and R/O areas may not be mapped contiguously. For ivshmem-v2, use the ivshmem_get_rw_mem_section, ivshmem_get_output_mem_section and ivshmem_get_state APIs to access the shared memory. - Parameters:
- dev – Pointer to the device structure for the driver instance 
- memmap – A pointer to fill in with the memory address 
 
- Returns:
- the size of the memory mapped, or 0 
 
 - 
uint32_t ivshmem_get_id(const struct device *dev)
- Get our VM ID. - Parameters:
- dev – Pointer to the device structure for the driver instance 
 
- Returns:
- our VM ID or 0 if we are not running on doorbell version 
 
 - 
uint16_t ivshmem_get_vectors(const struct device *dev)
- Get the number of interrupt vectors we can use. - Parameters:
- dev – Pointer to the device structure for the driver instance 
 
- Returns:
- the number of available interrupt vectors 
 
 - 
int ivshmem_int_peer(const struct device *dev, uint32_t peer_id, uint16_t vector)
- Interrupt another VM. - Parameters:
- dev – Pointer to the device structure for the driver instance 
- peer_id – The VM ID to interrupt 
- vector – The interrupt vector to use 
 
- Returns:
- 0 on success, a negative errno otherwise 
 
 - 
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 
 
- Returns:
- 0 on success, a negative errno otherwise 
 
 - 
struct ivshmem_driver_api
- #include <ivshmem.h>
 
- 
typedef int (*ivshmem_register_handler_f)(const struct device *dev, struct k_poll_signal *signal, uint16_t vector)