mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-21 21:19:35 +00:00
ACRN: DM: Implement the vhost vsock
This patch supports the user space logic of vhost vsock which is majorly for its initialization phase. Tracked-On: #7456 Signed-off-by: Liu Long <long.liu@linux.intel.com> Reviewed-by: Conghui <conghui.chen@intel.com> Acked-by: Wang, Yu1 <yu1.wang@intel.com>
This commit is contained in:
parent
231f986bd9
commit
46e41390b5
@ -155,6 +155,7 @@ SRCS += hw/pci/virtio/virtio_hdcp.c
|
||||
SRCS += hw/pci/virtio/virtio_rpmb.c
|
||||
SRCS += hw/pci/virtio/virtio_gpio.c
|
||||
SRCS += hw/pci/virtio/virtio_gpu.c
|
||||
SRCS += hw/pci/virtio/vhost_vsock.c
|
||||
SRCS += hw/pci/irq.c
|
||||
SRCS += hw/pci/uart.c
|
||||
SRCS += hw/pci/gvt.c
|
||||
|
340
devicemodel/hw/pci/virtio/vhost_vsock.c
Normal file
340
devicemodel/hw/pci/virtio/vhost_vsock.c
Normal file
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Copyright (C) OASIS Open 2018. All rights reserved.
|
||||
* Copyright (C) 2022 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* vhost-vsock device
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/uio.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/errno.h>
|
||||
#include <pthread.h>
|
||||
#include <linux/vhost.h>
|
||||
|
||||
#include "dm.h"
|
||||
#include "pci_core.h"
|
||||
#include "virtio.h"
|
||||
#include "vhost.h"
|
||||
#include "dm_string.h"
|
||||
#include "vhost_vsock.h"
|
||||
|
||||
static int
|
||||
vhost_vsock_set_running(struct vhost_dev *vdev, int start)
|
||||
{
|
||||
return vhost_kernel_ioctl(vdev, VHOST_VSOCK_SET_RUNNING, &start);
|
||||
}
|
||||
|
||||
static int
|
||||
vhost_vsock_set_guest_cid(struct vhost_dev *vdev,
|
||||
uint64_t guest_cid)
|
||||
{
|
||||
return vhost_kernel_ioctl(vdev,
|
||||
VHOST_VSOCK_SET_GUEST_CID, &guest_cid);
|
||||
}
|
||||
|
||||
static int
|
||||
vhost_vsock_start(struct vhost_vsock *vhost_vsock)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (vhost_vsock->vhost_started) {
|
||||
pr_err("vhost vsock is already started!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = vhost_dev_start(&vhost_vsock->vdev);
|
||||
if (rc < 0) {
|
||||
pr_err("vhost_dev_start is failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = vhost_vsock_set_running(&vhost_vsock->vdev, 1);
|
||||
if (rc < 0) {
|
||||
vhost_dev_stop(&vhost_vsock->vdev);
|
||||
pr_err("vhost_vsock_set_running is failed %d!\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
vhost_vsock->vhost_started = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
vhost_vsock_stop(struct vhost_vsock *vhost_vsock)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!vhost_vsock->vhost_started) {
|
||||
pr_err("vhost vsock is not started!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = vhost_vsock_set_running(&vhost_vsock->vdev, 0);
|
||||
if (rc < 0) {
|
||||
pr_err("vhost_vsock_set_running is failed with %d\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = vhost_dev_stop(&vhost_vsock->vdev);
|
||||
if (rc < 0) {
|
||||
pr_err("vhost_dev_stop is failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
vhost_vsock->vhost_started = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
virtio_vsock_set_status(void *vdev, uint64_t status)
|
||||
{
|
||||
struct virtio_vsock *vsock = vdev;
|
||||
bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK;
|
||||
int rc;
|
||||
|
||||
if (!vsock->vhost_vsock) {
|
||||
pr_err("virtio_vsock_set_status vhost is NULL!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (should_start) {
|
||||
rc = vhost_vsock_start(vsock->vhost_vsock);
|
||||
if (rc < 0) {
|
||||
pr_err("vhost_vsock_start is failed!\n");
|
||||
return;
|
||||
}
|
||||
} else if (vsock->vhost_vsock->vhost_started &&
|
||||
should_start == 0) {
|
||||
rc = vhost_vsock_stop(vsock->vhost_vsock);
|
||||
if (rc < 0) {
|
||||
pr_err("vhost_vsock_stop is failed!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
virtio_vsock_apply_feature(void *vdev, uint64_t negotiated_features)
|
||||
{
|
||||
struct virtio_vsock *vsock = vdev;
|
||||
|
||||
vsock->features = negotiated_features;
|
||||
}
|
||||
|
||||
static int
|
||||
virtio_vsock_read_cfg(void *vdev, int offset, int size, uint32_t *retval)
|
||||
{
|
||||
struct virtio_vsock *vsock = vdev;
|
||||
void *ptr;
|
||||
|
||||
ptr = (uint8_t *)&vsock->config + offset;
|
||||
memcpy(retval, ptr, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
virtio_vsock_reset(void *vdev)
|
||||
{
|
||||
struct virtio_vsock *vsock = vdev;
|
||||
|
||||
pr_dbg(("vsock: device reset requested!\n"));
|
||||
/* now reset rings, MSI-X vectors, and negotiated capabilities */
|
||||
virtio_reset_dev(&vsock->base);
|
||||
}
|
||||
|
||||
static struct virtio_ops virtio_vsock_ops = {
|
||||
"vhost-vsock", /* our name */
|
||||
VHOST_VSOCK_MAXQ, /* we currently support 2 virtqueues */
|
||||
sizeof(struct virtio_vsock_config), /* config reg size */
|
||||
virtio_vsock_reset, /* reset */
|
||||
NULL, /* device-wide qnotify -- not used */
|
||||
virtio_vsock_read_cfg, /* read PCI config */
|
||||
NULL, /* write PCI config */
|
||||
virtio_vsock_apply_feature, /* apply negotiated features */
|
||||
virtio_vsock_set_status, /* called on guest set status */
|
||||
};
|
||||
|
||||
static struct vhost_vsock *
|
||||
vhost_vsock_init(struct virtio_base *base, int vq_idx)
|
||||
{
|
||||
struct vhost_vsock *vhost_vsock = NULL;
|
||||
uint64_t vhost_features = VHOST_VSOCK_FEATURES;
|
||||
int rc;
|
||||
|
||||
vhost_vsock = calloc(1, sizeof(struct vhost_vsock));
|
||||
if (!vhost_vsock) {
|
||||
pr_err(("vhost init out of memory!\n"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* pre-init before calling vhost_dev_init */
|
||||
vhost_vsock->vdev.nvqs = 2;
|
||||
vhost_vsock->vdev.vqs = vhost_vsock->vqs;
|
||||
vhost_vsock->vhost_fd = open("/dev/vhost-vsock", O_RDWR);;
|
||||
if (vhost_vsock->vhost_fd < 0) {
|
||||
pr_err(("Open vhost-vsock fail, pls open vsock kernel config!\n"));
|
||||
goto fail;
|
||||
}
|
||||
rc = fcntl(vhost_vsock->vhost_fd, F_GETFL);
|
||||
if (rc == -1) {
|
||||
pr_err(("fcntl vhost node fail!\n"));
|
||||
goto fail;
|
||||
}
|
||||
if (fcntl(vhost_vsock->vhost_fd, F_SETFL, rc | O_NONBLOCK) == -1) {
|
||||
pr_err(("fcntl set NONBLOCK fail!\n"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = vhost_dev_init(&vhost_vsock->vdev, base, vhost_vsock->vhost_fd, vq_idx,
|
||||
vhost_features, 0, 0);
|
||||
if (rc < 0) {
|
||||
pr_err(("vhost_dev_init failed!\n"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return vhost_vsock;
|
||||
fail:
|
||||
if (vhost_vsock)
|
||||
free(vhost_vsock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
vhost_vsock_deinit(struct vhost_vsock *vhost_vsock)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = vhost_vsock_stop(vhost_vsock);
|
||||
if (rc < 0) {
|
||||
pr_err("vhost_dev_stop is failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = vhost_dev_deinit(&vhost_vsock->vdev);
|
||||
if (rc < 0) {
|
||||
pr_err("vhost_dev_deinit is failed!\n");
|
||||
return -1;
|
||||
}
|
||||
close(vhost_vsock->vhost_fd);
|
||||
free(vhost_vsock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
vhost_vsock_handle_output(void *vdev, struct virtio_vq_info *vq) {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
static int
|
||||
virtio_vhost_vsock_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
||||
{
|
||||
struct virtio_vsock *vsock;
|
||||
int rc, cid;
|
||||
pthread_mutexattr_t attr;
|
||||
char *devopts = NULL;
|
||||
char *tmp = NULL;
|
||||
|
||||
if (opts == NULL) {
|
||||
pr_err(("vsock: must have a valid guest_cid!\n"));
|
||||
return -1;
|
||||
}
|
||||
devopts = tmp = strdup(opts);
|
||||
if (!devopts) {
|
||||
pr_err(("vsock: The vsock parameter is NULL!\n"));
|
||||
return -1;
|
||||
}
|
||||
if (!strncmp(tmp, "cid=", 4)) {
|
||||
strsep(&tmp, "=");
|
||||
dm_strtoi(tmp, NULL, 10, &cid);
|
||||
}
|
||||
free(devopts);
|
||||
|
||||
if (cid <= VMADDR_CID_HOST || cid >= U32_MAX) {
|
||||
pr_err("vsock: guest_cid has to be 0x2~0xffffffff!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
vsock = calloc(1, sizeof(struct virtio_vsock));
|
||||
if (!vsock) {
|
||||
pr_err("vosck: memory allocate failed!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
vsock->config.guest_cid = cid;
|
||||
|
||||
rc = pthread_mutexattr_init(&attr);
|
||||
if (rc)
|
||||
pr_err("vsock: mutexattr init failed with erro %d\n", rc);
|
||||
rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
if (rc)
|
||||
pr_err("vsock: mutexattr_settype failed with error %d\n", rc);
|
||||
rc = pthread_mutex_init(&vsock->mtx, &attr);
|
||||
if (rc)
|
||||
pr_err("vsock: pthread_mutexattr_init failed with error %d\n", rc);
|
||||
|
||||
virtio_linkup(&vsock->base, &virtio_vsock_ops, vsock, dev, vsock->queues, BACKEND_VHOST);
|
||||
vsock->base.mtx = &vsock->mtx;
|
||||
vsock->base.device_caps = (1UL << VIRTIO_F_VERSION_1) | VHOST_VSOCK_FEATURES;
|
||||
|
||||
vsock->queues[VHOST_VSOCK_RXQ].qsize = VHOST_VSOCK_QUEUE_SIZE;
|
||||
vsock->queues[VHOST_VSOCK_RXQ].notify = vhost_vsock_handle_output;
|
||||
vsock->queues[VHOST_VSOCK_TXQ].qsize = VHOST_VSOCK_QUEUE_SIZE;
|
||||
vsock->queues[VHOST_VSOCK_TXQ].notify = vhost_vsock_handle_output;
|
||||
vsock->queues[VHOST_VSOCK_CTLQ].qsize = VHOST_VSOCK_QUEUE_SIZE;
|
||||
vsock->queues[VHOST_VSOCK_CTLQ].notify = vhost_vsock_handle_output;
|
||||
|
||||
/* initialize config space */
|
||||
pci_set_cfgdata16(dev, PCIR_DEVICE, VIRTIO_DEV_VSOCK);
|
||||
pci_set_cfgdata16(dev, PCIR_VENDOR, VIRTIO_VENDOR);
|
||||
pci_set_cfgdata8(dev, PCIR_CLASS, PCIC_NETWORK);
|
||||
pci_set_cfgdata16(dev, PCIR_REVID, 1);
|
||||
|
||||
virtio_set_modern_bar(&vsock->base, false);
|
||||
|
||||
vsock->vhost_vsock = vhost_vsock_init(&vsock->base, 0);
|
||||
vhost_vsock_set_guest_cid(&vsock->vhost_vsock->vdev, vsock->config.guest_cid);
|
||||
|
||||
if (virtio_interrupt_init(&vsock->base, virtio_uses_msix())) {
|
||||
if (vsock) {
|
||||
if (vsock->vhost_vsock)
|
||||
vhost_vsock_deinit(vsock->vhost_vsock);
|
||||
free(vsock);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
virtio_vhost_vsock_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
||||
{
|
||||
struct virtio_vsock *vsock;
|
||||
|
||||
if (dev->arg) {
|
||||
vsock = (struct virtio_vsock *) dev->arg;
|
||||
|
||||
if (vsock->vhost_vsock) {
|
||||
vhost_vsock_deinit(vsock->vhost_vsock);
|
||||
}
|
||||
pr_dbg("%s: done\n", __func__);
|
||||
} else
|
||||
pr_err("%s: NULL!\n", __func__);
|
||||
}
|
||||
|
||||
struct pci_vdev_ops pci_ops_vhost_vsock = {
|
||||
.class_name = "vhost-vsock",
|
||||
.vdev_init = virtio_vhost_vsock_init,
|
||||
.vdev_deinit = virtio_vhost_vsock_deinit,
|
||||
.vdev_barwrite = virtio_pci_write,
|
||||
.vdev_barread = virtio_pci_read
|
||||
};
|
||||
DEFINE_PCI_DEVTYPE(pci_ops_vhost_vsock);
|
54
devicemodel/include/vhost_vsock.h
Normal file
54
devicemodel/include/vhost_vsock.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Intel Corporation.
|
||||
* Copyright (C) 2022 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file vhost_vsock.h
|
||||
*/
|
||||
|
||||
#ifndef __VHOST_VSOCK_H__
|
||||
#define __VHOST_VSOCK_H__
|
||||
|
||||
#include "virtio.h"
|
||||
#include "vhost.h"
|
||||
|
||||
#define VHOST_VSOCK_RXQ 0
|
||||
#define VHOST_VSOCK_TXQ 1
|
||||
#define VHOST_VSOCK_CTLQ 2 /* NB: not yet supported */
|
||||
#define VHOST_VSOCK_MAXQ 3
|
||||
|
||||
#define VHOST_VSOCK_QUEUE_SIZE 128
|
||||
#define VHOST_F_LOG_ALL 26
|
||||
|
||||
#define VHOST_VSOCK_FEATURES \
|
||||
(1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) | (1ULL << VIRTIO_RING_F_INDIRECT_DESC) | \
|
||||
(1ULL << VIRTIO_RING_F_EVENT_IDX) | (1ULL << VHOST_F_LOG_ALL) | \
|
||||
(1ULL << VIRTIO_F_ANY_LAYOUT) | (1ULL << VIRTIO_F_VERSION_1)
|
||||
|
||||
#define U32_MAX 65535
|
||||
#define VMADDR_CID_HOST 2
|
||||
|
||||
struct virtio_vsock_config {
|
||||
uint64_t guest_cid;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct virtio_vsock {
|
||||
struct virtio_base base;
|
||||
pthread_mutex_t mtx;
|
||||
struct virtio_vq_info queues[VHOST_VSOCK_MAXQ];
|
||||
struct virtio_vsock_config config;
|
||||
struct vhost_vsock *vhost_vsock;
|
||||
uint64_t features;
|
||||
};
|
||||
|
||||
struct vhost_vsock {
|
||||
struct vhost_dev vdev;
|
||||
struct vhost_vq vqs[VHOST_VSOCK_MAXQ];
|
||||
int vhost_fd;
|
||||
bool vhost_started;
|
||||
};
|
||||
#endif
|
@ -221,6 +221,7 @@ enum {
|
||||
#define VIRTIO_DEV_CONSOLE 0x1003
|
||||
#define VIRTIO_DEV_RANDOM 0x1005
|
||||
#define VIRTIO_DEV_GPU 0x1050
|
||||
#define VIRTIO_DEV_VSOCK 0x1053
|
||||
|
||||
/*
|
||||
* ACRN virtio device IDs
|
||||
|
Loading…
Reference in New Issue
Block a user