Browse Source
VDUSE [1] is a linux framework that makes it possible to implement software-emulated vDPA devices in userspace. This adds a library as a subproject to help implementing VDUSE backends in QEMU. [1] https://www.kernel.org/doc/html/latest/userspace-api/vduse.html Signed-off-by: Xie Yongji <xieyongji@bytedance.com> Message-Id: <20220523084611.91-6-xieyongji@bytedance.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>pull/213/head
committed by
Kevin Wolf
11 changed files with 1424 additions and 0 deletions
@ -0,0 +1 @@ |
|||
../../../include/qemu/atomic.h |
|||
@ -0,0 +1 @@ |
|||
../../../include/qemu/compiler.h |
|||
File diff suppressed because it is too large
@ -0,0 +1,235 @@ |
|||
/*
|
|||
* VDUSE (vDPA Device in Userspace) library |
|||
* |
|||
* Copyright (C) 2022 Bytedance Inc. and/or its affiliates. All rights reserved. |
|||
* |
|||
* Author: |
|||
* Xie Yongji <xieyongji@bytedance.com> |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or |
|||
* later. See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#ifndef LIBVDUSE_H |
|||
#define LIBVDUSE_H |
|||
|
|||
#include <stdint.h> |
|||
#include <sys/uio.h> |
|||
|
|||
#define VIRTQUEUE_MAX_SIZE 1024 |
|||
|
|||
/* VDUSE device structure */ |
|||
typedef struct VduseDev VduseDev; |
|||
|
|||
/* Virtqueue structure */ |
|||
typedef struct VduseVirtq VduseVirtq; |
|||
|
|||
/* Some operation of VDUSE backend */ |
|||
typedef struct VduseOps { |
|||
/* Called when virtqueue can be processed */ |
|||
void (*enable_queue)(VduseDev *dev, VduseVirtq *vq); |
|||
/* Called when virtqueue processing should be stopped */ |
|||
void (*disable_queue)(VduseDev *dev, VduseVirtq *vq); |
|||
} VduseOps; |
|||
|
|||
/* Describing elements of the I/O buffer */ |
|||
typedef struct VduseVirtqElement { |
|||
/* Descriptor table index */ |
|||
unsigned int index; |
|||
/* Number of physically-contiguous device-readable descriptors */ |
|||
unsigned int out_num; |
|||
/* Number of physically-contiguous device-writable descriptors */ |
|||
unsigned int in_num; |
|||
/* Array to store physically-contiguous device-writable descriptors */ |
|||
struct iovec *in_sg; |
|||
/* Array to store physically-contiguous device-readable descriptors */ |
|||
struct iovec *out_sg; |
|||
} VduseVirtqElement; |
|||
|
|||
|
|||
/**
|
|||
* vduse_get_virtio_features: |
|||
* |
|||
* Get supported virtio features |
|||
* |
|||
* Returns: supported feature bits |
|||
*/ |
|||
uint64_t vduse_get_virtio_features(void); |
|||
|
|||
/**
|
|||
* vduse_queue_get_dev: |
|||
* @vq: specified virtqueue |
|||
* |
|||
* Get corresponding VDUSE device from the virtqueue. |
|||
* |
|||
* Returns: a pointer to VDUSE device on success, NULL on failure. |
|||
*/ |
|||
VduseDev *vduse_queue_get_dev(VduseVirtq *vq); |
|||
|
|||
/**
|
|||
* vduse_queue_get_fd: |
|||
* @vq: specified virtqueue |
|||
* |
|||
* Get the kick fd for the virtqueue. |
|||
* |
|||
* Returns: file descriptor on success, -1 on failure. |
|||
*/ |
|||
int vduse_queue_get_fd(VduseVirtq *vq); |
|||
|
|||
/**
|
|||
* vduse_queue_pop: |
|||
* @vq: specified virtqueue |
|||
* @sz: the size of struct to return (must be >= VduseVirtqElement) |
|||
* |
|||
* Pop an element from virtqueue available ring. |
|||
* |
|||
* Returns: a pointer to a structure containing VduseVirtqElement on success, |
|||
* NULL on failure. |
|||
*/ |
|||
void *vduse_queue_pop(VduseVirtq *vq, size_t sz); |
|||
|
|||
/**
|
|||
* vduse_queue_push: |
|||
* @vq: specified virtqueue |
|||
* @elem: pointer to VduseVirtqElement returned by vduse_queue_pop() |
|||
* @len: length in bytes to write |
|||
* |
|||
* Push an element to virtqueue used ring. |
|||
*/ |
|||
void vduse_queue_push(VduseVirtq *vq, const VduseVirtqElement *elem, |
|||
unsigned int len); |
|||
/**
|
|||
* vduse_queue_notify: |
|||
* @vq: specified virtqueue |
|||
* |
|||
* Request to notify the queue. |
|||
*/ |
|||
void vduse_queue_notify(VduseVirtq *vq); |
|||
|
|||
/**
|
|||
* vduse_dev_get_priv: |
|||
* @dev: VDUSE device |
|||
* |
|||
* Get the private pointer passed to vduse_dev_create(). |
|||
* |
|||
* Returns: private pointer on success, NULL on failure. |
|||
*/ |
|||
void *vduse_dev_get_priv(VduseDev *dev); |
|||
|
|||
/**
|
|||
* vduse_dev_get_queue: |
|||
* @dev: VDUSE device |
|||
* @index: virtqueue index |
|||
* |
|||
* Get the specified virtqueue. |
|||
* |
|||
* Returns: a pointer to the virtqueue on success, NULL on failure. |
|||
*/ |
|||
VduseVirtq *vduse_dev_get_queue(VduseDev *dev, int index); |
|||
|
|||
/**
|
|||
* vduse_dev_get_fd: |
|||
* @dev: VDUSE device |
|||
* |
|||
* Get the control message fd for the VDUSE device. |
|||
* |
|||
* Returns: file descriptor on success, -1 on failure. |
|||
*/ |
|||
int vduse_dev_get_fd(VduseDev *dev); |
|||
|
|||
/**
|
|||
* vduse_dev_handler: |
|||
* @dev: VDUSE device |
|||
* |
|||
* Used to process the control message. |
|||
* |
|||
* Returns: file descriptor on success, -errno on failure. |
|||
*/ |
|||
int vduse_dev_handler(VduseDev *dev); |
|||
|
|||
/**
|
|||
* vduse_dev_update_config: |
|||
* @dev: VDUSE device |
|||
* @size: the size to write to configuration space |
|||
* @offset: the offset from the beginning of configuration space |
|||
* @buffer: the buffer used to write from |
|||
* |
|||
* Update device configuration space and inject a config interrupt. |
|||
* |
|||
* Returns: 0 on success, -errno on failure. |
|||
*/ |
|||
int vduse_dev_update_config(VduseDev *dev, uint32_t size, |
|||
uint32_t offset, char *buffer); |
|||
|
|||
/**
|
|||
* vduse_dev_setup_queue: |
|||
* @dev: VDUSE device |
|||
* @index: virtqueue index |
|||
* @max_size: the max size of virtqueue |
|||
* |
|||
* Setup the specified virtqueue. |
|||
* |
|||
* Returns: 0 on success, -errno on failure. |
|||
*/ |
|||
int vduse_dev_setup_queue(VduseDev *dev, int index, int max_size); |
|||
|
|||
/**
|
|||
* vduse_dev_create_by_fd: |
|||
* @fd: passed file descriptor |
|||
* @num_queues: the number of virtqueues |
|||
* @ops: the operation of VDUSE backend |
|||
* @priv: private pointer |
|||
* |
|||
* Create VDUSE device from a passed file descriptor. |
|||
* |
|||
* Returns: pointer to VDUSE device on success, NULL on failure. |
|||
*/ |
|||
VduseDev *vduse_dev_create_by_fd(int fd, uint16_t num_queues, |
|||
const VduseOps *ops, void *priv); |
|||
|
|||
/**
|
|||
* vduse_dev_create_by_name: |
|||
* @name: VDUSE device name |
|||
* @num_queues: the number of virtqueues |
|||
* @ops: the operation of VDUSE backend |
|||
* @priv: private pointer |
|||
* |
|||
* Create VDUSE device on /dev/vduse/$NAME. |
|||
* |
|||
* Returns: pointer to VDUSE device on success, NULL on failure. |
|||
*/ |
|||
VduseDev *vduse_dev_create_by_name(const char *name, uint16_t num_queues, |
|||
const VduseOps *ops, void *priv); |
|||
|
|||
/**
|
|||
* vduse_dev_create: |
|||
* @name: VDUSE device name |
|||
* @device_id: virtio device id |
|||
* @vendor_id: virtio vendor id |
|||
* @features: virtio features |
|||
* @num_queues: the number of virtqueues |
|||
* @config_size: the size of the configuration space |
|||
* @config: the buffer of the configuration space |
|||
* @ops: the operation of VDUSE backend |
|||
* @priv: private pointer |
|||
* |
|||
* Create VDUSE device. |
|||
* |
|||
* Returns: pointer to VDUSE device on success, NULL on failure. |
|||
*/ |
|||
VduseDev *vduse_dev_create(const char *name, uint32_t device_id, |
|||
uint32_t vendor_id, uint64_t features, |
|||
uint16_t num_queues, uint32_t config_size, |
|||
char *config, const VduseOps *ops, void *priv); |
|||
|
|||
/**
|
|||
* vduse_dev_destroy: |
|||
* @dev: VDUSE device |
|||
* |
|||
* Destroy the VDUSE device. |
|||
* |
|||
* Returns: 0 on success, -errno on failure. |
|||
*/ |
|||
int vduse_dev_destroy(VduseDev *dev); |
|||
|
|||
#endif |
|||
@ -0,0 +1 @@ |
|||
../../../linux-headers/linux/ |
|||
@ -0,0 +1,10 @@ |
|||
project('libvduse', 'c', |
|||
license: 'GPL-2.0-or-later', |
|||
default_options: ['c_std=gnu99']) |
|||
|
|||
libvduse = static_library('vduse', |
|||
files('libvduse.c'), |
|||
c_args: '-D_GNU_SOURCE') |
|||
|
|||
libvduse_dep = declare_dependency(link_with: libvduse, |
|||
include_directories: include_directories('.')) |
|||
@ -0,0 +1 @@ |
|||
../../../include/standard-headers/linux/ |
|||
Loading…
Reference in new issue