Device Model APIs

This section contains APIs for the SOS Device Model services. Sources for the Device Model are found in the ACRN Device Model GitHub repo

group acrn_virtio

virtio API

vhost APIs

APIs for virtio backend in kernel module.

Defines

VRING_ALIGN
ACRN_VRING_DESC_F_NEXT
ACRN_VRING_DESC_F_WRITE
ACRN_VRING_DESC_F_INDIRECT
ACRN_VRING_AVAIL_F_NO_INTERRUPT
ACRN_VRING_USED_F_NO_NOTIFY
VRING_PAGE_BITS
VIRTIO_TYPE_NET
VIRTIO_TYPE_BLOCK
VIRTIO_TYPE_CONSOLE
VIRTIO_TYPE_ENTROPY
VIRTIO_TYPE_BALLOON
VIRTIO_TYPE_IOMEMORY
VIRTIO_TYPE_RPMSG
VIRTIO_TYPE_SCSI
VIRTIO_TYPE_9P
VIRTIO_TYPE_INPUT
VIRTIO_TYPE_RPMB
VIRTIO_TYPE_HECI
VIRTIO_TYPE_AUDIO
VIRTIO_TYPE_IPU
VIRTIO_TYPE_TSN
VIRTIO_TYPE_HYPERDMABUF
VIRTIO_TYPE_HDCP
VIRTIO_TYPE_COREU
INTEL_VENDOR_ID
VIRTIO_VENDOR
VIRTIO_DEV_NET
VIRTIO_DEV_BLOCK
VIRTIO_DEV_CONSOLE
VIRTIO_DEV_RANDOM
VIRTIO_DEV_RPMB
VIRTIO_DEV_HECI
VIRTIO_DEV_AUDIO
VIRTIO_DEV_IPU
VIRTIO_DEV_TSN
VIRTIO_DEV_HYPERDMABUF
VIRTIO_DEV_HDCP
VIRTIO_DEV_COREU
VIRTIO_CR_HOSTCAP
VIRTIO_CR_GUESTCAP
VIRTIO_CR_PFN
VIRTIO_CR_QNUM
VIRTIO_CR_QSEL
VIRTIO_CR_QNOTIFY
VIRTIO_CR_STATUS
VIRTIO_CR_ISR
VIRTIO_CR_CFGVEC
VIRTIO_CR_QVEC
VIRTIO_CR_CFG0
VIRTIO_CR_CFG1
VIRTIO_CR_MSIX
VIRTIO_CR_STATUS_ACK
VIRTIO_CR_STATUS_DRIVER
VIRTIO_CR_STATUS_DRIVER_OK
VIRTIO_CR_STATUS_FEATURES_OK
VIRTIO_CR_STATUS_NEEDS_RESET
VIRTIO_CR_STATUS_FAILED
VIRTIO_CR_ISR_QUEUES
VIRTIO_CR_ISR_CONF_CHANGED
VIRTIO_MSI_NO_VECTOR
ACRN_VIRTIO_F_NOTIFY_ON_EMPTY
ACRN_VIRTIO_RING_F_INDIRECT_DESC
ACRN_VIRTIO_RING_F_EVENT_IDX
ACRN_VIRTIO_F_VERSION_1
VIRTIO_USE_MSIX
VIRTIO_EVENT_IDX
VIRTIO_BROKED
VIRTIO_LEGACY_PIO_BAR_IDX
VIRTIO_MODERN_PIO_BAR_IDX
VIRTIO_MODERN_MMIO_BAR_IDX
VIRTIO_CAP_COMMON_OFFSET
VIRTIO_CAP_COMMON_SIZE
VIRTIO_CAP_ISR_OFFSET
VIRTIO_CAP_ISR_SIZE
VIRTIO_CAP_DEVICE_OFFSET
VIRTIO_CAP_DEVICE_SIZE
VIRTIO_CAP_NOTIFY_OFFSET
VIRTIO_CAP_NOTIFY_SIZE
VIRTIO_MODERN_MEM_BAR_SIZE
VIRTIO_MODERN_NOTIFY_OFF_MULT
VIRTIO_PCI_CAP_COMMON_CFG
VIRTIO_PCI_CAP_NOTIFY_CFG
VIRTIO_PCI_CAP_ISR_CFG
VIRTIO_PCI_CAP_DEVICE_CFG
VIRTIO_PCI_CAP_PCI_CFG
VIRTIO_COMMON_DFSELECT
VIRTIO_COMMON_DF
VIRTIO_COMMON_GFSELECT
VIRTIO_COMMON_GF
VIRTIO_COMMON_MSIX
VIRTIO_COMMON_NUMQ
VIRTIO_COMMON_STATUS
VIRTIO_COMMON_CFGGENERATION
VIRTIO_COMMON_Q_SELECT
VIRTIO_COMMON_Q_SIZE
VIRTIO_COMMON_Q_MSIX
VIRTIO_COMMON_Q_ENABLE
VIRTIO_COMMON_Q_NOFF
VIRTIO_COMMON_Q_DESCLO
VIRTIO_COMMON_Q_DESCHI
VIRTIO_COMMON_Q_AVAILLO
VIRTIO_COMMON_Q_AVAILHI
VIRTIO_COMMON_Q_USEDLO
VIRTIO_COMMON_Q_USEDHI
VIRTIO_BASE_LOCK(vb)
VIRTIO_BASE_UNLOCK(vb)
VQ_ALLOC
VQ_BROKED
VQ_AVAIL_EVENT_IDX(vq)
VQ_USED_EVENT_IDX(vq)
VIRTIO_SUCCESS
VIRTIO_ERROR_REENTER
VIRTIO_ERROR_FD_OPEN_FAILED
VIRTIO_ERROR_MEM_ALLOC_FAILED
VIRTIO_ERROR_START
VIRTIO_ERROR_GENERAL

