Skip to content

Commit

Permalink
virtio: virtio-mmio framework
Browse files Browse the repository at this point in the history
VIRTIO MMIO transport for OpenAMP.

Signed-off-by: Dan Milea <dan.milea@windriver.com>
  • Loading branch information
Dan Milea committed Jul 20, 2023
1 parent 5891cb4 commit bbd278d
Show file tree
Hide file tree
Showing 9 changed files with 711 additions and 10 deletions.
6 changes: 6 additions & 0 deletions cmake/options.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ if (NOT WITH_VIRTIO_DEVICE AND NOT WITH_VIRTIO_SLAVE)
add_definitions(-DVIRTIO_DRIVER_ONLY)
endif (NOT WITH_VIRTIO_DEVICE AND NOT WITH_VIRTIO_SLAVE)

option (WITH_VIRTIO_MMIO_DRV "Build with virtio mmio driver support enabled" OFF)

if (WITH_VIRTIO_MMIO_DRV)
add_definitions(-DWITH_VIRTIO_MMIO_DRV)
endif (WITH_VIRTIO_MMIO_DRV)

option (WITH_DCACHE_VRINGS "Build with vrings cache operations enabled" OFF)

if (WITH_DCACHE_VRINGS)
Expand Down
3 changes: 3 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ collect (PROJECT_LIB_SOURCES version.c)
add_subdirectory (virtio)
add_subdirectory (rpmsg)
add_subdirectory (remoteproc)
if (WITH_VIRTIO_MMIO_DRV)
add_subdirectory (virtio_mmio)
endif (WITH_VIRTIO_MMIO_DRV)

if (WITH_PROXY)
add_subdirectory (proxy)
Expand Down
2 changes: 1 addition & 1 deletion lib/include/openamp/rpmsg_virtio.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device *rvdev,
vq_callback *callbacks)
{
return virtio_create_virtqueues(rvdev->vdev, flags, nvqs, names,
callbacks);
callbacks, NULL);
}

/**
Expand Down
69 changes: 62 additions & 7 deletions lib/include/openamp/virtio.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ __deprecated static inline int deprecated_virtio_dev_slave(void)
struct virtio_device_id {
uint32_t device;
uint32_t vendor;
uint32_t version;
};

/*
Expand All @@ -120,6 +121,44 @@ struct virtio_device_id {
#define VIRTIO_TRANSPORT_F_START 28
#define VIRTIO_TRANSPORT_F_END 32

#ifdef VIRTIO_DEBUG
#include <metal/log.h>

#define VIRTIO_ASSERT(_exp, _msg) do { \
if (!(_exp)) { \
metal_log(METAL_LOG_EMERGENCY, \
"FATAL: %s - " _msg, __func__); \
metal_assert(_exp); \
} \
} while (0)
#else
#define VIRTIO_ASSERT(_exp, _msg) metal_assert(_exp)
#endif /* VIRTIO_DEBUG */

#define VRING_ALIGNMENT 4096

#define VIRTIO_RING_SIZE(n, align) \
(( \
( \
sizeof(struct vring_desc) * n + \
sizeof(struct vring_avail) + \
sizeof(uint16_t) * (n + 1) + \
align - 1 \
) \
& ~(align - 1) \
) + \
sizeof(struct vring_used) + \
sizeof(struct vring_used_elem) * n + sizeof(uint16_t))

#define VRING_DECLARE(name, n, align) \
static char __vrbuf_##name[VIRTIO_RING_SIZE(n, align)] __aligned(VRING_ALIGNMENT); \
static struct vring __vring_##name = { \
.desc = (void *)__vrbuf_##name, \
.avail = (void *)((unsigned long)__vrbuf_##name + n * sizeof(struct vring_desc)), \
.used = (void *)((unsigned long)__vrbuf_##name + ((n * sizeof(struct vring_desc) + \
(n + 1) * sizeof(uint16_t) + align - 1) & ~(align - 1))), \
}

typedef void (*virtio_dev_reset_cb)(struct virtio_device *vdev);

struct virtio_dispatch;
Expand Down Expand Up @@ -180,7 +219,8 @@ struct virtio_dispatch {
int (*create_virtqueues)(struct virtio_device *vdev,
unsigned int flags,
unsigned int nvqs, const char *names[],
vq_callback callbacks[]);
vq_callback callbacks[],
void *callback_args[]);
void (*delete_virtqueues)(struct virtio_device *vdev);
uint8_t (*get_status)(struct virtio_device *dev);
void (*set_status)(struct virtio_device *dev, uint8_t status);
Expand All @@ -205,17 +245,18 @@ struct virtio_dispatch {
/**
* @brief Create the virtio device virtqueue.
*
* @param vdev Pointer to virtio device structure.
* @param flags Create flag.
* @param nvqs The virtqueue number.
* @param names Virtqueue names.
* @param callbacks Virtqueue callback functions.
* @param vdev Pointer to virtio device structure.
* @param flags Create flag.
* @param nvqs The virtqueue number.
* @param names Virtqueue names.
* @param callbacks Virtqueue callback functions.
* @param callback_args Virtqueue callback function arguments.
*
* @return 0 on success, otherwise error code.
*/
int virtio_create_virtqueues(struct virtio_device *vdev, unsigned int flags,
unsigned int nvqs, const char *names[],
vq_callback callbacks[]);
vq_callback callbacks[], void *callback_args[]);

