322 lines
6.6 KiB
C
322 lines
6.6 KiB
C
/* SPDX-License-Identifier: (MIT OR GPL-2.0) */
|
|
#ifndef _LINUX_VIRTIO_VDMABUF_H
|
|
#define _LINUX_VIRTIO_VDMABUF_H
|
|
|
|
#include <uapi/linux/virtio_vdmabuf.h>
|
|
#include <linux/hashtable.h>
|
|
#include "../../drivers/vhost/vhost.h"
|
|
|
|
#define UINT32_MAX ((u32)~0U)
|
|
#define VIRTIO_VDMABUF_MAX_ID UINT32_MAX
|
|
#define VIRTIO_VDMABUF_HASH_BITS 7
|
|
#define VIRTIO_VDMABUF_CARVEOUT_NAME_LEN 16
|
|
#define VIRTIO_VDMABUF_MAX_OPS 6
|
|
#define VIRTIO_VDMABUF_MAX_BP_NUM (VIRTIO_VDAMBUF_MAX_ALLOC_SIZE / PAGE_SIZE)
|
|
#define VIRTIO_VDMABUF_CARVEOUT_NAMES {{"vi"},{"vo"},{"enc"},{"dec"},{"gpu"},{"dpu"}}
|
|
|
|
struct buf_pair {
|
|
struct page *page;
|
|
phys_addr_t addr;
|
|
unsigned int size;
|
|
};
|
|
|
|
struct virtio_vdmabuf_buf {
|
|
int vmid;
|
|
size_t size;
|
|
unsigned int buf_id;
|
|
|
|
struct mutex lock;
|
|
|
|
/* list of devices attached to this buffer */
|
|
struct list_head attachments;
|
|
|
|
struct dma_buf *dma_buf;
|
|
|
|
/* validity of the buffer */
|
|
bool valid;
|
|
|
|
/* set if the buffer is imported from remote */
|
|
bool imported;
|
|
|
|
/* size of private */
|
|
size_t sz_priv;
|
|
/* private data associated with the exported buffer */
|
|
void *priv;
|
|
|
|
void *host;
|
|
|
|
struct hlist_node node;
|
|
|
|
/* real buf info */
|
|
int heap_type;
|
|
int carveout_type;
|
|
int flags;
|
|
int bp_num;
|
|
struct buf_pair bp[];
|
|
};
|
|
|
|
struct virtio_vdmabuf_attachment {
|
|
struct device *dev;
|
|
struct sg_table *sgt;
|
|
struct list_head list;
|
|
};
|
|
|
|
struct carveout_buf {
|
|
phys_addr_t addr;
|
|
unsigned int size;
|
|
bool ready;
|
|
};
|
|
|
|
struct virtio_vdmabuf_event {
|
|
struct list_head list;
|
|
|
|
/*
|
|
* 0: vmid
|
|
* 1: buf_id
|
|
* 2: heap_type
|
|
* 3: carveout_type
|
|
* 4: flags
|
|
* 5: bp num
|
|
*/
|
|
unsigned int op[VIRTIO_VDMABUF_MAX_OPS];
|
|
struct buf_pair bp[];
|
|
};
|
|
|
|
struct virtio_vdmabuf_event_queue {
|
|
wait_queue_head_t e_wait;
|
|
struct list_head e_list;
|
|
|
|
spinlock_t e_lock;
|
|
struct mutex e_readlock;
|
|
};
|
|
|
|
/* driver information */
|
|
struct virtio_vdmabuf_info {
|
|
struct device *dev;
|
|
|
|
struct list_head head_vdmabuf_list;
|
|
struct list_head kvm_instances;
|
|
|
|
spinlock_t local_lock;
|
|
DECLARE_HASHTABLE(buf_list_local, VIRTIO_VDMABUF_HASH_BITS);
|
|
spinlock_t import_lock;
|
|
DECLARE_HASHTABLE(buf_list_import, VIRTIO_VDMABUF_HASH_BITS);
|
|
|
|
void *priv;
|
|
struct mutex g_mutex;
|
|
bool host_ready;
|
|
};
|
|
|
|
struct vhost_vdmabuf;
|
|
struct virtio_vdmabuf;
|
|
|
|
/*
|
|
* IOCTL definitions
|
|
*/
|
|
typedef int (*vhost_vdmabuf_ioctl_t)(struct vhost_vdmabuf *vdmabuf,
|
|
void *data);
|
|
typedef int (*virtio_vdmabuf_ioctl_t)(struct virtio_vdmabuf *vdmabuf,
|
|
void *data);
|
|
|
|
struct vhost_vdmabuf_ioctl_desc {
|
|
unsigned int cmd;
|
|
int flags;
|
|
vhost_vdmabuf_ioctl_t func;
|
|
const char *name;
|
|
};
|
|
|
|
struct virtio_vdmabuf_ioctl_desc {
|
|
unsigned int cmd;
|
|
int flags;
|
|
virtio_vdmabuf_ioctl_t func;
|
|
const char *name;
|
|
};
|
|
|
|
#define VIRTIO_VDMABUF_IOCTL_DEF(ioctl, _func, _flags) \
|
|
[_IOC_NR(ioctl)] = { \
|
|
.cmd = ioctl, \
|
|
.func = _func, \
|
|
.flags = _flags, \
|
|
.name = #ioctl \
|
|
}
|
|
|
|
/* msg structures */
|
|
struct virtio_vdmabuf_msg {
|
|
struct list_head list;
|
|
unsigned int cmd;
|
|
|
|
/*
|
|
* 0: vmid
|
|
* 1: buf_id
|
|
* 2: heap_type
|
|
* 3: carveout_type
|
|
* 4: flags
|
|
* 5: bp num
|
|
*/
|
|
unsigned int op[VIRTIO_VDMABUF_MAX_OPS];
|
|
struct buf_pair bp[];
|
|
};
|
|
|
|
enum {
|
|
VDMABUF_VQ_RECV = 0,
|
|
VDMABUF_VQ_SEND = 1,
|
|
VDMABUF_VQ_MAX = 2,
|
|
};
|
|
|
|
enum virtio_vdmabuf_cmd {
|
|
VIRTIO_VDMABUF_CMD_VMID_REQ,
|
|
VIRTIO_VDMABUF_CMD_VMID_REPLY,
|
|
VIRTIO_VDMABUF_CMD_IMPORT_REQ,
|
|
VIRTIO_VDMABUF_CMD_IMPORT_REPLY,
|
|
VIRTIO_VDMABUF_CMD_REL_NOTIFY,
|
|
};
|
|
|
|
struct virtio_vdmabuf {
|
|
/* virtio device structure */
|
|
struct virtio_device *vdev;
|
|
|
|
/* virtual queue array */
|
|
struct virtqueue *vqs[VDMABUF_VQ_MAX];
|
|
|
|
/* ID of guest OS */
|
|
unsigned int vmid;
|
|
|
|
/* spin lock that needs to be acquired before accessing
|
|
* virtual queue
|
|
*/
|
|
spinlock_t vq_lock;
|
|
struct mutex recv_lock;
|
|
struct mutex send_lock;
|
|
|
|
spinlock_t msg_list_lock;
|
|
struct list_head msg_list;
|
|
|
|
/* workqueue */
|
|
struct workqueue_struct *wq;
|
|
struct work_struct recv_work;
|
|
struct work_struct send_work;
|
|
struct work_struct send_msg_work;
|
|
|
|
struct virtio_vdmabuf_event_queue *eq_import;
|
|
};
|
|
|
|
struct vhost_vdmabuf {
|
|
struct vhost_dev dev;
|
|
struct vhost_virtqueue vqs[VDMABUF_VQ_MAX];
|
|
struct vhost_work send_work;
|
|
struct virtio_vdmabuf_event_queue *eq_import;
|
|
unsigned int vmid;
|
|
|
|
struct list_head msg_list;
|
|
struct list_head list;
|
|
|
|
spinlock_t local_lock;
|
|
DECLARE_HASHTABLE(buf_list_local, VIRTIO_VDMABUF_HASH_BITS);
|
|
spinlock_t import_lock;
|
|
DECLARE_HASHTABLE(buf_list_import, VIRTIO_VDMABUF_HASH_BITS);
|
|
};
|
|
|
|
static inline int vdmabuf_msg_size(int bp_num)
|
|
{
|
|
return sizeof(struct virtio_vdmabuf_msg) +
|
|
sizeof(struct buf_pair) * bp_num;
|
|
}
|
|
|
|
/* guest api */
|
|
static inline int
|
|
virtio_vdmabuf_add_buf(struct virtio_vdmabuf_info *info,
|
|
struct virtio_vdmabuf_buf *new,
|
|
bool local)
|
|
{
|
|
if (local)
|
|
hash_add(info->buf_list_local, &new->node, new->buf_id);
|
|
else
|
|
hash_add(info->buf_list_import, &new->node, new->buf_id);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline struct virtio_vdmabuf_buf
|
|
*virtio_vdmabuf_find_buf(struct virtio_vdmabuf_info *info,
|
|
unsigned int buf_id, bool local)
|
|
{
|
|
struct virtio_vdmabuf_buf *found;
|
|
|
|
if (local) {
|
|
hash_for_each_possible(info->buf_list_local, found, node, buf_id)
|
|
if (found->buf_id == buf_id)
|
|
return found;
|
|
} else {
|
|
hash_for_each_possible(info->buf_list_import, found, node, buf_id)
|
|
if (found->buf_id == buf_id)
|
|
return found;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static inline int
|
|
virtio_vdmabuf_del_buf(struct virtio_vdmabuf_info *info,
|
|
unsigned int buf_id, bool local)
|
|
{
|
|
struct virtio_vdmabuf_buf *found;
|
|
|
|
found = virtio_vdmabuf_find_buf(info, buf_id, local);
|
|
if (!found)
|
|
return -ENOENT;
|
|
|
|
hash_del(&found->node);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* host api */
|
|
static inline int
|
|
vhost_vdmabuf_add_buf(struct vhost_vdmabuf *vdmabuf,
|
|
struct virtio_vdmabuf_buf *new,
|
|
bool local)
|
|
{
|
|
if (local)
|
|
hash_add(vdmabuf->buf_list_local, &new->node, new->buf_id);
|
|
else
|
|
hash_add(vdmabuf->buf_list_import, &new->node, new->buf_id);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline struct virtio_vdmabuf_buf
|
|
*vhost_vdmabuf_find_buf(struct vhost_vdmabuf *vdmabuf,
|
|
unsigned int buf_id, bool local)
|
|
{
|
|
struct virtio_vdmabuf_buf *found;
|
|
|
|
if (local) {
|
|
hash_for_each_possible(vdmabuf->buf_list_local, found, node, buf_id)
|
|
if (found->buf_id == buf_id)
|
|
return found;
|
|
} else {
|
|
hash_for_each_possible(vdmabuf->buf_list_import, found, node, buf_id)
|
|
if (found->buf_id == buf_id)
|
|
return found;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static inline int
|
|
vhost_vdmabuf_del_buf(struct vhost_vdmabuf *vdmabuf,
|
|
unsigned int buf_id, bool local)
|
|
{
|
|
struct virtio_vdmabuf_buf *found;
|
|
|
|
found = vhost_vdmabuf_find_buf(vdmabuf, buf_id, local);
|
|
if (!found)
|
|
return -ENOENT;
|
|
|
|
hash_del(&found->node);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif
|