Enums

enum VBS_K_STATUS

Values:

VIRTIO_DEV_INITIAL = 1
VIRTIO_DEV_PRE_INIT
VIRTIO_DEV_INIT_FAILED
VIRTIO_DEV_INIT_SUCCESS
VIRTIO_DEV_START_FAILED
VIRTIO_DEV_STARTED

Functions

static size_t virtio_vring_size(u_int qsz)

Calculate size of a virtual ring, this interface is only valid for legacy virtio.

Return
size of a certain virtqueue, in bytes.
Parameters
  • qsz: Size of raw data in a certain virtqueue.

static int vq_ring_ready(struct virtio_vq_info *vq)

Is this ring ready for I/O?

Return
0 on not ready and 1 on ready.
Parameters

static int vq_has_descs(struct virtio_vq_info *vq)

Are there “available” descriptors?

This does not count how many, just returns 1 if there is any.

Return
0 on no available and 1 on available.
Parameters

static void vq_interrupt(struct virtio_base *vb, struct virtio_vq_info *vq)

Deliver an interrupt to guest on the given virtqueue.

The interrupt could be MSI-X or a generic MSI interrupt.

Return
NULL
Parameters

static void virtio_config_changed(struct virtio_base *vb)

Deliver an config changed interrupt to guest.

MSI-X or a generic MSI interrupt with config changed event.

Return
NULL.
Parameters

void virtio_linkup(struct virtio_base *base, struct virtio_ops *vops, void *pci_virtio_dev, struct pci_vdev *dev, struct virtio_vq_info *queues)

Link a virtio_base to its constants, the virtio device, and the PCI emulation.

Return
NULL
Parameters
  • base: Pointer to struct virtio_base.
  • vops: Pointer to struct virtio_ops.
  • pci_virtio_dev: Pointer to instance of certain virtio device.
  • dev: Pointer to struct pci_vdev which emulates a PCI device.
  • queues: Pointer to struct virtio_vq_info, normally an array.

int virtio_interrupt_init(struct virtio_base *base, int use_msix)

Initialize MSI-X vector capabilities if we’re to use MSI-X, or MSI capabilities if not.

Wrapper function for virtio_intr_init() for cases we directly use BAR 1 for MSI-X capabilities.

Return
0 on success and non-zero on fail.
Parameters
  • base: Pointer to struct virtio_base.
  • use_msix: If using MSI-X.

int virtio_intr_init(struct virtio_base *base, int barnum, int use_msix)

Initialize MSI-X vector capabilities if we’re to use MSI-X, or MSI capabilities if not.

We assume we want one MSI-X vector per queue, here, plus one for the config vec.

Return
0 on success and non-zero on fail.
Parameters
  • base: Pointer to struct virtio_base.
  • barnum: Which BAR[0..5] to use.
  • use_msix: If using MSI-X.

void virtio_reset_dev(struct virtio_base *base)

Reset device (device-wide).

This erases all queues, i.e., all the queues become invalid. But we don’t wipe out the internal pointers, by just clearing the VQ_ALLOC flag.