/**
* @brief Delete the virtio device virtqueue.
Expand All @@ -236,6 +277,20 @@ static inline int virtio_delete_virtqueues(struct virtio_device *vdev)
return 0;
}

/**
* @brief Get device ID.
*
* @param dev Pointer to device structure.
*
* @return Device ID value.
*/
static inline uint32_t virtio_get_devid(const struct virtio_device *vdev)
{
if (!vdev)
return 0;
return vdev->id.device;
}

/**
* @brief Retrieve device status.
*
Expand Down
216 changes: 216 additions & 0 deletions lib/include/openamp/virtio_mmio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
/*
* Copyright (c) 2022 Wind River Systems, Inc.
* Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007
*
* SPDX-License-Identifier: BSD-3-Clause
*/

#ifndef OPENAMP_VIRTIO_MMIO_H
#define OPENAMP_VIRTIO_MMIO_H

#include <metal/device.h>
#include <openamp/virtio.h>
#include <openamp/virtqueue.h>

#ifdef __cplusplus
extern "C" {
#endif

/* Enable support for legacy devices */
#define VIRTIO_MMIO_LEGACY

/* Control registers */

/* Magic value ("virt" string) - Read Only */
#define VIRTIO_MMIO_MAGIC_VALUE 0x000

#define VIRTIO_MMIO_MAGIC_VALUE_STRING ('v' | ('i' << 8) | ('r' << 16) | ('t' << 24))

/* Virtio device version - Read Only */
#define VIRTIO_MMIO_VERSION 0x004

/* Virtio device ID - Read Only */
#define VIRTIO_MMIO_DEVICE_ID 0x008

/* Virtio vendor ID - Read Only */
#define VIRTIO_MMIO_VENDOR_ID 0x00c

/*
* Bitmask of the features supported by the device (host)
* (32 bits per set) - Read Only
*/
#define VIRTIO_MMIO_DEVICE_FEATURES 0x010

/* Device (host) features set selector - Write Only */
#define VIRTIO_MMIO_DEVICE_FEATURES_SEL 0x014

/*
* Bitmask of features activated by the driver (guest)
* (32 bits per set) - Write Only
*/
#define VIRTIO_MMIO_DRIVER_FEATURES 0x020

/* Activated features set selector - Write Only */
#define VIRTIO_MMIO_DRIVER_FEATURES_SEL 0x024

#ifndef VIRTIO_MMIO_NO_LEGACY /* LEGACY DEVICES ONLY! */
/* Guest's memory page size in bytes - Write Only */
#define VIRTIO_MMIO_GUEST_PAGE_SIZE 0x028
#endif

/* Queue selector - Write Only */
#define VIRTIO_MMIO_QUEUE_SEL 0x030

/* Maximum size of the currently selected queue - Read Only */
#define VIRTIO_MMIO_QUEUE_NUM_MAX 0x034

/* Queue size for the currently selected queue - Write Only */
#define VIRTIO_MMIO_QUEUE_NUM 0x038

#ifdef VIRTIO_MMIO_LEGACY
/* Used Ring alignment for the currently selected queue - Write Only */
#define VIRTIO_MMIO_QUEUE_ALIGN 0x03c
/* Guest's PFN for the currently selected queue - Read Write */
#define VIRTIO_MMIO_QUEUE_PFN 0x040
#endif

/* Ready bit for the currently selected queue - Read Write */
#define VIRTIO_MMIO_QUEUE_READY 0x044

/* Queue notifier - Write Only */
#define VIRTIO_MMIO_QUEUE_NOTIFY 0x050

/* Interrupt status - Read Only */
#define VIRTIO_MMIO_INTERRUPT_STATUS 0x060

/* Interrupt acknowledge - Write Only */
#define VIRTIO_MMIO_INTERRUPT_ACK 0x064

/* Device status register - Read Write */
#define VIRTIO_MMIO_STATUS 0x070

/* Selected queue's Descriptor Table address, 64 bits in two halves */
#define VIRTIO_MMIO_QUEUE_DESC_LOW 0x080
#define VIRTIO_MMIO_QUEUE_DESC_HIGH 0x084

/* Selected queue's Available Ring address, 64 bits in two halves */
#define VIRTIO_MMIO_QUEUE_AVAIL_LOW 0x090
#define VIRTIO_MMIO_QUEUE_AVAIL_HIGH 0x094

/* Selected queue's Used Ring address, 64 bits in two halves */
#define VIRTIO_MMIO_QUEUE_USED_LOW 0x0a0
#define VIRTIO_MMIO_QUEUE_USED_HIGH 0x0a4

/* Shared memory region id */
#define VIRTIO_MMIO_SHM_SEL 0x0ac

/* Shared memory region length, 64 bits in two halves */
#define VIRTIO_MMIO_SHM_LEN_LOW 0x0b0
#define VIRTIO_MMIO_SHM_LEN_HIGH 0x0b4

/* Shared memory region base address, 64 bits in two halves */
#define VIRTIO_MMIO_SHM_BASE_LOW 0x0b8
#define VIRTIO_MMIO_SHM_BASE_HIGH 0x0bc

/* Configuration atomicity value */
#define VIRTIO_MMIO_CONFIG_GENERATION 0x0fc

/*
* The config space is defined by each driver as
* the per-driver configuration space - Read Write
*/
#define VIRTIO_MMIO_CONFIG 0x100

/* Interrupt flags (re: interrupt status & acknowledge registers) */
#define VIRTIO_MMIO_INT_VRING (1 << 0)
#define VIRTIO_MMIO_INT_CONFIG (1 << 1)

/* Data buffer size for preallocated buffers before vring */
#define VIRTIO_MMIO_MAX_DATA_SIZE 128

/**
* struct virtio_mmio_dev_mem: VIRTIO MMIO memory area
* @base memory region physical address
* @size memory region size
*/
struct virtio_mmio_dev_mem {
void *base;
size_t size;
};

/**
* struct virtio_mmio_device: representation of a VIRTIO MMIO device
* @vdev base virtio device struct
* @cfg_io device configuration space metal_io_region
* @shm_io pre-shared memory space metal_io_region
* @shm_device shared memory device
* @cfg_mem VIRTIO device configuration space
* @shm_mem VIRTIO device pre-shared memory
* @device_mode VIRTIO_DEV_DRIVER or VIRTIO_DEV_DEVICE
* @irq interrupt number
* @user_data custom user data
*/
struct virtio_mmio_device {
struct virtio_device vdev;
struct metal_io_region *cfg_io;
struct metal_io_region *shm_io;
struct metal_device shm_device;
struct virtio_mmio_dev_mem cfg_mem;
struct virtio_mmio_dev_mem shm_mem;
unsigned int device_mode;
unsigned int irq;
void *user_data;
};

/**
* @brief Register a VIRTIO device with the VIRTIO stack.
*
* @param dev Pointer to device structure.
* @param vq_num Number of virtqueues the device uses.
* @param vqs Array of pointers to vthe virtqueues used by the device.
*/
void virtio_mmio_register_device(struct virtio_device *vdev, int vq_num, struct virtqueue **vqs);

/**
* @brief Setup a virtqueue structure.
*
* @param dev Pointer to device structure.
* @param idx Index of the virtqueue.
* @param vq Pointer to virtqueue structure.
* @param cb Pointer to virtqueue callback. Can be NULL.
* @param cb_arg Argument for the virtqueue callback.
*
* @return pointer to virtqueue structure.
*/
struct virtqueue *virtio_mmio_setup_virtqueue(struct virtio_device *vdev,
unsigned int idx,
struct virtqueue *vq,
void (*cb)(void *),
void *cb_arg,
const char *vq_name);

/**
* @brief VIRTIO MMIO device initialization.
*
* @param vmdev Pointer to virtio_mmio_device structure.
* @param virt_mem_ptr Guest virtio (shared) memory base address (virtual).
* @param cfg_mem_ptr Virtio device configuration memory base address (virtual).
* @param user_data Pointer to custom user data.
*
* @return int 0 for success.
*/
int virtio_mmio_device_init(struct virtio_mmio_device *vmdev, uintptr_t virt_mem_ptr,
uintptr_t cfg_mem_ptr, void *user_data);

/**
* @brief VIRTIO MMIO interrupt service routine.
*
* @param vdev Pointer to virtio_device structure.
*/
void virtio_mmio_isr(struct virtio_device *vdev);

#ifdef __cplusplus
}
#endif

