From d261b4bce27428be3bcb1df7d136c22688aa87ed Mon Sep 17 00:00:00 2001 From: Shuo Liu Date: Mon, 29 Oct 2018 15:07:58 +0800 Subject: [PATCH] doc: update virtio related functions doc comments Update some virtio, VBS-K, vhost APIs documents. Tracked-On: #1595 Signed-off-by: Shuo Liu --- devicemodel/core/main.c | 9 + devicemodel/hw/pci/core.c | 30 +++ devicemodel/hw/pci/virtio/vhost.c | 54 ++++++ devicemodel/hw/pci/virtio/virtio.c | 148 +++++++++++++-- devicemodel/hw/pci/virtio/virtio_kernel.c | 25 ++- devicemodel/include/dm.h | 12 +- devicemodel/include/pci_core.h | 118 ++++++++++-- devicemodel/include/public/vhm_ioctl_defs.h | 72 +++---- devicemodel/include/vhost.h | 18 +- devicemodel/include/virtio.h | 28 +-- devicemodel/include/virtio_kernel.h | 36 +++- doc/acrn.doxyfile | 7 +- .../hld/hld-virtio-devices.rst | 179 +++++++++++++++++- 13 files changed, 647 insertions(+), 89 deletions(-) diff --git a/devicemodel/core/main.c b/devicemodel/core/main.c index ddc75e30e..96c46a657 100644 --- a/devicemodel/core/main.c +++ b/devicemodel/core/main.c @@ -209,6 +209,15 @@ pincpu_parse(const char *opt) return 0; } +/** + * @brief Convert guest physical address to host virtual address + * + * @param ctx Pointer to to struct vmctx representing VM context. + * @param gaddr Guest physical address base. + * @param len Guest physical address length. + * + * @return NULL on convert failed and host virtual address on successful. + */ void * paddr_guest2host(struct vmctx *ctx, uintptr_t gaddr, size_t len) { diff --git a/devicemodel/hw/pci/core.c b/devicemodel/hw/pci/core.c index 00044bfa9..14e4c2db1 100644 --- a/devicemodel/hw/pci/core.c +++ b/devicemodel/hw/pci/core.c @@ -1638,6 +1638,14 @@ pci_msix_enabled(struct pci_vdev *dev) return (dev->msix.enabled && !dev->msi.enabled); } +/** + * @brief Generate a MSI-X interrupt to guest + * + * @param dev Pointer to struct pci_vdev representing virtual PCI device. + * @param index MSIx table entry index. + * + * @return N/A + */ void pci_generate_msix(struct pci_vdev *dev, int index) { @@ -1659,6 +1667,14 @@ pci_generate_msix(struct pci_vdev *dev, int index) } } +/** + * @brief Generate a MSI interrupt to guest + * + * @param dev Pointer to struct pci_vdev representing virtual PCI device. + * @param index Message data index. + * + * @return N/A + */ void pci_generate_msi(struct pci_vdev *dev, int index) { @@ -1760,6 +1776,13 @@ pci_lintr_route(struct pci_vdev *dev) pci_set_cfgdata8(dev, PCIR_INTLINE, pirq_irq(ii->ii_pirq_pin)); } +/** + * @brief Assert INTx pin of virtual PCI device + * + * @param dev Pointer to struct pci_vdev representing virtual PCI device. + * + * @return N/A + */ void pci_lintr_assert(struct pci_vdev *dev) { @@ -1776,6 +1799,13 @@ pci_lintr_assert(struct pci_vdev *dev) pthread_mutex_unlock(&dev->lintr.lock); } +/** + * @brief Deassert INTx pin of virtual PCI device + * + * @param dev Pointer to struct pci_vdev representing virtual PCI device. + * + * @return N/A + */ void pci_lintr_deassert(struct pci_vdev *dev) { diff --git a/devicemodel/hw/pci/virtio/vhost.c b/devicemodel/hw/pci/virtio/vhost.c index 2973c1eb8..8bd7a48d7 100644 --- a/devicemodel/hw/pci/virtio/vhost.c +++ b/devicemodel/hw/pci/virtio/vhost.c @@ -581,6 +581,22 @@ vhost_set_mem_table(struct vhost_dev *vdev) return 0; } +/** + * @brief 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. + * + * @param vdev Pointer to struct vhost_dev. + * @param base Pointer to struct virtio_base. + * @param fd fd of the vhost chardev. + * @param vq_idx The first virtqueue which would be used by this vhost dev. + * @param vhost_features Subset of vhost features which would be enabled. + * @param vhost_ext_features Specific vhost internal features to be enabled. + * @param busyloop_timeout Busy loop timeout in us. + * + * @return 0 on success and -1 on failure. + */ int vhost_dev_init(struct vhost_dev *vdev, struct virtio_base *base, @@ -645,6 +661,15 @@ fail: return -1; } +/** + * @brief vhost_dev cleanup. + * + * This interface is called to cleanup the vhost_dev. + * + * @param vdev Pointer to struct vhost_dev. + * + * @return 0 on success and -1 on failure. + */ int vhost_dev_deinit(struct vhost_dev *vdev) { @@ -661,6 +686,15 @@ vhost_dev_deinit(struct vhost_dev *vdev) return 0; } +/** + * @brief start vhost data plane. + * + * This interface is called to start the data plane in vhost. + * + * @param vdev Pointer to struct vhost_dev. + * + * @return 0 on success and -1 on failure. + */ int vhost_dev_start(struct vhost_dev *vdev) { @@ -736,6 +770,15 @@ fail: return -1; } +/** + * @brief stop vhost data plane. + * + * This interface is called to stop the data plane in vhost. + * + * @param vdev Pointer to struct vhost_dev. + * + * @return 0 on success and -1 on failure. + */ int vhost_dev_stop(struct vhost_dev *vdev) { @@ -758,6 +801,17 @@ vhost_dev_stop(struct vhost_dev *vdev) return rc; } +/** + * @brief set backend fd of vhost net. + * + * This interface is called to set the backend fd (for example tap fd) + * to vhost. + * + * @param vdev Pointer to struct vhost_dev. + * @param backend_fd fd of backend (for example tap fd). + * + * @return 0 on success and -1 on failure. + */ int vhost_net_set_backend(struct vhost_dev *vdev, int backend_fd) { diff --git a/devicemodel/hw/pci/virtio/virtio.c b/devicemodel/hw/pci/virtio/virtio.c index c545cf324..4fd5c6326 100644 --- a/devicemodel/hw/pci/virtio/virtio.c +++ b/devicemodel/hw/pci/virtio/virtio.c @@ -45,9 +45,17 @@ */ #define DEV_STRUCT(vs) ((void *)(vs)) -/* - * Link a virtio_base to its constants, the virtio device, and - * the PCI emulation. +/** + * @brief Link a virtio_base to its constants, the virtio device, + * and the PCI emulation. + * + * @param base Pointer to struct virtio_base. + * @param vops Pointer to struct virtio_ops. + * @param pci_virtio_dev Pointer to instance of certain virtio device. + * @param dev Pointer to struct pci_vdev which emulates a PCI device. + * @param queues Pointer to struct virtio_vq_info, normally an array. + * + * @return NULL */ void virtio_linkup(struct virtio_base *base, struct virtio_ops *vops, @@ -69,14 +77,19 @@ virtio_linkup(struct virtio_base *base, struct virtio_ops *vops, } } -/* - * Reset device (device-wide). This erases all queues, i.e., - * all the queues become invalid (though we don't wipe out the - * internal pointers, we just clear the VQ_ALLOC flag). +/** + * @brief 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. + * + * @param base Pointer to struct virtio_base. + * + * @return N/A */ void virtio_reset_dev(struct virtio_base *base) @@ -114,8 +127,13 @@ virtio_reset_dev(struct virtio_base *base) base->config_generation = 0; } -/* - * Set I/O BAR (usually 0) to map PCI config registers. +/** + * @brief Set I/O BAR (usually 0) to map PCI config registers. + * + * @param base Pointer to struct virtio_base. + * @param barnum Which BAR[0..5] to use. + * + * @return N/A */ void virtio_set_io_bar(struct virtio_base *base, int barnum) @@ -131,12 +149,19 @@ virtio_set_io_bar(struct virtio_base *base, int barnum) base->legacy_pio_bar_idx = barnum; } -/* - * Initialize MSI-X vector capabilities if we're to use MSI-X, +/** + * @brief 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. + * + * + * @param base Pointer to struct virtio_base. + * @param barnum Which BAR[0..5] to use. + * @param use_msix If using MSI-X. + * + * @return 0 on success and non-zero on fail. */ int virtio_intr_init(struct virtio_base *base, int barnum, int use_msix) @@ -163,12 +188,17 @@ virtio_intr_init(struct virtio_base *base, int barnum, int use_msix) return 0; } -/* - * Initialize MSI-X vector capabilities if we're to use MSI-X, +/** + * @brief Initialize MSI-X vector capabilities if we're to use MSI-X, * or MSI capabilities if not. * - * Wrapper function for virtio_intr_init() since by default we - * will use bar 1 for MSI-X. + * Wrapper function for virtio_intr_init() for cases we directly use + * BAR 1 for MSI-X capabilities. + * + * @param base Pointer to struct virtio_base. + * @param use_msix If using MSI-X. + * + * @return 0 on success and non-zero on fail. */ int virtio_interrupt_init(struct virtio_base *base, int use_msix) @@ -1006,6 +1036,18 @@ virtio_set_modern_pio_bar(struct virtio_base *base, int barnum) return 0; } +/** + * @brief 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. + * + * @param base Pointer to struct virtio_base. + * @param use_notify_pio Whether use pio for notify capability. + * + * @return 0 on success and non-zero on fail. + */ int virtio_set_modern_bar(struct virtio_base *base, bool use_notify_pio) { @@ -1027,6 +1069,17 @@ virtio_set_modern_bar(struct virtio_base *base, bool use_notify_pio) return rc; } +/** + * @brief 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. + * + * @param base Pointer to struct virtio_base. + * + * @return N/A + */ void virtio_dev_error(struct virtio_base *base) { @@ -1604,6 +1657,21 @@ virtio_pci_modern_pio_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, pthread_mutex_unlock(base->mtx); } +/** + * @brief Handle PCI configuration space reads. + * + * Handle virtio standard register reads, and dispatch other reads to + * actual virtio device driver. + * + * @param ctx Pointer to struct vmctx representing VM context. + * @param vcpu VCPU ID. + * @param dev Pointer to struct pci_vdev which emulates a PCI device. + * @param baridx Which BAR[0..5] to use. + * @param offset Register offset in bytes within a BAR region. + * @param size Access range in bytes. + * + * @return register value. + */ uint64_t virtio_pci_read(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, int baridx, uint64_t offset, int size) @@ -1634,6 +1702,22 @@ virtio_pci_read(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, return size == 1 ? 0xff : size == 2 ? 0xffff : 0xffffffff; } +/** + * @brief Handle PCI configuration space writes. + * + * Handle virtio standard register writes, and dispatch other writes to + * actual virtio device driver. + * + * @param ctx Pointer to struct vmctx representing VM context. + * @param vcpu VCPU ID. + * @param dev Pointer to struct pci_vdev which emulates a PCI device. + * @param baridx Which BAR[0..5] to use. + * @param offset Register offset in bytes within a BAR region. + * @param size Access range in bytes. + * @param value Data value to be written into register. + * + * @return N/A + */ void virtio_pci_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, int baridx, uint64_t offset, int size, uint64_t value) @@ -1670,6 +1754,22 @@ virtio_pci_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, base->vops->name, baridx); } +/** + * @brief 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. + * + * @param ctx Pointer to struct vmctx representing VM context. + * @param vcpu VCPU ID. + * @param dev Pointer to struct pci_vdev which emulates a PCI device. + * @param coff Register offset in bytes within PCI configuration space. + * @param bytes Access range in bytes. + * @param rv The value returned as read. + * + * @return 0 on handled and non-zero on non-handled. + */ int virtio_pci_modern_cfgread(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, int coff, int bytes, uint32_t *rv) @@ -1719,6 +1819,22 @@ virtio_pci_modern_cfgread(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, return -1; } +/** + * @brief 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. + * + * @param ctx Pointer to struct vmctx representing VM context. + * @param vcpu VCPU ID. + * @param dev Pointer to struct pci_vdev which emulates a PCI device. + * @param coff Register offset in bytes within PCI configuration space. + * @param bytes Access range in bytes. + * @param val The value to write. + * + * @return 0 on handled and non-zero on non-handled. + */ int virtio_pci_modern_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, int coff, int bytes, uint32_t val) diff --git a/devicemodel/hw/pci/virtio/virtio_kernel.c b/devicemodel/hw/pci/virtio/virtio_kernel.c index ef3a35567..3dc60e220 100644 --- a/devicemodel/hw/pci/virtio/virtio_kernel.c +++ b/devicemodel/hw/pci/virtio/virtio_kernel.c @@ -28,7 +28,13 @@ vbs_vqs_info_set(int fd, void *arg) } /* VBS-K common ops */ -/* VBS-K reset */ +/** + * @brief Virtio kernel module reset. + * + * @param fd File descriptor representing virtio backend in kernel module. + * + * @return 0 on OK and non-zero on error. + */ int vbs_kernel_reset(int fd) { @@ -40,7 +46,15 @@ vbs_kernel_reset(int fd) * change the configuration of the virtio device after VBS-K has been * initialized. */ -/* VBS-K start/stop */ +/** + * @brief Virtio kernel module start. + * + * @param fd File descriptor representing virtio backend in kernel module. + * @param dev Pointer to struct vbs_dev_info. + * @param vqs Pointer to struct vbs_vqs_info. + * + * @return 0 on OK and non-zero on error. + */ int vbs_kernel_start(int fd, struct vbs_dev_info *dev, struct vbs_vqs_info *vqs) { @@ -66,6 +80,13 @@ vbs_kernel_start(int fd, struct vbs_dev_info *dev, struct vbs_vqs_info *vqs) return VIRTIO_SUCCESS; } +/** + * @brief Virtio kernel module stop. + * + * @param fd File descriptor representing virtio backend in kernel module. + * + * @return 0 on OK and non-zero on error. + */ int vbs_kernel_stop(int fd) { diff --git a/devicemodel/include/dm.h b/devicemodel/include/dm.h index 83be66072..28feb4663 100644 --- a/devicemodel/include/dm.h +++ b/devicemodel/include/dm.h @@ -45,7 +45,17 @@ extern bool stdio_in_use; int vmexit_task_switch(struct vmctx *ctx, struct vhm_request *vhm_req, int *vcpu); -void *paddr_guest2host(struct vmctx *ctx, uintptr_t addr, size_t len); + +/** + * @brief Convert guest physical address to host virtual address + * + * @param ctx Pointer to to struct vmctx representing VM context. + * @param gaddr Guest physical address base. + * @param len Guest physical address length. + * + * @return NULL on convert failed and host virtual address on successful. + */ +void *paddr_guest2host(struct vmctx *ctx, uintptr_t gaddr, size_t len); int virtio_uses_msix(void); void ptdev_no_reset(bool enable); void init_debugexit(void); diff --git a/devicemodel/include/pci_core.h b/devicemodel/include/pci_core.h index ba3aa3d89..eddaa94ff 100644 --- a/devicemodel/include/pci_core.h +++ b/devicemodel/include/pci_core.h @@ -252,10 +252,45 @@ int pci_emul_find_capability(struct pci_vdev *dev, uint8_t capid, int *p_capoff); int pci_emul_add_msicap(struct pci_vdev *pi, int msgnum); int pci_emul_add_pciecap(struct pci_vdev *pi, int pcie_device_type); -void pci_generate_msi(struct pci_vdev *pi, int msgnum); -void pci_generate_msix(struct pci_vdev *pi, int msgnum); -void pci_lintr_assert(struct pci_vdev *pi); -void pci_lintr_deassert(struct pci_vdev *pi); + +/** + * @brief Generate a MSI interrupt to guest + * + * @param dev Pointer to struct pci_vdev representing virtual PCI device. + * @param index Message data index. + * + * @return N/A + */ +void pci_generate_msi(struct pci_vdev *dev, int index); + +/** + * @brief Generate a MSI-X interrupt to guest + * + * @param dev Pointer to struct pci_vdev representing virtual PCI device. + * @param index MSIs table entry index. + * + * @return N/A + */ +void pci_generate_msix(struct pci_vdev *dev, int index); + +/** + * @brief Assert INTx pin of virtual PCI device + * + * @param dev Pointer to struct pci_vdev representing virtual PCI device. + * + * @return N/A + */ +void pci_lintr_assert(struct pci_vdev *dev); + +/** + * @brief Deassert INTx pin of virtual PCI device + * + * @param dev Pointer to struct pci_vdev representing virtual PCI device. + * + * @return N/A + */ +void pci_lintr_deassert(struct pci_vdev *dev); + void pci_lintr_request(struct pci_vdev *pi); void pci_lintr_release(struct pci_vdev *pi); int pci_msi_enabled(struct pci_vdev *pi); @@ -282,46 +317,97 @@ int check_gsi_sharing_violation(void); int pciaccess_init(void); void pciaccess_cleanup(void); +/** + * @brief Set virtual PCI device's configuration space in 1 byte width + * + * @param dev Pointer to struct pci_vdev representing virtual PCI device. + * @param offset Offset in configuration space. + * @param val Value in 1 byte. + * + * @return N/A + */ static inline void -pci_set_cfgdata8(struct pci_vdev *pi, int offset, uint8_t val) +pci_set_cfgdata8(struct pci_vdev *dev, int offset, uint8_t val) { assert(offset <= PCI_REGMAX); - *(uint8_t *)(pi->cfgdata + offset) = val; + *(uint8_t *)(dev->cfgdata + offset) = val; } +/** + * @brief Set virtual PCI device's configuration space in 2 bytes width + * + * @param dev Pointer to struct pci_vdev representing virtual PCI device. + * @param offset Offset in configuration space. + * @param val Value in 2 bytes. + * + * @return N/A + */ static inline void -pci_set_cfgdata16(struct pci_vdev *pi, int offset, uint16_t val) +pci_set_cfgdata16(struct pci_vdev *dev, int offset, uint16_t val) { assert(offset <= (PCI_REGMAX - 1) && (offset & 1) == 0); - *(uint16_t *)(pi->cfgdata + offset) = val; + *(uint16_t *)(dev->cfgdata + offset) = val; } +/** + * @brief Set virtual PCI device's configuration space in 4 bytes width + * + * @param dev Pointer to struct pci_vdev representing virtual PCI device. + * @param offset Offset in configuration space. + * @param val Value in 4 bytes. + * + * @return N/A + */ static inline void -pci_set_cfgdata32(struct pci_vdev *pi, int offset, uint32_t val) +pci_set_cfgdata32(struct pci_vdev *dev, int offset, uint32_t val) { assert(offset <= (PCI_REGMAX - 3) && (offset & 3) == 0); - *(uint32_t *)(pi->cfgdata + offset) = val; + *(uint32_t *)(dev->cfgdata + offset) = val; } +/** + * @brief Get virtual PCI device's configuration space in 1 byte width + * + * @param dev Pointer to struct pci_vdev representing virtual PCI device. + * @param offset Offset in configuration space. + * + * @return The configuration value in 1 byte. + */ static inline uint8_t -pci_get_cfgdata8(struct pci_vdev *pi, int offset) +pci_get_cfgdata8(struct pci_vdev *dev, int offset) { assert(offset <= PCI_REGMAX); - return (*(uint8_t *)(pi->cfgdata + offset)); + return (*(uint8_t *)(dev->cfgdata + offset)); } +/** + * @brief Get virtual PCI device's configuration space in 2 byte width + * + * @param dev Pointer to struct pci_vdev representing virtual PCI device. + * @param offset Offset in configuration space. + * + * @return The configuration value in 2 bytes. + */ static inline uint16_t -pci_get_cfgdata16(struct pci_vdev *pi, int offset) +pci_get_cfgdata16(struct pci_vdev *dev, int offset) { assert(offset <= (PCI_REGMAX - 1) && (offset & 1) == 0); - return (*(uint16_t *)(pi->cfgdata + offset)); + return (*(uint16_t *)(dev->cfgdata + offset)); } +/** + * @brief Get virtual PCI device's configuration space in 4 byte width + * + * @param dev Pointer to struct pci_vdev representing virtual PCI device. + * @param offset Offset in configuration space. + * + * @return The configuration value in 4 bytes. + */ static inline uint32_t -pci_get_cfgdata32(struct pci_vdev *pi, int offset) +pci_get_cfgdata32(struct pci_vdev *dev, int offset) { assert(offset <= (PCI_REGMAX - 3) && (offset & 3) == 0); - return (*(uint32_t *)(pi->cfgdata + offset)); + return (*(uint32_t *)(dev->cfgdata + offset)); } #endif /* _PCI_CORE_H_ */ diff --git a/devicemodel/include/public/vhm_ioctl_defs.h b/devicemodel/include/public/vhm_ioctl_defs.h index dda0d5894..03b24f35f 100644 --- a/devicemodel/include/public/vhm_ioctl_defs.h +++ b/devicemodel/include/public/vhm_ioctl_defs.h @@ -117,113 +117,117 @@ #define IC_EVENT_IRQFD _IC_ID(IC_ID, IC_ID_EVENT_BASE + 0x01) /** - * struct vm_memmap - EPT memory mapping info for guest + * @brief EPT memory mapping info for guest */ struct vm_memmap { - /** @type: memory mapping type */ + /** memory mapping type */ uint32_t type; - /** @using_vma: using vma_base to get vm0_gpa, + /** using vma_base to get vm0_gpa, * only for type == VM_MEMMAP_SYSMEM */ uint32_t using_vma; - /** @gpa: user OS guest physical start address of memory mapping */ + /** user OS guest physical start address of memory mapping */ uint64_t gpa; - /** union */ union { - /** @hpa: host physical start address of memory, + /** host physical start address of memory, * only for type == VM_MMIO */ uint64_t hpa; - /** @vma_base: service OS user virtual start address of + /** service OS user virtual start address of * memory, only for type == VM_MEMMAP_SYSMEM && * using_vma == true */ uint64_t vma_base; }; - /** @len: the length of memory range mapped */ + /** the length of memory range mapped */ uint64_t len; /* mmap length */ - /** @prot: memory mapping attribute */ + /** memory mapping attribute */ uint32_t prot; /* RWX */ }; /** - * struct ic_ptdev_irq - pass thru device irq data structure + * @brief pass thru device irq data structure */ struct ic_ptdev_irq { #define IRQ_INTX 0 #define IRQ_MSI 1 #define IRQ_MSIX 2 - /** @type: irq type */ + /** irq type */ uint32_t type; - /** @virt_bdf: virtual bdf description of pass thru device */ + /** virtual bdf description of pass thru device */ uint16_t virt_bdf; /* IN: Device virtual BDF# */ - /** @phy_bdf: physical bdf description of pass thru device */ + /** physical bdf description of pass thru device */ uint16_t phys_bdf; /* IN: Device physical BDF# */ - /** union */ union { - /** struct intx - info of IOAPIC/PIC interrupt */ + /** info of IOAPIC/PIC interrupt */ struct { - /** @virt_pin: virtual IOAPIC pin */ + /** virtual IOAPIC pin */ uint32_t virt_pin; - /** @phys_pin: physical IOAPIC pin */ + /** physical IOAPIC pin */ uint32_t phys_pin; - /** @pic_pin: PIC pin */ + /** PIC pin */ uint32_t is_pic_pin; } intx; - /** struct msix - info of MSI/MSIX interrupt */ + /** info of MSI/MSIX interrupt */ struct { /* Keep this filed on top of msix */ - /** @vector_cnt: vector count of MSI/MSIX */ + /** vector count of MSI/MSIX */ uint32_t vector_cnt; - /** @table_size: size of MSIX table(round up to 4K) */ + /** size of MSIX table(round up to 4K) */ uint32_t table_size; - /** @table_paddr: physical address of MSIX table */ + /** physical address of MSIX table */ uint64_t table_paddr; } msix; }; }; /** - * struct ioreq_notify - data strcture to notify hypervisor ioreq is handled - * - * @client_id: client id to identify ioreq client - * @vcpu: identify the ioreq submitter + * @brief data strcture to notify hypervisor ioreq is handled */ struct ioreq_notify { - int32_t client_id; - uint32_t vcpu; + /** client id to identify ioreq client */ + int32_t client_id; + /** identify the ioreq submitter */ + uint32_t vcpu; }; /** - * struct api_version - data structure to track VHM API version - * - * @major_version: major version of VHM API - * @minor_version: minor version of VHM API + * @brief data structure to track VHM API version */ struct api_version { + /** major version of VHM API */ uint32_t major_version; + /** minor version of VHM API */ uint32_t minor_version; }; +struct acrn_ioeventfd { #define ACRN_IOEVENTFD_FLAG_PIO 0x01 #define ACRN_IOEVENTFD_FLAG_DATAMATCH 0x02 #define ACRN_IOEVENTFD_FLAG_DEASSIGN 0x04 -struct acrn_ioeventfd { + /** file descriptor of the eventfd of this ioeventfd */ int32_t fd; + /** flag for ioeventfd ioctl */ uint32_t flags; + /** base address to be monitored */ uint64_t addr; + /** address length */ uint32_t len; uint32_t reserved; + /** data to be matched */ uint64_t data; }; -#define ACRN_IRQFD_FLAG_DEASSIGN 0x01 struct acrn_irqfd { +#define ACRN_IRQFD_FLAG_DEASSIGN 0x01 + /** file descriptor of the eventfd of this irqfd */ int32_t fd; + /** flag for irqfd ioctl */ uint32_t flags; + /** MSI interrupt to be injected */ struct acrn_msi_entry msi; }; #endif /* VHM_IOCTL_DEFS_H */ diff --git a/devicemodel/include/vhost.h b/devicemodel/include/vhost.h index 24172e282..4c4fba52f 100644 --- a/devicemodel/include/vhost.h +++ b/devicemodel/include/vhost.h @@ -5,12 +5,25 @@ * */ +/** + * @file vhost.h + * + * @brief VHOST APIs for ACRN Project + */ + #ifndef __VHOST_H__ #define __VHOST_H__ #include "virtio.h" #include "mevent.h" +/** + * @brief vhost APIs + * + * @addtogroup acrn_virtio + * @{ + */ + struct vhost_vq { int kick_fd; /**< fd of kick eventfd */ int call_fd; /**< fd of call eventfd */ @@ -71,7 +84,7 @@ struct vhost_dev { * @brief vhost_dev initialization. * * This interface is called to initialize the vhost_dev. It must be called - * before the actual feature negoitiation with the guest OS starts. + * before the actual feature negotiation with the guest OS starts. * * @param vdev Pointer to struct vhost_dev. * @param base Pointer to struct virtio_base. @@ -133,4 +146,7 @@ int vhost_dev_stop(struct vhost_dev *vdev); */ int vhost_net_set_backend(struct vhost_dev *vdev, int backend_fd); +/** + * @} + */ #endif diff --git a/devicemodel/include/virtio.h b/devicemodel/include/virtio.h index 60f06c4fb..5eb88a509 100644 --- a/devicemodel/include/virtio.h +++ b/devicemodel/include/virtio.h @@ -698,15 +698,15 @@ struct iovec; * @brief Link a virtio_base to its constants, the virtio device, * and the PCI emulation. * - * @param vb Pointer to struct virtio_base. - * @param vo Pointer to struct virtio_ops. + * @param base Pointer to struct virtio_base. + * @param vops Pointer to struct virtio_ops. * @param pci_virtio_dev Pointer to instance of certain virtio device. * @param dev Pointer to struct pci_vdev which emulates a PCI device. * @param queues Pointer to struct virtio_vq_info, normally an array. * * @return NULL */ -void virtio_linkup(struct virtio_base *vb, struct virtio_ops *vo, +void virtio_linkup(struct virtio_base *base, struct virtio_ops *vops, void *pci_virtio_dev, struct pci_vdev *dev, struct virtio_vq_info *queues); @@ -717,24 +717,27 @@ void virtio_linkup(struct virtio_base *vb, struct virtio_ops *vo, * Wrapper function for virtio_intr_init() for cases we directly use * BAR 1 for MSI-X capabilities. * - * @param vb Pointer to struct virtio_base. + * @param base Pointer to struct virtio_base. * @param use_msix If using MSI-X. * * @return 0 on success and non-zero on fail. */ -int virtio_interrupt_init(struct virtio_base *vb, int use_msix); +int virtio_interrupt_init(struct virtio_base *base, int use_msix); /** * @brief Initialize MSI-X vector capabilities if we're to use MSI-X, * or MSI capabilities if not. * - * @param vb Pointer to struct virtio_base. + * We assume we want one MSI-X vector per queue, here, plus one + * for the config vec. + * + * @param base Pointer to struct virtio_base. * @param barnum Which BAR[0..5] to use. * @param use_msix If using MSI-X. * * @return 0 on success and non-zero on fail. */ -int virtio_intr_init(struct virtio_base *vb, int barnum, int use_msix); +int virtio_intr_init(struct virtio_base *base, int barnum, int use_msix); /** * @brief Reset device (device-wide). @@ -743,21 +746,24 @@ int virtio_intr_init(struct virtio_base *vb, int barnum, int use_msix); * But we don't wipe out the internal pointers, by just clearing * the VQ_ALLOC flag. * - * @param vb Pointer to struct virtio_base. + * It resets negotiated features to "none". + * If MSI-X is enabled, this also resets all the vectors to NO_VECTOR. + * + * @param base Pointer to struct virtio_base. * * @return N/A */ -void virtio_reset_dev(struct virtio_base *vb); +void virtio_reset_dev(struct virtio_base *base); /** * @brief Set I/O BAR (usually 0) to map PCI config registers. * - * @param vb Pointer to struct virtio_base. + * @param base Pointer to struct virtio_base. * @param barnum Which BAR[0..5] to use. * * @return N/A */ -void virtio_set_io_bar(struct virtio_base *vb, int barnum); +void virtio_set_io_bar(struct virtio_base *base, int barnum); /** * @brief Walk through the chain of descriptors involved in a request diff --git a/devicemodel/include/virtio_kernel.h b/devicemodel/include/virtio_kernel.h index 3fe6646b8..5aa5c5f39 100644 --- a/devicemodel/include/virtio_kernel.h +++ b/devicemodel/include/virtio_kernel.h @@ -12,6 +12,13 @@ #include "vbs_common_if.h" /* data format between VBS-U & VBS-K */ +/** + * @brief APIs for virtio backend in kernel module + * + * @addtogroup acrn_virtio + * @{ + */ + enum VBS_K_STATUS { VIRTIO_DEV_INITIAL = 1, /* initial status */ VIRTIO_DEV_PRE_INIT, /* detected thru cmdline option */ @@ -30,12 +37,37 @@ enum VBS_K_STATUS { #define VIRTIO_ERROR_GENERAL 5 /* VBS-K common ops */ -/* VBS-K reset*/ +/** + * @brief Virtio kernel module reset. + * + * @param fd File descriptor representing virtio backend in kernel module. + * + * @return 0 on OK and non-zero on error. + */ int vbs_kernel_reset(int fd); -/* VBS-K start/stop */ +/** + * @brief Virtio kernel module start. + * + * @param fd File descriptor representing virtio backend in kernel module. + * @param dev Pointer to struct vbs_dev_info. + * @param vqs Pointer to struct vbs_vqs_info. + * + * @return 0 on OK and non-zero on error. + */ int vbs_kernel_start(int fd, struct vbs_dev_info *dev, struct vbs_vqs_info *vqs); + +/** + * @brief Virtio kernel module stop. + * + * @param fd File descriptor representing virtio backend in kernel module. + * + * @return 0 on OK and non-zero on error. + */ int vbs_kernel_stop(int fd); +/** + * @} + */ #endif diff --git a/doc/acrn.doxyfile b/doc/acrn.doxyfile index 8c7835d4c..be8926b69 100644 --- a/doc/acrn.doxyfile +++ b/doc/acrn.doxyfile @@ -812,7 +812,12 @@ INPUT = custom-doxygen/mainpage.md \ ../hypervisor/include/arch/x86/ioapic.h \ ../hypervisor/include/arch/x86/irq.h \ ../hypervisor/include/arch/x86/lapic.h \ - ../hypervisor/include/common/irq.h + ../hypervisor/include/common/irq.h \ + ../devicemodel/include/virtio_kernel.h \ + ../devicemodel/include/vhost.h \ + ../devicemodel/include/dm.h \ + ../devicemodel/include/pci_core.h \ + ../devicemodel/include/public/vhm_ioctl_defs.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/doc/developer-guides/hld/hld-virtio-devices.rst b/doc/developer-guides/hld/hld-virtio-devices.rst index 0d8da4194..296c154b1 100644 --- a/doc/developer-guides/hld/hld-virtio-devices.rst +++ b/doc/developer-guides/hld/hld-virtio-devices.rst @@ -383,13 +383,55 @@ common to all VBS-K modules, are the counterparts to preserve the related information. The related information is necessary to kernel-land vring service API helpers. +VHOST Key Data Structures +========================= + +The key data structures for vhost are listed as follows. + +.. doxygenstruct:: vhost_dev + :project: Project ACRN + +.. doxygenstruct:: vhost_vq + :project: Project ACRN + DM APIs ======= The DM APIs are exported by DM, and they should be used when realizing BE device drivers on ACRN. -[API Material from doxygen comments] +.. doxygenfunction:: paddr_guest2host + :project: Project ACRN + +.. doxygenfunction:: pci_set_cfgdata8 + :project: Project ACRN + +.. doxygenfunction:: pci_set_cfgdata16 + :project: Project ACRN + +.. doxygenfunction:: pci_set_cfgdata32 + :project: Project ACRN + +.. doxygenfunction:: pci_get_cfgdata8 + :project: Project ACRN + +.. doxygenfunction:: pci_get_cfgdata16 + :project: Project ACRN + +.. doxygenfunction:: pci_get_cfgdata32 + :project: Project ACRN + +.. doxygenfunction:: pci_lintr_assert + :project: Project ACRN + +.. doxygenfunction:: pci_lintr_deassert + :project: Project ACRN + +.. doxygenfunction:: pci_generate_msi + :project: Project ACRN + +.. doxygenfunction:: pci_generate_msix + :project: Project ACRN VBS APIs ======== @@ -404,7 +446,41 @@ VBS-U APIs These APIs provided by VBS-U are callbacks to be registered to DM, and the virtio framework within DM will invoke them appropriately. -[API Material from doxygen comments] +.. doxygenstruct:: virtio_ops + :project: Project ACRN + +.. doxygenfunction:: virtio_pci_read + :project: Project ACRN + +.. doxygenfunction:: virtio_pci_write + :project: Project ACRN + +.. doxygenfunction:: virtio_dev_error + :project: Project ACRN + +.. doxygenfunction:: virtio_interrupt_init + :project: Project ACRN + +.. doxygenfunction:: virtio_linkup + :project: Project ACRN + +.. doxygenfunction:: virtio_reset_dev + :project: Project ACRN + +.. doxygenfunction:: virtio_set_io_bar + :project: Project ACRN + +.. doxygenfunction:: virtio_set_modern_bar + :project: Project ACRN + +.. doxygenfunction:: virtio_pci_modern_cfgread + :project: Project ACRN + +.. doxygenfunction:: virtio_pci_modern_cfgwrite + :project: Project ACRN + +.. doxygenfunction:: virtio_config_changed + :project: Project ACRN VBS-K APIs ---------- @@ -415,12 +491,92 @@ the following APIs to implement their VBS-K modules. APIs provided by DM ~~~~~~~~~~~~~~~~~~~ -[API Material from doxygen comments] +.. doxygenfunction:: vbs_kernel_reset + :project: Project ACRN + +.. doxygenfunction:: vbs_kernel_start + :project: Project ACRN + +.. doxygenfunction:: vbs_kernel_stop + :project: Project ACRN APIs provided by VBS-K modules in service OS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -[API Material from doxygen comments] +.. kernel-doc:: include/linux/vbs/vbs.h + :functions: virtio_dev_init + virtio_dev_ioctl + virtio_vqs_ioctl + virtio_dev_register + virtio_dev_deregister + virtio_vqs_index_get + virtio_dev_reset + +VHOST APIS +========== + +APIs provided by DM +------------------- + +.. doxygenfunction:: vhost_dev_init + :project: Project ACRN + +.. doxygenfunction:: vhost_dev_deinit + :project: Project ACRN + +.. doxygenfunction:: vhost_dev_start + :project: Project ACRN + +.. doxygenfunction:: vhost_dev_stop + :project: Project ACRN + +Linux vhost IOCTLs +------------------ + +``#define VHOST_GET_FEATURES _IOR(VHOST_VIRTIO, 0x00, __u64)`` + This IOCTL is used to get the supported feature flags by vhost kernel driver. +``#define VHOST_SET_FEATURES _IOW(VHOST_VIRTIO, 0x00, __u64)`` + This IOCTL is used to set the supported feature flags to vhost kernel driver. +``#define VHOST_SET_OWNER _IO(VHOST_VIRTIO, 0x01)`` + This IOCTL is used to set current process as the exclusive owner of the vhost + char device. It must be called before any other vhost commands. +``#define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)`` + This IOCTL is used to give up the ownership of the vhost char device. +``#define VHOST_SET_MEM_TABLE _IOW(VHOST_VIRTIO, 0x03, struct vhost_memory)`` + This IOCTL is used to convey the guest OS memory layout to vhost kernel driver. +``#define VHOST_SET_VRING_NUM _IOW(VHOST_VIRTIO, 0x10, struct vhost_vring_state)`` + This IOCTL is used to set the number of descriptors in virtio ring. It cannot + be modified while the virtio ring is running. +``#define VHOST_SET_VRING_ADDR _IOW(VHOST_VIRTIO, 0x11, struct vhost_vring_addr)`` + This IOCTL is used to set the address of the virtio ring. +``#define VHOST_SET_VRING_BASE _IOW(VHOST_VIRTIO, 0x12, struct vhost_vring_state)`` + This IOCTL is used to set the base value where virtqueue looks for available + descriptors. +``#define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state)`` + This IOCTL is used to get the base value where virtqueue looks for available + descriptors. +``#define VHOST_SET_VRING_KICK _IOW(VHOST_VIRTIO, 0x20, struct vhost_vring_file)`` + This IOCTL is used to set the eventfd on which vhost can poll for guest + virtqueue kicks. +``#define VHOST_SET_VRING_CALL _IOW(VHOST_VIRTIO, 0x21, struct vhost_vring_file)`` + This IOCTL is used to set the eventfd which is used by vhost do inject + virtual interrupt. + +VHM eventfd IOCTLs +------------------ + +.. doxygenstruct:: acrn_ioeventfd + :project: Project ACRN + +``#define IC_EVENT_IOEVENTFD _IC_ID(IC_ID, IC_ID_EVENT_BASE + 0x00)`` + This IOCTL is used to register/unregister ioeventfd with appropriate address, + length and data value. + +.. doxygenstruct:: acrn_irqfd + :project: Project ACRN + +``#define IC_EVENT_IRQFD _IC_ID(IC_ID, IC_ID_EVENT_BASE + 0x01)`` + This IOCTL is used to register/unregister irqfd with appropriate MSI information. VQ APIs ======= @@ -433,7 +589,20 @@ to be identical between VBS-U and VBS-K, so that users don't need to learn different APIs when implementing BE drivers based on VBS-U and VBS-K. -[API Material from doxygen comments] +.. doxygenfunction:: vq_interrupt + :project: Project ACRN + +.. doxygenfunction:: vq_getchain + :project: Project ACRN + +.. doxygenfunction:: vq_retchain + :project: Project ACRN + +.. doxygenfunction:: vq_relchain + :project: Project ACRN + +.. doxygenfunction:: vq_endchains + :project: Project ACRN Below is an example showing a typical logic of how a BE driver handles requests from a FE driver.