It resets negotiated features to “none”. If MSI-X is enabled, this also resets all the vectors to NO_VECTOR.

Return
N/A
Parameters

void virtio_set_io_bar(struct virtio_base *base, int barnum)

Set I/O BAR (usually 0) to map PCI config registers.

Return
N/A
Parameters
  • base: Pointer to struct virtio_base.
  • barnum: Which BAR[0..5] to use.

int vq_getchain(struct virtio_vq_info *vq, uint16_t *pidx, struct iovec *iov, int n_iov, uint16_t *flags)

Walk through the chain of descriptors involved in a request and put them into a given iov[] array.

Return
number of descriptors.
Parameters
  • vq: Pointer to struct virtio_vq_info.
  • pidx: Pointer to available ring position.
  • iov: Pointer to iov[] array prepared by caller.
  • n_iov: Size of iov[] array.
  • flags: Pointer to a uint16_t array which will contain flag of each descriptor.

void vq_retchain(struct virtio_vq_info *vq)

Return the currently-first request chain back to the available ring.

Return
N/A
Parameters

void vq_relchain(struct virtio_vq_info *vq, uint16_t idx, uint32_t iolen)

Return specified request chain to the guest, setting its I/O length to the provided value.

Return
N/A
Parameters
  • vq: Pointer to struct virtio_vq_info.
  • idx: Pointer to available ring position, returned by vq_getchain().
  • iolen: Number of data bytes to be returned to frontend.

void vq_endchains(struct virtio_vq_info *vq, int used_all_avail)

Driver has finished processing “available” chains and calling vq_relchain on each one.

If driver used all the available chains, used_all_avail need to be set to 1.

Return
N/A
Parameters
  • vq: Pointer to struct virtio_vq_info.
  • used_all_avail: Flag indicating if driver used all available chains.

uint64_t virtio_pci_read(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, int baridx, uint64_t offset, int size)

Handle PCI configuration space reads.

Handle virtio standard register reads, and dispatch other reads to actual virtio device driver.

Return
register value.
Parameters
  • ctx: Pointer to struct vmctx representing VM context.
  • vcpu: VCPU ID.
  • dev: Pointer to struct pci_vdev which emulates a PCI device.
  • baridx: Which BAR[0..5] to use.
  • offset: Register offset in bytes within a BAR region.
  • size: Access range in bytes.

void virtio_pci_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, int baridx, uint64_t offset, int size, uint64_t value)

Handle PCI configuration space writes.

Handle virtio standard register writes, and dispatch other writes to actual virtio device driver.

Return
N/A
Parameters
  • ctx: Pointer to struct vmctx representing VM context.
  • vcpu: VCPU ID.
  • dev: Pointer to struct pci_vdev which emulates a PCI device.
  • baridx: Which BAR[0..5] to use.
  • offset: Register offset in bytes within a BAR region.
  • size: Access range in bytes.
  • value: Data value to be written into register.

void virtio_dev_error(struct virtio_base *base)

Indicate the device has experienced an error.

This is called when the device has experienced an error from which it cannot re-cover. DEVICE_NEEDS_RESET is set to the device status register and a config change intr is sent to the guest driver.

Return
N/A
Parameters

int virtio_set_modern_bar(struct virtio_base *base, bool use_notify_pio)

Set modern BAR (usually 4) to map PCI config registers.

Set modern MMIO BAR (usually 4) to map virtio 1.0 capabilities and optional set modern PIO BAR (usually 2) to map notify capability. This interface is only valid for modern virtio.

Return
0 on success and non-zero on fail.
Parameters
  • base: Pointer to struct virtio_base.
  • use_notify_pio: Whether use pio for notify capability.

int virtio_pci_modern_cfgread(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, int coff, int bytes, uint32_t *rv)

Handle PCI configuration space reads.

Handle virtio PCI configuration space reads. Only the specific registers that need speical operation are handled in this callback. For others just fallback to pci core. This interface is only valid for virtio modern.

Return
0 on handled and non-zero on non-handled.
Parameters
  • ctx: Pointer to struct vmctx representing VM context.
  • vcpu: VCPU ID.
  • dev: Pointer to struct pci_vdev which emulates a PCI device.
  • coff: Register offset in bytes within PCI configuration space.
  • bytes: Access range in bytes.
  • rv: The value returned as read.

int virtio_pci_modern_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, int coff, int bytes, uint32_t val)

