Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Virtio native support for lib openamp #494

Merged
merged 1 commit into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
danmilea marked this conversation as resolved.
Show resolved Hide resolved

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)
arnopo marked this conversation as resolved.
Show resolved Hide resolved
{
return virtio_create_virtqueues(rvdev->vdev, flags, nvqs, names,
callbacks);
callbacks, NULL);
}

/**
Expand Down
70 changes: 63 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,45 @@ 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 { \
danmilea marked this conversation as resolved.
Show resolved Hide resolved
arnopo marked this conversation as resolved.
Show resolved Hide resolved
int exp = (_exp); \
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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something that should become configurable. it is not not blocking for this step, can be done later.


#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 +220,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 +246,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 +278,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

arnopo marked this conversation as resolved.
Show resolved Hide resolved
/**
* 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, 0 otherwise
*/
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, 0 otherwise
*/
static inline int virtqueue_full(struct virtqueue *vq)
{
return (vq->vq_free_cnt == 0);
}

#if defined __cplusplus
}
#endif
Expand Down
Loading
Loading