#endif /* OPENAMP_VIRTIO_MMIO_H */
25 changes: 25 additions & 0 deletions lib/include/openamp/virtqueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ struct virtqueue {
uint16_t vq_queue_index;
uint16_t vq_nentries;
void (*callback)(struct virtqueue *vq);
void *priv;
void (*notify)(struct virtqueue *vq);
struct vring vq_ring;
uint16_t vq_free_cnt;
Expand Down Expand Up @@ -334,6 +335,30 @@ uint32_t virtqueue_get_desc_size(struct virtqueue *vq);
uint32_t virtqueue_get_buffer_length(struct virtqueue *vq, uint16_t idx);
void *virtqueue_get_buffer_addr(struct virtqueue *vq, uint16_t idx);

/**
* @brief Test if virtqueue is empty
*
* @param vq Pointer to VirtIO queue control block
*
* @return 1 if virtqueue is empty
*/
static inline int virtqueue_empty(struct virtqueue *vq)
{
return (vq->vq_nentries == vq->vq_free_cnt);
}

/**
* @brief Test if virtqueue is full
*
* @param vq Pointer to VirtIO queue control block
*
* @return 1 if virtqueue is full
*/
static inline int virtqueue_full(struct virtqueue *vq)
{
return (vq->vq_free_cnt == 0);
}

#if defined __cplusplus
}
#endif
Expand Down
Loading

0 comments on commit bbd278d

Please sign in to comment.