Handle PCI configuration space writes.

Handle virtio PCI configuration space writes. Only the specific registers that need speical operation are handled in this callback. For others just fallback to pci core. This interface is only valid for virtio modern.

Return
0 on handled and non-zero on non-handled.
Parameters
  • ctx: Pointer to struct vmctx representing VM context.
  • vcpu: VCPU ID.
  • dev: Pointer to struct pci_vdev which emulates a PCI device.
  • coff: Register offset in bytes within PCI configuration space.
  • bytes: Access range in bytes.
  • val: The value to write.

int vbs_kernel_reset(int fd)

Virtio kernel module reset.

Return
0 on OK and non-zero on error.
Parameters
  • fd: File descriptor representing virtio backend in kernel module.

int vbs_kernel_start(int fd, struct vbs_dev_info *dev, struct vbs_vqs_info *vqs)

Virtio kernel module start.

Return
0 on OK and non-zero on error.
Parameters
  • fd: File descriptor representing virtio backend in kernel module.
  • dev: Pointer to struct vbs_dev_info.
  • vqs: Pointer to struct vbs_vqs_info.

int vbs_kernel_stop(int fd)

Virtio kernel module stop.

Return
0 on OK and non-zero on error.
Parameters
  • fd: File descriptor representing virtio backend in kernel module.

int vhost_dev_init(struct vhost_dev *vdev, struct virtio_base *base, int fd, int vq_idx, uint64_t vhost_features, uint64_t vhost_ext_features, uint32_t busyloop_timeout)

vhost_dev initialization.

This interface is called to initialize the vhost_dev. It must be called before the actual feature negotiation with the guest OS starts.

Return
0 on success and -1 on failure.
Parameters
  • vdev: Pointer to struct vhost_dev.
  • base: Pointer to struct virtio_base.
  • fd: fd of the vhost chardev.
  • vq_idx: The first virtqueue which would be used by this vhost dev.
  • vhost_features: Subset of vhost features which would be enabled.
  • vhost_ext_features: Specific vhost internal features to be enabled.
  • busyloop_timeout: Busy loop timeout in us.

int vhost_dev_deinit(struct vhost_dev *vdev)

vhost_dev cleanup.

This interface is called to cleanup the vhost_dev.

Return
0 on success and -1 on failure.
Parameters

int vhost_dev_start(struct vhost_dev *vdev)

start vhost data plane.

This interface is called to start the data plane in vhost.

Return
0 on success and -1 on failure.
Parameters

int vhost_dev_stop(struct vhost_dev *vdev)

stop vhost data plane.

This interface is called to stop the data plane in vhost.

Return
0 on success and -1 on failure.
Parameters

int vhost_net_set_backend(struct vhost_dev *vdev, int backend_fd)

set backend fd of vhost net.

This interface is called to set the backend fd (for example tap fd) to vhost.

Return
0 on success and -1 on failure.
Parameters
  • vdev: Pointer to struct vhost_dev.
  • backend_fd: fd of backend (for example tap fd).

struct virtio_desc
#include <virtio.h>

Public Members

uint64_t addr
uint32_t len
uint16_t flags
uint16_t next
struct virtio_used
#include <virtio.h>

Public Members

uint32_t idx
uint32_t tlen
struct virtio_vring_avail
#include <virtio.h>

Public Members

uint16_t flags
uint16_t idx
uint16_t ring[]
struct virtio_vring_used
#include <virtio.h>

Public Members

uint16_t flags
uint16_t idx
struct virtio_used ring[]
struct virtio_pci_common_cfg
#include <virtio.h>

Public Members

uint32_t device_feature_select
uint32_t device_feature
uint32_t guest_feature_select
uint32_t guest_feature
uint16_t msix_config
uint16_t num_queues
uint8_t device_status
uint8_t config_generation
uint16_t queue_select
uint16_t queue_size
uint16_t queue_msix_vector
uint16_t queue_enable
uint16_t queue_notify_off
uint32_t queue_desc_lo
uint32_t queue_desc_hi
uint32_t queue_avail_lo
uint32_t queue_avail_hi
uint32_t queue_used_lo
uint32_t queue_used_hi
struct virtio_pci_cap
#include <virtio.h>

Public Members

uint8_t cap_vndr
uint8_t cap_next
uint8_t cap_len
uint8_t cfg_type
uint8_t bar
uint8_t padding[3]
uint32_t offset
uint32_t length
struct virtio_pci_notify_cap
#include <virtio.h>

Public Members

struct virtio_pci_cap cap
uint32_t notify_off_multiplier
struct virtio_pci_cfg_cap
#include <virtio.h>

Public Members

struct virtio_pci_cap cap
uint8_t pci_cfg_data[4]
struct virtio_base
#include <virtio.h>

Base component to any virtio device.

Public Members

struct virtio_ops *vops

virtio operations

int flags

VIRTIO_* flags from above

pthread_mutex_t *mtx

POSIX mutex, if any

struct pci_vdev *dev

PCI device instance

uint64_t negotiated_caps

negotiated capabilities

uint64_t device_caps

device capabilities

struct virtio_vq_info *queues

one per nvq

int curq

current queue

uint8_t status

value from last status write

uint8_t isr

ISR flags, if not MSI-X

uint16_t msix_cfg_idx

MSI-X vector for config event

uint32_t legacy_pio_bar_idx

index of legacy pio bar

uint32_t modern_pio_bar_idx

index of modern pio bar

uint32_t modern_mmio_bar_idx

index of modern mmio bar

uint8_t config_generation

configuration generation

uint32_t device_feature_select

current selected device feature

uint32_t driver_feature_select

current selected guest feature

int cfg_coff

PCI cfg access capability offset

struct virtio_ops
#include <virtio.h>

Virtio specific operation functions for this type of virtio device.

Public Members

const char *name

name of driver (for diagnostics)

int nvq

number of virtual queues

size_t cfgsize

size of dev-specific config regs

void (*reset)(void *)

called on virtual device reset

void (*qnotify)(void *, struct virtio_vq_info *)

called on QNOTIFY if no VQ notify

int (*cfgread)(void *, int, int, uint32_t *)

to read config regs

int (*cfgwrite)(void *, int, int, uint32_t)

to write config regs

void (*apply_features)(void *, uint64_t)

to apply negotiated features

void (*set_status)(void *, uint64_t)

called to set device status

struct virtio_vq_info
#include <virtio.h>

Virtqueue data structure.

Data structure allocated (statically) per virtual queue.

Drivers may change qsize after a reset. When the guest OS requests a device reset, the hypervisor first calls vb->vo->reset(); then the data structure below is reinitialized (for each virtqueue: vb->vo->nvq).

The remaining fields should only be fussed-with by the generic code.

Note: the addresses of desc, avail, and vq_used are all computable from each other, but it’s a lot simpler if we just keep a pointer to each one. The event indices are similarly (but more easily) computable, and this time we’ll compute them: they’re just XX_ring[N].

Public Members

uint16_t qsize

size of this queue (a power of 2)

void (*notify)(void *, struct virtio_vq_info *)

called instead of notify, if not NULL

struct virtio_base *base

backpointer to virtio_base

uint16_t num

the num’th queue in the virtio_base

uint16_t flags

flags (see above)

uint16_t last_avail

a recent value of avail->idx

uint16_t save_used

saved used->idx; see vq_endchains

uint16_t msix_idx

MSI-X index, or VIRTIO_MSI_NO_VECTOR

uint32_t pfn

PFN of virt queue (not shifted!)

volatile struct virtio_desc *desc

descriptor array

volatile struct virtio_vring_avail *avail

the “avail” ring

volatile struct virtio_vring_used *used

the “used” ring

uint32_t gpa_desc[2]

gpa of descriptors

uint32_t gpa_avail[2]

gpa of avail_ring

uint32_t gpa_used[2]

gpa of used_ring

bool enabled

whether the virtqueue is enabled

struct vhost_vq
#include <vhost.h>

Public Members

int kick_fd

fd of kick eventfd

int call_fd

fd of call eventfd

int idx

index of this vq in vhost dev

struct mevent *mevp

mevent for call eventfd

struct vhost_dev *dev

pointer to vhost_dev

struct vhost_dev
#include <vhost.h>

Public Members

struct virtio_base *base

backpointer to virtio_base

struct vhost_vq *vqs

pointer to vhost_vq array

int nvqs

number of virtqueues

int fd

vhost chardev fd

int vq_idx

first vq’s index in virtio_vq_info

uint64_t vhost_features

supported virtio defined features

uint64_t vhost_ext_features

vhost self-defined internal features bits used for communicate between vhost user-space and kernel-space modules

uint32_t busyloop_timeout

vq busyloop timeout in us

bool started

whether vhost is started