aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile26
-rw-r--r--adapter.c301
-rw-r--r--include/adapter.h (renamed from adapter.h)17
-rw-r--r--include/event_notifier.h (renamed from event_notifier.h)0
-rw-r--r--include/parser.h42
-rw-r--r--include/queue.h (renamed from queue.h)0
-rw-r--r--include/vhost_loopback.h (renamed from vhost_loopback.h)0
-rw-r--r--include/vhost_user_blk.h (renamed from vhost_user_blk.h)2
-rw-r--r--include/vhost_user_can.h (renamed from vhost_user_can.h)5
-rw-r--r--include/vhost_user_console.h (renamed from vhost_user_console.h)26
-rw-r--r--include/vhost_user_gpio.h (renamed from vhost_user_gpio.h)20
-rw-r--r--include/vhost_user_input.h30
-rw-r--r--include/vhost_user_loopback.h (renamed from vhost_user_loopback.h)87
-rw-r--r--include/vhost_user_rng.h (renamed from vhost_user_rng.h)3
-rw-r--r--include/vhost_user_sound.h (renamed from vhost_user_sound.h)22
-rw-r--r--include/virtio_loopback.h (renamed from virtio_loopback.h)61
-rw-r--r--include/virtio_rng.h (renamed from virtio_rng.h)5
-rw-r--r--linux/.fuse_hidden001086ab000006dabin0 -> 16384 bytes
-rw-r--r--linux/virtio_gpio.h72
-rw-r--r--linux/virtio_snd.h334
-rw-r--r--src/common/event_notifier.c (renamed from event_notifier.c)3
-rw-r--r--src/devices/vhost_user_blk.c (renamed from vhost_user_blk.c)432
-rw-r--r--src/devices/vhost_user_can.c179
-rw-r--r--src/devices/vhost_user_console.c175
-rw-r--r--src/devices/vhost_user_gpio.c204
-rw-r--r--src/devices/vhost_user_input.c154
-rw-r--r--src/devices/vhost_user_rng.c112
-rw-r--r--src/devices/vhost_user_sound.c178
-rw-r--r--src/devices/virtio_rng.c (renamed from virtio_rng.c)27
-rw-r--r--src/lib/vhost_loopback.c (renamed from vhost_loopback.c)18
-rw-r--r--src/lib/vhost_user_loopback.c (renamed from vhost_user_loopback.c)389
-rw-r--r--src/lib/virtio_loopback.c (renamed from virtio_loopback.c)307
-rw-r--r--vhost_user_can.c329
-rw-r--r--vhost_user_console.c302
-rw-r--r--vhost_user_gpio.c393
-rw-r--r--vhost_user_input.c241
-rw-r--r--vhost_user_input.h158
-rw-r--r--vhost_user_rng.c219
-rw-r--r--vhost_user_sound.c322
-rw-r--r--virtio_blk.h95
-rw-r--r--virtio_input.c331
41 files changed, 1779 insertions, 3842 deletions
diff --git a/Makefile b/Makefile
index 33af630..846fa6f 100644
--- a/Makefile
+++ b/Makefile
@@ -18,8 +18,7 @@
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#CFLAGS := -Wno-unused-variable -Wno-unused-function -D_GNU_SOURCE
-CFLAGS = -D_GNU_SOURCE -O2 -Wall -Wextra -Werror
+CFLAGS := -D_GNU_SOURCE -O2 -Wall -Wextra -Werror -Wno-unused-variable -Wno-unused-function
CC ?=
@@ -27,14 +26,29 @@ ifeq ($(ARCH), arm64)
# arm64
CC ?= aarch64-linux-gnu-gcc
else
- CC ?= gcc
+ ifeq ($(ARCH), riscv64)
+ # arm64
+ CC ?= riscv64-linux-gnu-gcc
+ else
+ CC ?= gcc
+ endif
endif
INCL += -I .
+INCL += -I ./include/
+
DEPS = adapter.h vhost_user_loopback.h event_notifier.h virtio_loopback.h
-SRC_C = event_notifier.c vhost_user_loopback.c virtio_loopback.c virtio_rng.c virtio_input.c vhost_user_input.c vhost_user_blk.c vhost_user_rng.c vhost_user_sound.c vhost_user_gpio.c vhost_user_can.c vhost_user_console.c vhost_loopback.c adapter.c
+# Source directories
+SRC_DIRS = src/adapter src/lib src/common src/lib src/devices
+
+# Source files
+SRC_C = $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.c))
+
+# Object files
OBJS = $(SRC_C:.c=.o)
+
+# Binary output
BINS = adapter
ifeq ($(DEBUG), 1)
@@ -43,15 +57,17 @@ endif
all: $(BINS)
+# Linking
$(BINS): $(OBJS)
@echo -e "CC\t$@"
$(CC) $(CFLAGS) $(INCL) $^ -o $@ -lpthread
+# Compilation
%.o: %.c
@echo -e "CC\t$@"
$(CC) $(CFLAGS) $(INCL) -c $< -o $@
clean:
- rm -f *.o *~ $(BINS)
+ rm -f $(OBJS) *~ $(BINS)
.PHONY: all
diff --git a/adapter.c b/adapter.c
deleted file mode 100644
index 1dbde9b..0000000
--- a/adapter.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright 2022-2023 Virtual Open Systems SAS
- *
- * Authors:
- * Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>
- * Stefanos Gerangelos <s.gerangelos@virtualopensystems.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/eventfd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <pthread.h>
-#include <stdbool.h>
-#include <sys/param.h>
-#include <assert.h>
-
-/* For socket */
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-/* Project header files */
-#include "adapter.h"
-
-/* Global variables */
-int client_sock;
-struct vhost_dev *dev;
-struct adapter_dev *adev;
-struct vhost_user *vudev;
-
-void vhost_user_adapter_init(void)
-{
-
- DBG("Setup adapter data structures\n");
-
- /* Init vhost-user device */
- vudev = (struct vhost_user *)malloc(sizeof(struct vhost_user));
-
- /* Init vhost device */
- dev = (struct vhost_dev *)malloc(sizeof(struct vhost_dev));
-
- /* Init virtio device */
- global_vdev = (VirtIODevice *)malloc(sizeof(VirtIODevice));
-
- /* Init virtio bus */
- global_vbus = (VirtioBus *)malloc(sizeof(VirtioBus));
- global_vbus->vdev = global_vdev;
- global_vdev->vbus = global_vbus;
- global_vdev->vhdev = dev;
-
-
- /* Store virtio_dev reference into vhost_dev struct*/
- dev->vdev = global_vdev;
-
- /* Init adapter device */
- adev = (struct adapter_dev *)malloc(sizeof(struct adapter_dev));
- adev->vdev = dev;
- adev->vudev = vudev;
- adev->virtio_dev = global_vdev;
- adev->vbus = global_vbus;
-}
-
-void client(char *sock_path)
-{
- int rc, len;
- struct sockaddr_un client_sockaddr;
-
- DBG("Create shared socket with vhost-user-device\n");
-
- /* Initialize the struct to zero */
- memset(&client_sockaddr, 0, sizeof(struct sockaddr_un));
-
- /*
- * Create a UNIX socket
- */
- client_sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (client_sock == -1) {
- DBG("SOCKET ERROR\n");
- exit(1);
- }
-
- /*
- * Set up the UNIX sockaddr structure
- * by using AF_UNIX for the family and
- * giving it a filepath to connect.
- */
- client_sockaddr.sun_family = AF_UNIX;
- strcpy(client_sockaddr.sun_path, sock_path);
- len = sizeof(client_sockaddr);
- rc = connect(client_sock, (struct sockaddr *) &client_sockaddr, len);
- if (rc == -1) {
- printf("CONNECT ERROR: Check the \"-s\" parameter\n");
- close(client_sock);
- exit(1);
- }
-}
-
-static void help_args(void)
-{
- printf("Run example:\n\t./adapter -s /path_to_socket/rng.sock\n"
- "\t\t -d device_name\n"
- "\t\t [ -qn number of queues ]\n"
- "\t\t [ -qs size of queues ]\n"
- "The 'device_name' can be one of the following:\n"
- "\tvrng, vhurng, vhublk, vhuinput, vhusnd, vhugpio, vhucan, vhuconsole\n");
-}
-
-int find_arg(int argc, char **argv, char *str)
-{
- int i;
-
- for (i = 0; i < argc; i++) {
- if (!strcmp(argv[i], str)) {
- return i + 1;
- }
- }
- return -1;
-}
-
-int val_device_arg(char *str)
-{
- int adapter_devices_num = ADAPTER_DEVS, i;
-
- for (i = 0; i < adapter_devices_num; i++) {
- if (!strcmp(adapter_devices[i], str)) {
- return i + 1;
- }
- }
-
- return 0;
-}
-
-bool check_vhu_device(char *str)
-{
- int vhu_devices_num = VHU_DEVS, i;
-
- for (i = 0; i < vhu_devices_num; i++) {
- if (!strcmp(vhu_devices[i], str)) {
- return true;
- }
- }
-
- return false;
-}
-
-void get_queue_num_size_args(int argc, char **argv,
- int *eval_queue_num, int *eval_queue_size)
-{
- int queue_num, queue_size, queue_num_id, queue_size_id;
-
- if (argc < 9) {
- return;
- }
-
- queue_num_id = find_arg(argc, argv, "-qn");
- queue_size_id = find_arg(argc, argv, "-qs");
-
- /* Check if both qs ans qn exist */
- if (queue_num_id < 0 || queue_size_id < 0) {
- return;
- }
-
- queue_num = atoi(argv[queue_num_id]);
- queue_size = atoi(argv[queue_size_id]);
-
- /* Evaluate number of queues */
- if (queue_num <= 0 || queue_num > 16) {
- return;
- }
-
- /* Evaluate queues' size */
- if (queue_size <= 0 || queue_size > 1024) {
- return;
- }
-
- *eval_queue_num = queue_num;
- *eval_queue_size = queue_size;
-}
-
-
-int main(int argc, char **argv)
-{
- int socket_idx, device_idx, device_id;
- bool vhost_user_enabled;
- /* Assign default queue num and size */
- int queue_num = 1, queue_size = 64;
-
- /*
- * Check if the user has provided all the required arguments.
- * If not, print the help messages.
- */
-
- if (argc < 3) {
- goto error_args;
- }
-
- device_idx = find_arg(argc, argv, "-d");
-
- if (device_idx < 0) {
- printf("You have not specified parameter \"-d\"\n");
- goto error_args;
- }
-
- /* Validate the argumetns */
- device_id = val_device_arg(argv[device_idx]);
-
- if (device_id == 0) {
- goto error_args;
- }
-
- /* Check if this is a vhost-user device */
- vhost_user_enabled = check_vhu_device(argv[device_idx]);
-
- /* Check if a socket is needed and provided */
- socket_idx = find_arg(argc, argv, "-s");
-
- if ((socket_idx < 0) && (vhost_user_enabled)) {
- printf("You have not specified parameter \"-s\"\n");
- goto error_args;
- }
-
- /*
- * Create the socket and connect to the backend.
- * Enabled on vhost-user case
- */
- if (vhost_user_enabled) {
- client(argv[socket_idx]);
- }
-
- /* Initialize the adapter data structures */
- vhost_user_adapter_init();
-
- /* Get queue number and size from arguments */
- get_queue_num_size_args(argc, argv, &queue_num, &queue_size);
-
- /* Initialize the virtio/vhost-user device */
- /* TODO: Switch numbers with name defs */
- switch (device_id) {
- case 1:
- virtio_rng_realize(queue_num, queue_size);
- break;
- case 2:
- vhost_user_rng_realize(queue_num, queue_size);
- break;
- case 3:
- printf("Running vhublk with num %d and size %d\n",
- queue_num, queue_size);
- vhost_user_blk_realize(queue_num, queue_size);
- break;
- case 4:
- vhost_user_input_init(global_vdev);
- virtio_input_device_realize(queue_num, queue_size);
- break;
- case 5:
- vus_device_realize(queue_num, queue_size);
- break;
- case 6:
- vu_gpio_device_realize(queue_num, queue_size);
- break;
- case 7:
- vhost_user_can_realize(queue_num, queue_size);
- break;
- case 8:
- vhost_user_console_realize(queue_num, queue_size);
- break;
- default:
- exit(1);
- }
-
- /*
- * Start loopback trasnport layer and communiation with the loopback driver
- */
- virtio_loopback_start();
-
- return 0;
-
-error_args:
- help_args();
- return 1;
-}
diff --git a/adapter.h b/include/adapter.h
index 99a5856..601ed23 100644
--- a/adapter.h
+++ b/include/adapter.h
@@ -35,19 +35,10 @@
#include "vhost_user_can.h"
#include "vhost_user_console.h"
-#ifdef DEBUG
-#define DBG(...) printf("adapter: " __VA_ARGS__)
-#else
-#define DBG(...)
-#endif /* DEBUG */
+extern Device devices[MAX_DEVICES];
-#define VHU_DEVS 8
-#define ADAPTER_DEVS (VHU_DEVS + 1)
-
-const char *adapter_devices[] = {"vrng", "vhurng", "vhublk", "vhuinput",
- "vhusnd", "vhugpio", "vhucan",
- "vhuconsole" };
-const char *vhu_devices[] = {"vhurng", "vhublk", "vhuinput", "vhusnd",
- "vhugpio", "vhucan", "vhuconsole"};
+/* Global functions */
+int parse_args(int argc, char *argv[]);
+void help_args(void);
#endif /* ADAPTER */
diff --git a/event_notifier.h b/include/event_notifier.h
index 718f784..718f784 100644
--- a/event_notifier.h
+++ b/include/event_notifier.h
diff --git a/include/parser.h b/include/parser.h
new file mode 100644
index 0000000..f37e41d
--- /dev/null
+++ b/include/parser.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2022-2024 Virtual Open Systems SAS.
+ *
+ * Author:
+ * Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PARSER_H
+#define PARSER_H
+
+/* Project header files */
+#include "adapter.h"
+
+// Default values for queue_num and queue_size
+#define DEFAULT_QUEUE_NUM 1
+#define DEFAULT_QUEUE_SIZE 1024
+
+/* Global variables */
+const char *adapter_devices[] = {"vrng", "vhurng", "vhublk",
+ "vhuinput", "vhusnd", "vhugpio",
+ "vhucan", "vhuconsole"};
+const char *vhu_devices[] = {"vhurng", "vhublk", "vhuinput",
+ "vhusnd", "vhugpio", "vhucan",
+ "vhuconsole"};
+const unsigned int num_adapter_devices = sizeof(adapter_devices) / sizeof(adapter_devices[0]);
+const unsigned int num_vhu_devices = num_adapter_devices - 1;
+
+#endif /* PARSER_H */
diff --git a/queue.h b/include/queue.h
index e029e7b..e029e7b 100644
--- a/queue.h
+++ b/include/queue.h
diff --git a/vhost_loopback.h b/include/vhost_loopback.h
index 198a5af..198a5af 100644
--- a/vhost_loopback.h
+++ b/include/vhost_loopback.h
diff --git a/vhost_user_blk.h b/include/vhost_user_blk.h
index d5857c8..3b25dfe 100644
--- a/vhost_user_blk.h
+++ b/include/vhost_user_blk.h
@@ -54,6 +54,6 @@ struct VHostUserBlk {
bool started_vu;
};
-void vhost_user_blk_realize(int queue_num, int queue_size);
+void vhost_user_blk_realize(struct adapter_dev *adev);
#endif /* VHOST_USER_BLK */
diff --git a/vhost_user_can.h b/include/vhost_user_can.h
index a4615be..4768499 100644
--- a/vhost_user_can.h
+++ b/include/vhost_user_can.h
@@ -43,15 +43,12 @@ typedef struct VHostUserCan {
uint32_t queue_size;
struct virtio_can_config config;
struct vhost_dev *vhost_dev;
- VirtQueue *ctrl_vq;
- VirtQueue *tx_vq;
- VirtQueue *rx_vq;
/* Support classic CAN */
bool support_can_classic;
/* Support CAN FD */
bool support_can_fd;
} VHostUserCan;
-void vhost_user_can_realize(int queue_num, int queue_size);
+void vhost_user_can_realize(struct adapter_dev *adev);
#endif /* VHOST_USER_CAN */
diff --git a/vhost_user_console.h b/include/vhost_user_console.h
index f1a03eb..9f0eed8 100644
--- a/vhost_user_console.h
+++ b/include/vhost_user_console.h
@@ -20,16 +20,6 @@
#define VIRTIO_CONSOLE_F_MULTIPORT 1 /* Does host provide multiple ports? */
#define VIRTIO_CONSOLE_F_EMERG_WRITE 2 /* Does host support emergency write? */
-/* Some events for control messages */
-#define VIRTIO_CONSOLE_DEVICE_READY 0
-#define VIRTIO_CONSOLE_PORT_ADD 1
-#define VIRTIO_CONSOLE_PORT_REMOVE 2
-#define VIRTIO_CONSOLE_PORT_READY 3
-#define VIRTIO_CONSOLE_CONSOLE_PORT 4
-#define VIRTIO_CONSOLE_RESIZE 5
-#define VIRTIO_CONSOLE_PORT_OPEN 6
-#define VIRTIO_CONSOLE_PORT_NAME 7
-
struct virtio_console_config {
/* colums of the screens */
__virtio16 cols;
@@ -41,16 +31,6 @@ struct virtio_console_config {
__virtio32 emerg_wr;
};
-/*
- * A message that's passed between the Host and the Guest for a
- * particular port.
- */
-struct virtio_console_control {
- __virtio32 id; /* Port number */
- __virtio16 event; /* The kind of control event (see below) */
- __virtio16 value; /* Extra information for the key */
-};
-
typedef struct VHostUserConsole {
VirtIODevice *parent;
struct vhost_virtqueue *vhost_vqs;
@@ -59,12 +39,8 @@ typedef struct VHostUserConsole {
uint32_t queue_size;
struct virtio_console_config config;
struct vhost_dev *vhost_dev;
- VirtQueue *rx_vq;
- VirtQueue *tx_vq;
- VirtQueue *ctrl_rx_vq;
- VirtQueue *ctrl_tx_vq;
} VHostUserConsole;
-void vhost_user_console_realize(int queue_num, int queue_size);
+void vhost_user_console_realize(struct adapter_dev *adev);
#endif /* VHOST_USER_CONSOLE */
diff --git a/vhost_user_gpio.h b/include/vhost_user_gpio.h
index 7bf8ac8..4d77e0a 100644
--- a/vhost_user_gpio.h
+++ b/include/vhost_user_gpio.h
@@ -1,7 +1,7 @@
/*
* Based on virtio-gpio.h of QEMU project
*
- * Copyright (c) 2023 Virtual Open Systems SAS.
+ * Copyright (c) 2023-2024 Virtual Open Systems SAS.
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version. See the COPYING file in the
@@ -14,24 +14,24 @@
#include "vhost_loopback.h"
#include "vhost_user_loopback.h"
#include "virtio_loopback.h"
-#include <linux/virtio_gpio.h>
-#include "queue.h"
-#include <sys/mman.h>
-#define TYPE_VHOST_USER_GPIO "vhost-user-gpio-device"
#define VIRTIO_GPIO_F_IRQ 0
+struct virtio_gpio_config {
+ uint16_t ngpio;
+ uint8_t padding[2];
+ uint32_t gpio_names_size;
+};
+
struct VHostUserGPIO {
VirtIODevice *parent;
struct virtio_gpio_config config;
struct vhost_virtqueue *vhost_vqs;
struct vhost_dev *vhost_dev;
- VirtQueue *command_vq;
- VirtQueue *interrupt_vq;
- bool connected;
- bool started_vu;
+ uint16_t num_queues;
+ uint32_t queue_size;
};
-void vu_gpio_device_realize(int queue_num, int queue_size);
+void vu_gpio_device_realize(struct adapter_dev *adev);
#endif /* VHOST_USER_GPIO */
diff --git a/include/vhost_user_input.h b/include/vhost_user_input.h
new file mode 100644
index 0000000..8137694
--- /dev/null
+++ b/include/vhost_user_input.h
@@ -0,0 +1,30 @@
+/*
+ * Based on virtio-input.h of QEMU project
+ *
+ * Copyright (c) 2022-2024 Virtual Open Systems SAS.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ */
+
+#ifndef VHOST_USER_INPUT
+#define VHOST_USER_INPUT
+
+#include "vhost_loopback.h"
+#include "vhost_user_loopback.h"
+#include "virtio_loopback.h"
+#include <linux/virtio_input.h>
+
+typedef struct VhostUserInput {
+ VirtIODevice *parent;
+ struct vhost_dev *vhost_dev;
+ struct virtio_input_config config;
+ VirtQueue *evt, *sts;
+ bool started;
+ bool completed;
+} VhostUserInput;
+
+void virtio_input_device_realize(struct adapter_dev *adev);
+
+#endif /* VHOST_USER_INPUT */
diff --git a/vhost_user_loopback.h b/include/vhost_user_loopback.h
index 14919e1..3aa8e8c 100644
--- a/vhost_user_loopback.h
+++ b/include/vhost_user_loopback.h
@@ -36,16 +36,6 @@
#include "virtio_loopback.h"
#include "queue.h"
-typedef struct adapter_dev {
- struct vhost_dev *vdev;
- struct vhost_user *vudev;
- VirtIODevice *virtio_dev;
- VirtioBus *vbus;
-} AdapterDev;
-
-
-
-
struct scrub_regions {
struct vhost_memory_region *region;
int reg_idx;
@@ -89,6 +79,7 @@ typedef struct MemoryRegionSection {
struct vhost_dev {
VirtIODevice *vdev;
+ struct vhost_user *vhudev;
struct vhost_memory *mem;
int n_mem_sections;
MemoryRegionSection *mem_sections;
@@ -120,7 +111,7 @@ struct vhost_dev {
};
-#define VHOST_USER_MAX_RAM_SLOTS 32
+#define VHOST_USER_MAX_RAM_SLOTS 16
typedef uint64_t ram_addr_t;
typedef struct RAMBlock RAMBlock;
@@ -236,11 +227,47 @@ struct vhost_user {
struct vhost_memory_region shadow_regions[VHOST_USER_MAX_RAM_SLOTS];
};
-/* Global variables */
-extern int client_sock;
-extern struct vhost_dev *dev;
-extern struct adapter_dev *adev;
-extern struct vhost_user *vudev;
+#define MAX_DEVICES 100
+#define MAX_NAME_LENGTH 256
+#define MAX_SOCKET_LENGTH 256
+
+typedef struct Device {
+ char device_name[MAX_NAME_LENGTH];
+ char socket[MAX_SOCKET_LENGTH];
+ int queue_num;
+ int queue_size;
+ int device_index;
+ int requires_socket;
+ int client_socket;
+} Device;
+
+typedef struct adapter_dev {
+ struct vhost_dev vdev;
+ struct vhost_user vudev;
+ VirtIODevice virtio_dev;
+ VirtioBus vbus;
+ Device *device_params;
+ /* More variables */
+ int loopback_fd;
+ int efd; /* Eventfd file descriptor */
+ virtio_neg_t *address;
+ virtio_device_info_struct_t device_info;
+ VirtIOMMIOProxy proxy;
+} AdapterDev;
+
+#define container_of_a(ptr, type, member) \
+ ((type *)((char *)(ptr) - offsetof(type, member)))
+
+/*
+#define to_vhost_user_device(ptr, field) \
+ container_of_a(ptr, struct vhost_user, field)
+
+#define virtio_to_vhost_dev(ptr, field) \
+ container_of_a(ptr, struct vhost_dev, field)
+
+*/
+#define to_adapter_device(ptr, field) \
+ container_of(ptr, struct adapter_dev, field)
/* Based on qemu/hw/virtio/vhost-user.c */
#define VHOST_USER_F_PROTOCOL_FEATURES 30
@@ -912,20 +939,21 @@ bool vu_queue_avail_bytes(VuDev *dev, VuVirtq *vq, unsigned int in_bytes,
bool vhost_user_one_time_request(VhostUserRequest request);
void vmsg_close_fds(VhostUserMsg *vmsg);
-int vhost_user_set_owner(void);
-int process_message_reply(const VhostUserMsg *msg);
-int vhost_user_get_u64(int request, uint64_t *u64);
-int vhost_user_get_features(uint64_t *features);
-int enforce_reply(const VhostUserMsg *msg);
-int vhost_user_set_u64(int request, uint64_t u64, bool wait_for_reply);
-int vhost_user_set_protocol_features(uint64_t features);
-int vhost_user_get_max_memslots(uint64_t *max_memslots);
+int vhost_user_set_owner(struct vhost_dev *dev);
+int process_message_reply(struct vhost_dev *dev, const VhostUserMsg *msg);
+int vhost_user_get_u64(struct vhost_dev *dev, int request, uint64_t *u64);
+int vhost_user_get_features(struct vhost_dev *dev, uint64_t *features);
+int enforce_reply(struct vhost_dev *dev, const VhostUserMsg *msg);
+int vhost_user_set_u64(struct vhost_dev *dev, int request, uint64_t u64, bool wait_for_reply);
+int vhost_user_set_protocol_features(struct vhost_dev *dev, uint64_t features);
+int vhost_user_get_max_memslots(struct vhost_dev *dev, uint64_t *max_memslots);
int vhost_setup_slave_channel(struct vhost_dev *dev);
int vhost_user_get_vq_index(struct vhost_dev *dev, int idx);
-int vhost_set_vring_file(VhostUserRequest request,
- struct vhost_vring_file *file);
-int vhost_user_set_vring_kick(struct vhost_vring_file *file);
-int vhost_user_set_vring_call(struct vhost_vring_file *file);
+int vhost_set_vring_file(struct vhost_dev *dev,
+ VhostUserRequest request,
+ struct vhost_vring_file *file);
+int vhost_user_set_vring_kick(struct vhost_dev *dev, struct vhost_vring_file *file);
+int vhost_user_set_vring_call(struct vhost_dev *dev, struct vhost_vring_file *file);
int vhost_virtqueue_init(struct vhost_dev *dev,
struct vhost_virtqueue *vq, int n);
void vhost_dev_init(struct vhost_dev *vhdev);
@@ -953,7 +981,7 @@ void vhost_commit_vqs(struct vhost_dev *dev);
void find_add_new_reg(struct vhost_dev *dev);
void print_mem_table(struct vhost_dev *dev);
void print_vhost_user_messages(int request);
-
+void vhost_user_dev_class_init(VirtIODevice *vdev);
/* FIXME: This need to move in a better place */
struct vhost_inflight;
@@ -963,5 +991,4 @@ int vhost_user_get_inflight_fd(struct vhost_dev *dev,
int vhost_user_set_inflight_fd(struct vhost_dev *dev,
struct vhost_inflight *inflight);
-
#endif /* LIBVHOST_USER_H */
diff --git a/vhost_user_rng.h b/include/vhost_user_rng.h
index 4627c50..b6f58da 100644
--- a/vhost_user_rng.h
+++ b/include/vhost_user_rng.h
@@ -39,6 +39,5 @@ typedef struct VHostUserRNG {
bool connected;
} VHostUserRNG;
-void vhost_user_rng_realize(int queue_num, int queue_size);
-
+void vhost_user_rng_realize(struct adapter_dev *adev);
#endif /* VHOST_USER_RNG */
diff --git a/vhost_user_sound.h b/include/vhost_user_sound.h
index d802bc0..e63e9d3 100644
--- a/vhost_user_sound.h
+++ b/include/vhost_user_sound.h
@@ -3,7 +3,7 @@
*
* Copyright 2020 Red Hat, Inc.
*
- * Copyright (c) 2023 Virtual Open Systems SAS.
+ * Copyright (c) 2023-2024 Virtual Open Systems SAS.
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version. See the COPYING file in the
@@ -17,10 +17,17 @@
#include "virtio_loopback.h"
#include "vhost_loopback.h"
#include "vhost_user_loopback.h"
-#include <linux/virtio_snd.h>
+
+struct virtio_snd_config {
+ /* # of available physical jacks */
+ uint32_t jacks;
+ /* # of available PCM streams */
+ uint32_t streams;
+ /* # of available channel maps */
+ uint32_t chmaps;
+};
typedef struct VHostUserSound {
- /*< private >*/
VirtIODevice *parent;
struct vhost_virtqueue *vhost_vqs;
VirtQueue **virtqs;
@@ -28,13 +35,8 @@ typedef struct VHostUserSound {
uint32_t queue_size;
struct virtio_snd_config config;
struct vhost_dev *vhost_dev;
- VirtQueue *ctrl_vq;
- VirtQueue *event_vq;
- VirtQueue *tx_vq;
- VirtQueue *rx_vq;
- /*< public >*/
} VHostUserSound;
-void vus_device_realize(int queue_num, int queue_size);
+void vus_device_realize(struct adapter_dev *adev);
-#endif /* VHOST_USER_BLK */
+#endif /* VHOST_USER_SOUND */
diff --git a/virtio_loopback.h b/include/virtio_loopback.h
index 62e404c..d8e68f1 100644
--- a/virtio_loopback.h
+++ b/include/virtio_loopback.h
@@ -165,7 +165,7 @@
sizeof(virtio_device_info_struct_t))
#define IRQ _IOC(_IOC_WRITE, 'k', 4, sizeof(int))
#define SHARE_VQS _IOC(_IOC_WRITE, 'k', 5, sizeof(uint32_t))
-#define SHARE_COM_STRUCT _IOC(_IOC_WRITE, 'k', 7, 0)
+#define SHARE_COM_STRUCT _IOC(_IOC_WRITE, 'k', 6, 0)
#define VIRTIO_PCI_VRING_ALIGN 4096
@@ -254,14 +254,10 @@ typedef struct VirtIOMMIOProxy {
#define VRING_DESC_ALIGN_SIZE 16
/******************/
-
#define container_of(ptr, type, member) ({ \
const typeof(((type *) 0)->member) *__mptr = (ptr); \
(type *) ((char *) __mptr - offsetof(type, member));})
-extern uint64_t vring_phys_addrs[10];
-extern uint32_t vring_phys_addrs_idx;
-
typedef struct VRing {
unsigned int num;
unsigned int num_default;
@@ -356,7 +352,6 @@ typedef struct VirtQueue {
} VirtQueue;
typedef struct VirtIORNG VirtIORNG;
-typedef struct VirtIOInput VirtIOInput;
typedef struct VHostUserRNG VHostUserRNG;
typedef struct VirtioDeviceClass VirtioDeviceClass;
typedef struct VHostUserBlk VHostUserBlk;
@@ -382,10 +377,20 @@ typedef struct VirtIODevice {
void *config;
uint16_t config_vector;
uint32_t generation;
+ int last_avail;
+ int prev_level;
+ int int_count;
+ int eventfd_count;
+ int notify_cnt;
+ bool enable_virtio_interrupt;
+ pthread_mutex_t interrupt_lock;
int nvectors;
VirtQueue *vq;
VirtQueue **vqs;
int *nvqs;
+ /* TODO: Put a defined value for vq num */
+ uint64_t vring_phys_addrs[12];
+ uint32_t vring_phys_addrs_idx;
uint16_t device_id;
bool vm_running;
bool broken; /* device in invalid state, needs reset */
@@ -398,16 +403,17 @@ typedef struct VirtIODevice {
char *bus_name;
uint8_t device_endian;
bool use_guest_notifier_mask;
- /* TODO: Switch to union? */
- VirtIORNG *vrng;
- VirtIOInput *vinput;
- VHostUserRNG *vhrng;
- VHostUserBlk *vhublk;
- VhostUserInput *vhuinput;
- VHostUserSound *vhusnd;
- VHostUserGPIO *vhugpio;
- VHostUserCan *vhucan;
- VHostUserConsole *vhuconsole;
+ union {
+ VirtIORNG *vrng;
+ VHostUserRNG *vhrng;
+ VHostUserBlk *vhublk;
+ VhostUserInput *vhuinput;
+ VHostUserSound *vhusnd;
+ VHostUserGPIO *vhugpio;
+ VHostUserCan *vhucan;
+ VHostUserConsole *vhuconsole;
+ };
+ const int *user_feature_bits;
} VirtIODevice;
typedef struct efd_data {
@@ -520,6 +526,7 @@ typedef struct VirtioBus {
int ioeventfd_grabbed;
} VirtioBus;
+struct adapter_dev;
typedef struct VirtioDeviceClass {
/*< private >*/
@@ -535,8 +542,10 @@ typedef struct VirtioDeviceClass {
void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
void (*reset)(VirtIODevice *vdev);
void (*set_status)(VirtIODevice *vdev, uint8_t val);
- void (*realize)(int queue_num, int queue_size);
+ void (*realize)(struct adapter_dev *adev);
void (*unrealize)(VirtIODevice *vdev);
+ void (*start)(VirtIODevice *vdev);
+ void (*stop)(VirtIODevice *vdev);
/*
* For transitional devices, this is a bitmap of features
* that are only exposed on the legacy interface but not
@@ -578,19 +587,15 @@ typedef struct VirtioDeviceClass {
struct vhost_dev *(*get_vhost)(VirtIODevice *vdev);
} VirtioDeviceClass;
-/* Global variables */
-extern int fd;
-extern int loopback_fd;
-
void handle_input(VirtIODevice *vdev, VirtQueue *vq);
void *my_select(void *data);
void *wait_read_write(void *data);
void virtio_notify_config(VirtIODevice *vdev);
-void create_rng_struct(void);
void print_neg_flag(uint64_t neg_flag, bool read);
-void adapter_read_write_cb(void);
-int virtio_loopback_start(void);
+void adapter_read_write_cb(struct adapter_dev *adev);
+int virtio_loopback_start(struct adapter_dev *adev, pthread_t *thread_id);
+void virtio_loopback_stop(struct adapter_dev *adev);
int virtio_queue_ready(VirtQueue *vq);
void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
unsigned int *out_bytes,
@@ -657,6 +662,8 @@ uint32_t get_vqs_max_size(VirtIODevice *vdev);
#define VIRTIO_CONFIG_S_DRIVER_OK 4
#define VIRTIO_F_VERSION_1 32
#define VIRTIO_F_ACCESS_PLATFORM 33
+#define VIRTIO_F_IN_ORDER 35
+#define VIRTIO_F_NOTIFICATION_DATA 38
/*
* Legacy name for VIRTIO_F_ACCESS_PLATFORM
@@ -705,10 +712,4 @@ uint32_t get_vqs_max_size(VirtIODevice *vdev);
*/
#define INIT_PA 0
-
-extern VirtIODevice *global_vdev;
-extern VirtIOMMIOProxy *proxy;
-extern VirtioBus *global_vbus;
-
#endif /* VIRTIO_LOOPBACK */
-
diff --git a/virtio_rng.h b/include/virtio_rng.h
index 4264b45..6e97294 100644
--- a/virtio_rng.h
+++ b/include/virtio_rng.h
@@ -20,6 +20,7 @@
#define VIRTIO_RNG_DEV
#include "virtio_loopback.h"
+#include "vhost_user_loopback.h"
extern const char test_str[64];
@@ -48,8 +49,8 @@ bool is_guest_ready(VirtIORNG *vrng);
size_t get_request_size(VirtQueue *vq, unsigned quota);
void virtio_rng_set_status(VirtIODevice *vdev, uint8_t status);
void virtio_rng_process(VirtIORNG *vrng);
-void chr_read(VirtIORNG *vrng, const void *buf, size_t size);
-void virtio_rng_realize(int queue_num, int queue_size);
+void chr_read(VirtIORNG *vrng, const char *buf, size_t size);
+void virtio_rng_realize(struct adapter_dev *adev);
void virtio_rng_init(VirtIODevice *vdev);
#endif /* VIRTIO_RNG */
diff --git a/linux/.fuse_hidden001086ab000006da b/linux/.fuse_hidden001086ab000006da
new file mode 100644
index 0000000..ce99873
--- /dev/null
+++ b/linux/.fuse_hidden001086ab000006da
Binary files differ
diff --git a/linux/virtio_gpio.h b/linux/virtio_gpio.h
deleted file mode 100644
index d4b29d9..0000000
--- a/linux/virtio_gpio.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-
-#ifndef _LINUX_VIRTIO_GPIO_H
-#define _LINUX_VIRTIO_GPIO_H
-
-#include <linux/types.h>
-
-/* Virtio GPIO Feature bits */
-#define VIRTIO_GPIO_F_IRQ 0
-
-/* Virtio GPIO request types */
-#define VIRTIO_GPIO_MSG_GET_NAMES 0x0001
-#define VIRTIO_GPIO_MSG_GET_DIRECTION 0x0002
-#define VIRTIO_GPIO_MSG_SET_DIRECTION 0x0003
-#define VIRTIO_GPIO_MSG_GET_VALUE 0x0004
-#define VIRTIO_GPIO_MSG_SET_VALUE 0x0005
-#define VIRTIO_GPIO_MSG_IRQ_TYPE 0x0006
-
-/* Possible values of the status field */
-#define VIRTIO_GPIO_STATUS_OK 0x0
-#define VIRTIO_GPIO_STATUS_ERR 0x1
-
-/* Direction types */
-#define VIRTIO_GPIO_DIRECTION_NONE 0x00
-#define VIRTIO_GPIO_DIRECTION_OUT 0x01
-#define VIRTIO_GPIO_DIRECTION_IN 0x02
-
-/* Virtio GPIO IRQ types */
-#define VIRTIO_GPIO_IRQ_TYPE_NONE 0x00
-#define VIRTIO_GPIO_IRQ_TYPE_EDGE_RISING 0x01
-#define VIRTIO_GPIO_IRQ_TYPE_EDGE_FALLING 0x02
-#define VIRTIO_GPIO_IRQ_TYPE_EDGE_BOTH 0x03
-#define VIRTIO_GPIO_IRQ_TYPE_LEVEL_HIGH 0x04
-#define VIRTIO_GPIO_IRQ_TYPE_LEVEL_LOW 0x08
-
-struct virtio_gpio_config {
- __le16 ngpio;
- __u8 padding[2];
- __le32 gpio_names_size;
-};
-
-/* Virtio GPIO Request / Response */
-struct virtio_gpio_request {
- __le16 type;
- __le16 gpio;
- __le32 value;
-};
-
-struct virtio_gpio_response {
- __u8 status;
- __u8 value;
-};
-
-struct virtio_gpio_response_get_names {
- __u8 status;
- __u8 value[];
-};
-
-/* Virtio GPIO IRQ Request / Response */
-struct virtio_gpio_irq_request {
- __le16 gpio;
-};
-
-struct virtio_gpio_irq_response {
- __u8 status;
-};
-
-/* Possible values of the interrupt status field */
-#define VIRTIO_GPIO_IRQ_STATUS_INVALID 0x0
-#define VIRTIO_GPIO_IRQ_STATUS_VALID 0x1
-
-#endif /* _LINUX_VIRTIO_GPIO_H */
diff --git a/linux/virtio_snd.h b/linux/virtio_snd.h
deleted file mode 100644
index dfe4954..0000000
--- a/linux/virtio_snd.h
+++ /dev/null
@@ -1,334 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause */
-/*
- * Copyright (C) 2021 OpenSynergy GmbH
- */
-#ifndef VIRTIO_SND_IF_H
-#define VIRTIO_SND_IF_H
-
-#include <linux/virtio_types.h>
-
-/*******************************************************************************
- * CONFIGURATION SPACE
- */
-struct virtio_snd_config {
- /* # of available physical jacks */
- __le32 jacks;
- /* # of available PCM streams */
- __le32 streams;
- /* # of available channel maps */
- __le32 chmaps;
-};
-
-enum {
- /* device virtqueue indexes */
- VIRTIO_SND_VQ_CONTROL = 0,
- VIRTIO_SND_VQ_EVENT,
- VIRTIO_SND_VQ_TX,
- VIRTIO_SND_VQ_RX,
- /* # of device virtqueues */
- VIRTIO_SND_VQ_MAX
-};
-
-/*******************************************************************************
- * COMMON DEFINITIONS
- */
-
-/* supported dataflow directions */
-enum {
- VIRTIO_SND_D_OUTPUT = 0,
- VIRTIO_SND_D_INPUT
-};
-
-enum {
- /* jack control request types */
- VIRTIO_SND_R_JACK_INFO = 1,
- VIRTIO_SND_R_JACK_REMAP,
-
- /* PCM control request types */
- VIRTIO_SND_R_PCM_INFO = 0x0100,
- VIRTIO_SND_R_PCM_SET_PARAMS,
- VIRTIO_SND_R_PCM_PREPARE,
- VIRTIO_SND_R_PCM_RELEASE,
- VIRTIO_SND_R_PCM_START,
- VIRTIO_SND_R_PCM_STOP,
-
- /* channel map control request types */
- VIRTIO_SND_R_CHMAP_INFO = 0x0200,
-
- /* jack event types */
- VIRTIO_SND_EVT_JACK_CONNECTED = 0x1000,
- VIRTIO_SND_EVT_JACK_DISCONNECTED,
-
- /* PCM event types */
- VIRTIO_SND_EVT_PCM_PERIOD_ELAPSED = 0x1100,
- VIRTIO_SND_EVT_PCM_XRUN,
-
- /* common status codes */
- VIRTIO_SND_S_OK = 0x8000,
- VIRTIO_SND_S_BAD_MSG,
- VIRTIO_SND_S_NOT_SUPP,
- VIRTIO_SND_S_IO_ERR
-};
-
-/* common header */
-struct virtio_snd_hdr {
- __le32 code;
-};
-
-/* event notification */
-struct virtio_snd_event {
- /* VIRTIO_SND_EVT_XXX */
- struct virtio_snd_hdr hdr;
- /* optional event data */
- __le32 data;
-};
-
-/* common control request to query an item information */
-struct virtio_snd_query_info {
- /* VIRTIO_SND_R_XXX_INFO */
- struct virtio_snd_hdr hdr;
- /* item start identifier */
- __le32 start_id;
- /* item count to query */
- __le32 count;
- /* item information size in bytes */
- __le32 size;
-};
-
-/* common item information header */
-struct virtio_snd_info {
- /* function group node id (High Definition Audio Specification 7.1.2) */
- __le32 hda_fn_nid;
-};
-
-/*******************************************************************************
- * JACK CONTROL MESSAGES
- */
-struct virtio_snd_jack_hdr {
- /* VIRTIO_SND_R_JACK_XXX */
- struct virtio_snd_hdr hdr;
- /* 0 ... virtio_snd_config::jacks - 1 */
- __le32 jack_id;
-};
-
-/* supported jack features */
-enum {
- VIRTIO_SND_JACK_F_REMAP = 0
-};
-
-struct virtio_snd_jack_info {
- /* common header */
- struct virtio_snd_info hdr;
- /* supported feature bit map (1 << VIRTIO_SND_JACK_F_XXX) */
- __le32 features;
- /* pin configuration (High Definition Audio Specification 7.3.3.31) */
- __le32 hda_reg_defconf;
- /* pin capabilities (High Definition Audio Specification 7.3.4.9) */
- __le32 hda_reg_caps;
- /* current jack connection status (0: disconnected, 1: connected) */
- __u8 connected;
-
- __u8 padding[7];
-};
-
-/* jack remapping control request */
-struct virtio_snd_jack_remap {
- /* .code = VIRTIO_SND_R_JACK_REMAP */
- struct virtio_snd_jack_hdr hdr;
- /* selected association number */
- __le32 association;
- /* selected sequence number */
- __le32 sequence;
-};
-
-/*******************************************************************************
- * PCM CONTROL MESSAGES
- */
-struct virtio_snd_pcm_hdr {
- /* VIRTIO_SND_R_PCM_XXX */
- struct virtio_snd_hdr hdr;
- /* 0 ... virtio_snd_config::streams - 1 */
- __le32 stream_id;
-};
-
-/* supported PCM stream features */
-enum {
- VIRTIO_SND_PCM_F_SHMEM_HOST = 0,
- VIRTIO_SND_PCM_F_SHMEM_GUEST,
- VIRTIO_SND_PCM_F_MSG_POLLING,
- VIRTIO_SND_PCM_F_EVT_SHMEM_PERIODS,
- VIRTIO_SND_PCM_F_EVT_XRUNS
-};
-
-/* supported PCM sample formats */
-enum {
- /* analog formats (width / physical width) */
- VIRTIO_SND_PCM_FMT_IMA_ADPCM = 0, /* 4 / 4 bits */
- VIRTIO_SND_PCM_FMT_MU_LAW, /* 8 / 8 bits */
- VIRTIO_SND_PCM_FMT_A_LAW, /* 8 / 8 bits */
- VIRTIO_SND_PCM_FMT_S8, /* 8 / 8 bits */
- VIRTIO_SND_PCM_FMT_U8, /* 8 / 8 bits */
- VIRTIO_SND_PCM_FMT_S16, /* 16 / 16 bits */
- VIRTIO_SND_PCM_FMT_U16, /* 16 / 16 bits */
- VIRTIO_SND_PCM_FMT_S18_3, /* 18 / 24 bits */
- VIRTIO_SND_PCM_FMT_U18_3, /* 18 / 24 bits */
- VIRTIO_SND_PCM_FMT_S20_3, /* 20 / 24 bits */
- VIRTIO_SND_PCM_FMT_U20_3, /* 20 / 24 bits */
- VIRTIO_SND_PCM_FMT_S24_3, /* 24 / 24 bits */
- VIRTIO_SND_PCM_FMT_U24_3, /* 24 / 24 bits */
- VIRTIO_SND_PCM_FMT_S20, /* 20 / 32 bits */
- VIRTIO_SND_PCM_FMT_U20, /* 20 / 32 bits */
- VIRTIO_SND_PCM_FMT_S24, /* 24 / 32 bits */
- VIRTIO_SND_PCM_FMT_U24, /* 24 / 32 bits */
- VIRTIO_SND_PCM_FMT_S32, /* 32 / 32 bits */
- VIRTIO_SND_PCM_FMT_U32, /* 32 / 32 bits */
- VIRTIO_SND_PCM_FMT_FLOAT, /* 32 / 32 bits */
- VIRTIO_SND_PCM_FMT_FLOAT64, /* 64 / 64 bits */
- /* digital formats (width / physical width) */
- VIRTIO_SND_PCM_FMT_DSD_U8, /* 8 / 8 bits */
- VIRTIO_SND_PCM_FMT_DSD_U16, /* 16 / 16 bits */
- VIRTIO_SND_PCM_FMT_DSD_U32, /* 32 / 32 bits */
- VIRTIO_SND_PCM_FMT_IEC958_SUBFRAME /* 32 / 32 bits */
-};
-
-/* supported PCM frame rates */
-enum {
- VIRTIO_SND_PCM_RATE_5512 = 0,
- VIRTIO_SND_PCM_RATE_8000,
- VIRTIO_SND_PCM_RATE_11025,
- VIRTIO_SND_PCM_RATE_16000,
- VIRTIO_SND_PCM_RATE_22050,
- VIRTIO_SND_PCM_RATE_32000,
- VIRTIO_SND_PCM_RATE_44100,
- VIRTIO_SND_PCM_RATE_48000,
- VIRTIO_SND_PCM_RATE_64000,
- VIRTIO_SND_PCM_RATE_88200,
- VIRTIO_SND_PCM_RATE_96000,
- VIRTIO_SND_PCM_RATE_176400,
- VIRTIO_SND_PCM_RATE_192000,
- VIRTIO_SND_PCM_RATE_384000
-};
-
-struct virtio_snd_pcm_info {
- /* common header */
- struct virtio_snd_info hdr;
- /* supported feature bit map (1 << VIRTIO_SND_PCM_F_XXX) */
- __le32 features;
- /* supported sample format bit map (1 << VIRTIO_SND_PCM_FMT_XXX) */
- __le64 formats;
- /* supported frame rate bit map (1 << VIRTIO_SND_PCM_RATE_XXX) */
- __le64 rates;
- /* dataflow direction (VIRTIO_SND_D_XXX) */
- __u8 direction;
- /* minimum # of supported channels */
- __u8 channels_min;
- /* maximum # of supported channels */
- __u8 channels_max;
-
- __u8 padding[5];
-};
-
-/* set PCM stream format */
-struct virtio_snd_pcm_set_params {
- /* .code = VIRTIO_SND_R_PCM_SET_PARAMS */
- struct virtio_snd_pcm_hdr hdr;
- /* size of the hardware buffer */
- __le32 buffer_bytes;
- /* size of the hardware period */
- __le32 period_bytes;
- /* selected feature bit map (1 << VIRTIO_SND_PCM_F_XXX) */
- __le32 features;
- /* selected # of channels */
- __u8 channels;
- /* selected sample format (VIRTIO_SND_PCM_FMT_XXX) */
- __u8 format;
- /* selected frame rate (VIRTIO_SND_PCM_RATE_XXX) */
- __u8 rate;
-
- __u8 padding;
-};
-
-/*******************************************************************************
- * PCM I/O MESSAGES
- */
-
-/* I/O request header */
-struct virtio_snd_pcm_xfer {
- /* 0 ... virtio_snd_config::streams - 1 */
- __le32 stream_id;
-};
-
-/* I/O request status */
-struct virtio_snd_pcm_status {
- /* VIRTIO_SND_S_XXX */
- __le32 status;
- /* current device latency */
- __le32 latency_bytes;
-};
-
-/*******************************************************************************
- * CHANNEL MAP CONTROL MESSAGES
- */
-struct virtio_snd_chmap_hdr {
- /* VIRTIO_SND_R_CHMAP_XXX */
- struct virtio_snd_hdr hdr;
- /* 0 ... virtio_snd_config::chmaps - 1 */
- __le32 chmap_id;
-};
-
-/* standard channel position definition */
-enum {
- VIRTIO_SND_CHMAP_NONE = 0, /* undefined */
- VIRTIO_SND_CHMAP_NA, /* silent */
- VIRTIO_SND_CHMAP_MONO, /* mono stream */
- VIRTIO_SND_CHMAP_FL, /* front left */
- VIRTIO_SND_CHMAP_FR, /* front right */
- VIRTIO_SND_CHMAP_RL, /* rear left */
- VIRTIO_SND_CHMAP_RR, /* rear right */
- VIRTIO_SND_CHMAP_FC, /* front center */
- VIRTIO_SND_CHMAP_LFE, /* low frequency (LFE) */
- VIRTIO_SND_CHMAP_SL, /* side left */
- VIRTIO_SND_CHMAP_SR, /* side right */
- VIRTIO_SND_CHMAP_RC, /* rear center */
- VIRTIO_SND_CHMAP_FLC, /* front left center */
- VIRTIO_SND_CHMAP_FRC, /* front right center */
- VIRTIO_SND_CHMAP_RLC, /* rear left center */
- VIRTIO_SND_CHMAP_RRC, /* rear right center */
- VIRTIO_SND_CHMAP_FLW, /* front left wide */
- VIRTIO_SND_CHMAP_FRW, /* front right wide */
- VIRTIO_SND_CHMAP_FLH, /* front left high */
- VIRTIO_SND_CHMAP_FCH, /* front center high */
- VIRTIO_SND_CHMAP_FRH, /* front right high */
- VIRTIO_SND_CHMAP_TC, /* top center */
- VIRTIO_SND_CHMAP_TFL, /* top front left */
- VIRTIO_SND_CHMAP_TFR, /* top front right */
- VIRTIO_SND_CHMAP_TFC, /* top front center */
- VIRTIO_SND_CHMAP_TRL, /* top rear left */
- VIRTIO_SND_CHMAP_TRR, /* top rear right */
- VIRTIO_SND_CHMAP_TRC, /* top rear center */
- VIRTIO_SND_CHMAP_TFLC, /* top front left center */
- VIRTIO_SND_CHMAP_TFRC, /* top front right center */
- VIRTIO_SND_CHMAP_TSL, /* top side left */
- VIRTIO_SND_CHMAP_TSR, /* top side right */
- VIRTIO_SND_CHMAP_LLFE, /* left LFE */
- VIRTIO_SND_CHMAP_RLFE, /* right LFE */
- VIRTIO_SND_CHMAP_BC, /* bottom center */
- VIRTIO_SND_CHMAP_BLC, /* bottom left center */
- VIRTIO_SND_CHMAP_BRC /* bottom right center */
-};
-
-/* maximum possible number of channels */
-#define VIRTIO_SND_CHMAP_MAX_SIZE 18
-
-struct virtio_snd_chmap_info {
- /* common header */
- struct virtio_snd_info hdr;
- /* dataflow direction (VIRTIO_SND_D_XXX) */
- __u8 direction;
- /* # of valid channel position values */
- __u8 channels;
- /* channel position values (VIRTIO_SND_CHMAP_XXX) */
- __u8 positions[VIRTIO_SND_CHMAP_MAX_SIZE];
-};
-
-#endif /* VIRTIO_SND_IF_H */
diff --git a/event_notifier.c b/src/common/event_notifier.c
index 5b7c1cd..d4b08f7 100644
--- a/event_notifier.c
+++ b/src/common/event_notifier.c
@@ -80,6 +80,9 @@ void qemu_set_cloexec(int fd)
int f;
f = fcntl(fd, F_GETFD);
f = fcntl(fd, F_SETFD, f | FD_CLOEXEC);
+
+ /* TODO: Check the f value */
+ (void)f;
}
/*
diff --git a/vhost_user_blk.c b/src/devices/vhost_user_blk.c
index f0ae3d4..bba954b 100644
--- a/vhost_user_blk.c
+++ b/src/devices/vhost_user_blk.c
@@ -45,12 +45,26 @@
#define DBG(...)
#endif /* DEBUG */
+static const int user_feature_bits[] = {
+ VIRTIO_F_VERSION_1,
+ VIRTIO_RING_F_INDIRECT_DESC,
+ VIRTIO_RING_F_EVENT_IDX,
+ VIRTIO_F_RING_RESET,
+ VIRTIO_F_NOTIFY_ON_EMPTY,
+ VHOST_INVALID_FEATURE_BIT,
+ VIRTIO_BLK_F_SEG_MAX,
+ VIRTIO_BLK_F_GEOMETRY,
+ VIRTIO_BLK_F_TOPOLOGY,
+ VIRTIO_BLK_F_FLUSH,
+ VIRTIO_BLK_F_DISCARD,
+ VIRTIO_BLK_F_WRITE_ZEROES,
+ VIRTIO_BLK_F_BLK_SIZE,
+ VIRTIO_BLK_F_RO,
+ VIRTIO_BLK_F_CONFIG_WCE,
+ VIRTIO_BLK_F_MQ,
+};
-#define REALIZE_CONNECTION_RETRIES 3
-static uint64_t vhost_user_blk_get_features(VirtIODevice *vdev,
- uint64_t features);
-
-static int vhost_user_blk_start(VirtIODevice *vdev)
+static void vhost_user_blk_start(VirtIODevice *vdev)
{
VHostUserBlk *s = vdev->vhublk;
VirtioBus *k = vdev->vbus;
@@ -61,19 +75,19 @@ static int vhost_user_blk_start(VirtIODevice *vdev)
if (!k->set_guest_notifiers) {
DBG("binding does not support guest notifiers\n");
- return -1;
+ goto error;
}
ret = vhost_dev_enable_notifiers(s->vhost_dev, vdev);
if (ret < 0) {
DBG("Error enabling host notifiers\n");
- return ret;
+ goto error;
}
ret = k->set_guest_notifiers(k->vdev, s->vhost_dev->nvqs, true);
if (ret < 0) {
DBG("Error enabling host notifier\n");
- return ret;
+ goto error;
}
s->vhost_dev->acked_features = vdev->guest_features;
@@ -83,36 +97,31 @@ static int vhost_user_blk_start(VirtIODevice *vdev)
ret = vhost_dev_prepare_inflight(s->vhost_dev, vdev);
if (ret < 0) {
DBG("Error setting inflight format\n");
- return ret;
+ goto error;
}
if (!s->inflight->addr) {
ret = vhost_dev_get_inflight(s->vhost_dev, s->queue_size, s->inflight);
if (ret < 0) {
DBG("Error getting inflight\n");
- return ret;
+ goto error;
}
}
ret = vhost_dev_set_inflight(s->vhost_dev, s->inflight);
if (ret < 0) {
DBG("Error setting inflight\n");
- return ret;
+ goto error;
}
- DBG("After vhost_dev_set_inflight\n");
-
-
ret = vhost_dev_start(s->vhost_dev, vdev, true);
if (ret < 0) {
DBG("Error starting vhost\n");
- return ret;
+ goto error;
}
s->started_vu = true;
-
- DBG("vhost_virtqueue_mask\n");
/*
* guest_notifier_mask/pending not used yet, so just unmask
* everything here. virtio-pci will do the right thing by
@@ -122,8 +131,10 @@ static int vhost_user_blk_start(VirtIODevice *vdev)
vhost_virtqueue_mask(s->vhost_dev, vdev, i, false);
}
- DBG("vhost_user_blk_start return successfully: %d\n", ret);
- return ret;
+ DBG("vhost_user_blk_start returns successfully\n");
+ return;
+
+error:
}
@@ -146,7 +157,6 @@ static int vhost_user_blk_handle_config_change(struct vhost_dev *dev)
DBG("blkcfg.capacity != s->blkcfg.capacity\n");
s->blkcfg.capacity = blkcfg.capacity;
memcpy(dev->vdev->config, &s->blkcfg, sizeof(struct virtio_blk_config));
- DBG("To virtio_notify_config\n");
virtio_notify_config(dev->vdev);
}
@@ -157,166 +167,17 @@ const VhostDevConfigOps blk_ops = {
.vhost_dev_config_notifier = vhost_user_blk_handle_config_change,
};
-static uint64_t vhost_user_blk_get_features(VirtIODevice *vdev,
- uint64_t features)
-{
- VHostUserBlk *s = vdev->vhublk;
-
- DBG("vhost_user_blk_get_features()\n");
-
- /* Turn on pre-defined features */
- virtio_add_feature(&features, VIRTIO_BLK_F_SEG_MAX);
- virtio_add_feature(&features, VIRTIO_BLK_F_GEOMETRY);
- virtio_add_feature(&features, VIRTIO_BLK_F_TOPOLOGY);
- virtio_add_feature(&features, VIRTIO_BLK_F_FLUSH);
- virtio_add_feature(&features, VIRTIO_BLK_F_DISCARD);
- virtio_add_feature(&features, VIRTIO_BLK_F_WRITE_ZEROES);
- virtio_add_feature(&features, VIRTIO_BLK_F_BLK_SIZE);
- virtio_add_feature(&features, VIRTIO_BLK_F_RO);
- /*
- * TODO: Delete if not needed
- * virtio_add_feature(&features, VIRTIO_BLK_F_BLK_SIZE);
- */
-
- /*
- * The next line makes the blk read only
- *
- * virtio_add_feature(&features, VIRTIO_BLK_F_RO);
- *
- */
-
- if (s->config_wce) {
- DBG("Add config feature\n");
- virtio_add_feature(&features, VIRTIO_BLK_F_CONFIG_WCE);
- }
-
- if (s->num_queues > 1) {
- virtio_add_feature(&features, VIRTIO_BLK_F_MQ);
- }
-
- return vhost_user_get_features(&features);
-}
-
-static int vhost_user_blk_connect(VirtIODevice *vdev)
-{
- VHostUserBlk *s = vdev->vhublk;
-
- DBG("vhost_user_blk_connect(...)\n");
-
- if (s->connected) {
- DBG("s->connected\n");
- return 0;
- }
-
- s->connected = true;
- s->vhost_dev->num_queues = s->num_queues;
- s->vhost_dev->nvqs = s->num_queues;
- s->vhost_dev->vqs = s->vhost_vqs;
- s->vhost_dev->vq_index = 0;
- s->vhost_dev->backend_features = 0;
-
- DBG("s->vhost_dev->nvqs: %d\n", s->vhost_dev->nvqs);
-
- vhost_dev_set_config_notifier(s->vhost_dev, &blk_ops);
-
- vhost_dev_init(s->vhost_dev);
-
- /* Pass the new obtained features */
- global_vdev->host_features = s->vhost_dev->features;
-
- /*
- * The next line disables VIRTIO_RING_F_INDIRECT_DESC:
- * global_vdev->host_features &= ~(1ULL << VIRTIO_RING_F_INDIRECT_DESC);
- */
-
- DBG("After init global_vdev->host_features: 0x%lx\n",
- global_vdev->host_features);
-
- DBG("vhost_user_blk_connect return successfully!\n");
-
- return 0;
-}
-
/*
* These functions will be used in the future:
*
- * static void vhost_user_blk_stop(VirtIODevice *vdev)
- * {
- * DBG("Not yet implemented\n");
- * (void)vdev;
- * }
- *
* static void vhost_user_blk_disconnect(VirtIODevice *dev)
* {
* DBG("vhost_user_blk_disconnect not yet implemented\n");
* (void)dev;
* }
*
- * static void vhost_user_blk_chr_closed_bh(void *opaque)
- * {
- * DBG("vhost_user_blk_chr_closed_bh not yet implemented\n");
- * (void)opaque;
- * }
- *
- * static void vhost_user_blk_event(void *opaque)
- * {
- * DBG("vhost_user_blk_event not yet implemented");
- * (void)opaque;
- * }
- *
*/
-static int vhost_user_blk_realize_connect(VHostUserBlk *s)
-{
- int ret;
-
- DBG("vhost_user_blk_realize_connect(...)\n");
- s->connected = false;
-
- DBG("s->vdev: 0x%lx\n", (uint64_t)s->parent);
- DBG("global_vdev: 0x%lx\n", (uint64_t)global_vdev);
- ret = vhost_user_blk_connect(s->parent);
- if (ret < 0) {
- DBG("vhost_user_blk_connect failed\n");
- return ret;
- }
- DBG("s->connected: %d\n", s->connected);
-
- ret = vhost_dev_get_config(s->vhost_dev, (uint8_t *)&s->blkcfg,
- sizeof(struct virtio_blk_config));
- if (ret < 0) {
- DBG("vhost_dev_get_config failed\n");
- return ret;
- }
-
- if (global_vdev->vhublk->config_wce != s->blkcfg.wce) {
- s->blkcfg.wce = global_vdev->vhublk->config_wce;
-
- ret = vhost_dev_set_config(s->vhost_dev, (uint8_t *)&s->blkcfg.wce,
- offsetof(struct virtio_blk_config, wce),
- sizeof(s->blkcfg.wce),
- VHOST_SET_CONFIG_TYPE_MASTER);
- if (ret < 0) {
- DBG("set device config space failed\n");
- return ret;
- }
- }
-
- return 0;
-}
-
-static void vhost_user_blk_device_unrealize(VirtIODevice *vdev)
-{
- DBG("vhost_user_blk_device_unrealize not yet implemented\n");
- (void)vdev;
-}
-
-static void vhost_user_blk_reset(VirtIODevice *vdev)
-{
- DBG("vhost_user_blk_reset not yet implemented\n");
- (void)vdev;
-}
-
static void vhost_user_blk_update_config(VirtIODevice *vdev, uint8_t *config)
{
VHostUserBlk *s = vdev->vhublk;
@@ -354,39 +215,131 @@ static void vhost_user_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
s->blkcfg.wce = blkcfg->wce;
}
+static void vhost_user_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+ /*
+ * Not normally called; it's the daemon that handles the queue;
+ * however virtio's cleanup path can call this.
+ */
+ DBG("vhost_user_blk_handle_output not yet implemented\n");
+ (void)vdev;
+ (void)vq;
+}
+
+void vhost_user_blk_init(VirtIODevice *vdev);
+static void print_config_blk(uint8_t *config_data);
-static void vhost_user_blk_set_status(VirtIODevice *vdev, uint8_t status)
+void vhost_user_blk_realize(struct adapter_dev *adev)
{
- VHostUserBlk *s = vdev->vhublk;
- /* Just for testing: bool should_start = true; */
- bool should_start = virtio_device_started(vdev, status);
- int ret;
+ struct VirtIODevice *vdev = &adev->virtio_dev;
+ unsigned int queue_size = adev->device_params->queue_size;
+ unsigned int queue_num = adev->device_params->queue_num;
+ VirtIOMMIOProxy *proxy = &adev->proxy;
+ int ret, i;
- DBG("vhost_user_blk_set_status (...)\n");
+ DBG("vhost_user_blk_realize\n");
- /* TODO: Remove if not needed */
- if (!s->connected) {
- DBG("Not connected!\n");
- return;
+ /* Initialize proxy */
+ proxy->legacy = 1;
+
+ /* VIRTIO_ID_BLOCK is 2, check virtio_ids.h in linux */
+ virtio_dev_init(vdev, "virtio-blk", 2,
+ sizeof(struct virtio_blk_config));
+ vdev->user_feature_bits = user_feature_bits;
+
+ vhost_user_blk_init(vdev);
+
+ vdev->vhublk->config_wce = 1;
+
+ vdev->vhublk->vhost_dev->nvqs = queue_num;
+ vdev->vhublk->num_queues = queue_num;
+ vdev->vhublk->queue_size = queue_size;
+
+ /* NOTE: vdev->vqs == vhublk->virtqs */
+ vdev->vqs = (VirtQueue **)malloc(sizeof(VirtQueue *)
+ * vdev->vhublk->num_queues);
+ for (i = 0; i < vdev->vhublk->num_queues; i++) {
+ vdev->vqs[i] = virtio_add_queue(vdev,
+ vdev->vhublk->queue_size,
+ vhost_user_blk_handle_output);
}
- DBG("should_start == %d\n", should_start);
- if (s->vhost_dev->started == should_start) {
- DBG("s->dev->started == should_start\n");
+ vdev->vhublk->inflight = (struct vhost_inflight *)malloc(
+ sizeof(struct vhost_inflight));
+ vdev->vhublk->vhost_vqs = (struct vhost_virtqueue *)malloc(
+ sizeof(struct vhost_virtqueue) *
+ vdev->vhublk->num_queues);
+
+ vdev->vhublk->vhost_dev->num_queues = vdev->vhublk->num_queues;
+ vdev->vhublk->vhost_dev->nvqs = vdev->vhublk->num_queues;
+ vdev->vhublk->vhost_dev->vqs = vdev->vhublk->vhost_vqs;
+ vdev->vhublk->vhost_dev->vq_index = 0;
+ vdev->vhublk->vhost_dev->backend_features = 0;
+
+ vhost_dev_set_config_notifier(vdev->vhublk->vhost_dev, &blk_ops);
+
+ vhost_dev_init(vdev->vhublk->vhost_dev);
+
+ /* Pass the new obtained features */
+ vdev->host_features = vdev->vhublk->vhost_dev->features;
+
+ /*
+ * The next line disables VIRTIO_RING_F_INDIRECT_DESC:
+ * vdev->host_features &= ~(1ULL << VIRTIO_RING_F_INDIRECT_DESC);
+ */
+
+ ret = vhost_dev_get_config(vdev->vhublk->vhost_dev, (uint8_t *)&vdev->vhublk->blkcfg,
+ sizeof(struct virtio_blk_config));
+ if (ret < 0) {
+ DBG("vhost_dev_get_config failed\n");
return;
}
- if (should_start) {
- ret = vhost_user_blk_start(vdev);
+ if (vdev->vhublk->config_wce != vdev->vhublk->blkcfg.wce) {
+ vdev->vhublk->blkcfg.wce = vdev->vhublk->config_wce;
+
+ ret = vhost_dev_set_config(vdev->vhublk->vhost_dev, (uint8_t *)&vdev->vhublk->blkcfg.wce,
+ offsetof(struct virtio_blk_config, wce),
+ sizeof(vdev->vhublk->blkcfg.wce),
+ VHOST_SET_CONFIG_TYPE_MASTER);
if (ret < 0) {
- DBG("vhost_user_blk_start returned error\n");
+ DBG("set device config space failed\n");
+ return;
}
- } else {
- DBG("Call vhost_user_blk_stop (not yet in place)\n");
- /* TODO: vhost_user_blk_stop(vdev); */
}
- DBG("vhost_user_blk_set_status return successfully\n");
+ DBG("final vdev->host_features: 0x%lx\n",
+ vdev->host_features);
+
+ print_config_blk((uint8_t *)(&vdev->vhublk->blkcfg));
+}
+
+static void vhost_user_dev_class_init_extra(VirtIODevice *vdev)
+{
+ DBG("virtio_dev_class_init\n");
+
+ vdev->vdev_class->realize = vhost_user_blk_realize;
+ vdev->vdev_class->start = vhost_user_blk_start;
+ vdev->vdev_class->get_config = vhost_user_blk_update_config;
+ vdev->vdev_class->set_config = vhost_user_blk_set_config;
+ vdev->vdev_class->print_config = print_config_blk;
+}
+
+void vhost_user_blk_init(VirtIODevice *vdev)
+{
+ struct vhost_dev *vhdev = vdev->vhdev;
+ DBG("vhost_user_blk_init\n");
+
+ VHostUserBlk *vhublk = (VHostUserBlk *)malloc(sizeof(VHostUserBlk));
+ vdev->vhublk = vhublk;
+ vdev->nvqs = (int *)&vhdev->nvqs;
+ vhublk->parent = vdev;
+ vhublk->virtqs = vdev->vqs;
+ vhublk->vhost_dev = vhdev;
+
+ vhost_user_dev_class_init(vdev);
+ vhost_user_dev_class_init_extra(vdev);
+ virtio_loopback_bus_init(vdev->vbus);
}
static void print_config_blk(uint8_t *config_data)
@@ -432,104 +385,3 @@ static void print_config_blk(uint8_t *config_data)
DBG("uint8_t unused1[3]: %u\n", config_strct->unused1[1]);
DBG("uint8_t unused1[3]: %u\n", config_strct->unused1[2]);
}
-
-static void virtio_dev_class_init(VirtIODevice *vdev)
-{
- DBG("virtio_dev_class_init\n");
-
- vdev->vdev_class = (VirtioDeviceClass *)malloc(sizeof(VirtioDeviceClass));
- vdev->vdev_class->parent = vdev;
- vdev->vdev_class->realize = vhost_user_blk_realize;
- vdev->vdev_class->unrealize = vhost_user_blk_device_unrealize;
- vdev->vdev_class->get_config = vhost_user_blk_update_config;
- vdev->vdev_class->set_config = vhost_user_blk_set_config;
- vdev->vdev_class->get_features = vhost_user_blk_get_features;
- vdev->vdev_class->set_status = vhost_user_blk_set_status;
- vdev->vdev_class->reset = vhost_user_blk_reset;
- vdev->vdev_class->update_mem_table = update_mem_table;
- vdev->vdev_class->print_config = print_config_blk;
-}
-
-void vhost_user_blk_init(VirtIODevice *vdev)
-{
-
- DBG("vhost_user_blk_init\n");
-
- VHostUserBlk *vhublk = (VHostUserBlk *)malloc(sizeof(VHostUserBlk));
- vdev->vhublk = vhublk;
- vdev->nvqs = (int *)&dev->nvqs;
- vhublk->parent = vdev;
- vhublk->virtqs = vdev->vqs;
- vhublk->vhost_dev = dev;
-
- virtio_dev_class_init(vdev);
- virtio_loopback_bus_init(vdev->vbus);
-}
-
-static void vhost_user_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
-{
- /*
- * Not normally called; it's the daemon that handles the queue;
- * however virtio's cleanup path can call this.
- */
- DBG("vhost_user_blk_handle_output not yet implemented\n");
- (void)vdev;
- (void)vq;
-}
-
-void vhost_user_blk_realize(int queue_num, int queue_size)
-{
- int retries;
- int i, ret;
-
- DBG("vhost_user_blk_realize\n");
-
- /* This needs to be added */
- proxy = (VirtIOMMIOProxy *)malloc(sizeof(VirtIOMMIOProxy));
- *proxy = (VirtIOMMIOProxy) {
- .legacy = 1,
- };
-
- /* VIRTIO_ID_BLOCK is 2, check virtio_ids.h in linux */
- virtio_dev_init(global_vdev, "virtio-blk", 2,
- sizeof(struct virtio_blk_config));
-
- vhost_user_blk_init(global_vdev);
-
- global_vdev->vhublk->config_wce = 1;
-
- global_vdev->vhublk->vhost_dev->nvqs = queue_num;
- global_vdev->vhublk->num_queues = queue_num;
- global_vdev->vhublk->queue_size = queue_size;
-
- /* NOTE: global_vdev->vqs == vhublk->virtqs */
- global_vdev->vqs = (VirtQueue **)malloc(sizeof(VirtQueue *)
- * global_vdev->vhublk->num_queues);
- for (i = 0; i < global_vdev->vhublk->num_queues; i++) {
- global_vdev->vqs[i] = virtio_add_queue(global_vdev,
- global_vdev->vhublk->queue_size,
- vhost_user_blk_handle_output);
- }
-
- global_vdev->vhublk->inflight = (struct vhost_inflight *)malloc(
- sizeof(struct vhost_inflight));
- global_vdev->vhublk->vhost_vqs = (struct vhost_virtqueue *)malloc(
- sizeof(struct vhost_virtqueue) *
- global_vdev->vhublk->num_queues);
-
- retries = REALIZE_CONNECTION_RETRIES;
-
- do {
- ret = vhost_user_blk_realize_connect(global_vdev->vhublk);
- } while (ret < 0 && retries--);
-
- if (ret < 0) {
- DBG("vhost_user_blk_realize_connect: -EPROTO\n");
- }
-
- DBG("final global_vdev->host_features: 0x%lx\n",
- global_vdev->host_features);
-
- print_config_blk((uint8_t *)(&global_vdev->vhublk->blkcfg));
-}
-
diff --git a/src/devices/vhost_user_can.c b/src/devices/vhost_user_can.c
new file mode 100644
index 0000000..091637c
--- /dev/null
+++ b/src/devices/vhost_user_can.c
@@ -0,0 +1,179 @@
+/*
+ * Virtio CAN Device
+ *
+ * Based on virtio_can.h of OpenSynergy's virtio-can RFC
+ * https://github.com/OpenSynergy/qemu/tree/virtio-can-spec-rfc-v3
+ *
+ * Copyright (C) 2021-2023 OpenSynergy GmbH
+ * Copyright (c) 2023 Virtual Open Systems SAS.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/param.h>
+
+/* Project header files */
+#include "vhost_user_can.h"
+
+#ifdef DEBUG
+#define DBG(...) printf("vhost-user-can: " __VA_ARGS__)
+#else
+#define DBG(...)
+#endif /* DEBUG */
+
+/***************************** vhost-user-can ******************************/
+
+static const int user_feature_bits[] = {
+ VIRTIO_F_VERSION_1,
+ VIRTIO_RING_F_INDIRECT_DESC,
+ VIRTIO_RING_F_EVENT_IDX,
+ VIRTIO_F_RING_RESET,
+ VIRTIO_F_NOTIFY_ON_EMPTY,
+ VHOST_INVALID_FEATURE_BIT
+};
+
+static void vhost_user_can_can_handle_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+ /*
+ * Not normally called; it's the daemon that handles the queue;
+ * however virtio's cleanup path can call this.
+ */
+ DBG("vhost_user_can_can_handle_output: Not yet implemented!\n");
+ (void)vdev;
+ (void)vq;
+}
+
+static int vhost_user_can_can_config_change(struct vhost_dev *dev)
+{
+ DBG("vhost_user_can_can_config_change\n");
+
+ int ret = vhost_dev_get_config(dev, (uint8_t *)dev->vdev->config,
+ sizeof(struct virtio_can_config));
+ if (ret < 0) {
+ DBG("vhost_user_can_sound_config_change error\n");
+ return -1;
+ }
+
+ virtio_notify_config(dev->vdev);
+
+ return 0;
+}
+
+const VhostDevConfigOps can_config_ops = {
+ .vhost_dev_config_notifier = vhost_user_can_can_config_change,
+};
+
+static void vhost_user_can_init(VirtIODevice *vdev);
+
+void vhost_user_can_realize(struct adapter_dev *adev)
+{
+ VirtIODevice *vdev = &adev->virtio_dev;
+ VirtIOMMIOProxy *proxy = &adev->proxy;
+ int ret;
+
+ /* Initialize proxy */
+ proxy->legacy = 1;
+
+ /* VIRTIO_ID_CAN is 36, check virtio_ids.h in linux*/
+ virtio_dev_init(vdev, "virtio-can", 36, sizeof(struct virtio_can_config));
+ vdev->user_feature_bits = user_feature_bits;
+ vhost_user_can_init(vdev);
+
+ /* add queues */
+ vdev->vhucan->vhost_dev->nvqs = 3;
+ vdev->vhucan->num_queues = 3;
+ vdev->vhucan->queue_size = 64;
+
+ /* NOTE: vdev->vqs == vhucan->virtqs */
+ vdev->vqs = (VirtQueue **)malloc(sizeof(VirtQueue *)
+ * vdev->vhucan->num_queues);
+ vdev->vqs[0] = virtio_add_queue(vdev, 64, vhost_user_can_can_handle_output);
+ vdev->vqs[1] = virtio_add_queue(vdev, 64, vhost_user_can_can_handle_output);
+ vdev->vqs[2] = virtio_add_queue(vdev, 64, vhost_user_can_can_handle_output);
+
+ vdev->vhucan->vhost_vqs = (struct vhost_virtqueue *)malloc(
+ sizeof(struct vhost_virtqueue) *
+ vdev->vhucan->num_queues);
+
+ /* Set up vhost device */
+ vdev->vhucan->vhost_dev->num_queues = vdev->vhucan->num_queues;
+ vdev->vhucan->vhost_dev->nvqs = vdev->vhucan->num_queues;
+ vdev->vhucan->vhost_dev->vqs = vdev->vhucan->vhost_vqs;
+ vdev->vhucan->vhost_dev->vq_index = 0;
+ vdev->vhucan->vhost_dev->backend_features = 0;
+
+ vhost_dev_set_config_notifier(vdev->vhucan->vhost_dev, &can_config_ops);
+
+ /* TODO: Add error handling */
+ vhost_dev_init(vdev->vhucan->vhost_dev);
+
+ /* Pass the new obtained features */
+ vdev->host_features = vdev->vhucan->vhost_dev->features;
+
+ ret = vhost_dev_get_config(vdev->vhucan->vhost_dev,
+ (uint8_t *)vdev->config,
+ sizeof(struct virtio_can_config));
+ if (ret < 0) {
+ goto vhost_dev_init_failed;
+ }
+
+ vdev->vdev_class->print_config((uint8_t *)&vdev->config);
+
+ return;
+
+vhost_dev_init_failed:
+ DBG("vhost_dev_init_failed\n");
+ return;
+}
+
+static void print_config_can(uint8_t *config_data)
+{
+ struct virtio_can_config *config_strct =
+ (struct virtio_can_config *)config_data;
+
+ (void)config_strct;
+ DBG("print_config_can:\n");
+
+ DBG("\tuint16_t status: %u\n", config_strct->status);
+}
+
+static void vhost_user_dev_class_init_extra(VirtIODevice *vdev)
+{
+ DBG("virtio_dev_class_init\n");
+
+ vdev->vdev_class->realize = vhost_user_can_realize;
+ vdev->vdev_class->print_config = print_config_can;
+}
+
+static void vhost_user_can_init(VirtIODevice *vdev)
+{
+ DBG("vhost_user_can_init\n");
+
+ VHostUserCan *vhucan = (VHostUserCan *)malloc(sizeof(VHostUserCan));
+ vdev->vhucan = vhucan;
+ vdev->nvqs = (int *)&vdev->vhdev->nvqs;
+ vhucan->parent = vdev;
+ vhucan->virtqs = vdev->vqs;
+ vhucan->vhost_dev = vdev->vhdev;
+
+ vhost_user_dev_class_init(vdev);
+ vhost_user_dev_class_init_extra(vdev);
+ virtio_loopback_bus_init(vdev->vbus);
+}
diff --git a/src/devices/vhost_user_console.c b/src/devices/vhost_user_console.c
new file mode 100644
index 0000000..d640b22
--- /dev/null
+++ b/src/devices/vhost_user_console.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2023 Virtual Open Systems SAS.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ *
+ */
+
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/param.h>
+
+/* Project header files */
+#include "vhost_user_console.h"
+
+#ifdef DEBUG
+#define DBG(...) printf("vhost-user-console: " __VA_ARGS__)
+#else
+#define DBG(...)
+#endif /* DEBUG */
+
+static const int user_feature_bits[] = {
+ VIRTIO_F_VERSION_1,
+ VIRTIO_RING_F_INDIRECT_DESC,
+ VIRTIO_RING_F_EVENT_IDX,
+ VIRTIO_F_RING_RESET,
+ VIRTIO_F_NOTIFY_ON_EMPTY,
+ VHOST_INVALID_FEATURE_BIT,
+ VIRTIO_CONSOLE_F_SIZE,
+ VIRTIO_CONSOLE_F_MULTIPORT,
+ VIRTIO_CONSOLE_F_EMERG_WRITE
+};
+
+static void vhost_user_console_handle_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+ /*
+ * Not normally called; it's the daemon that handles the queue;
+ * however virtio's cleanup path console call this.
+ */
+ DBG("vhost_user_console_handle_output: Not yet implemented!\n");
+ (void)vdev;
+ (void)vq;
+}
+
+static int vhost_user_console_config_change(struct vhost_dev *dev)
+{
+ DBG("vhost_user_console_console_config_change\n");
+
+ int ret = vhost_dev_get_config(dev, (uint8_t *)dev->vdev->config,
+ sizeof(struct virtio_console_config));
+ if (ret < 0) {
+ DBG("vhost_user_console_sound_config_change error\n");
+ return -1;
+ }
+
+ virtio_notify_config(dev->vdev);
+
+ return 0;
+}
+
+const VhostDevConfigOps console_config_ops = {
+ .vhost_dev_config_notifier = vhost_user_console_config_change,
+};
+
+static void vhost_user_console_init(VirtIODevice *vdev);
+
+void vhost_user_console_realize(struct adapter_dev *adev)
+{
+ VirtIODevice *vdev = &adev->virtio_dev;
+ VirtIOMMIOProxy *proxy = &adev->proxy;
+ int ret;
+
+ DBG("vhost_user_console_device_realize\n");
+
+ /* Initialize proxy */
+ proxy->legacy = 1;
+
+ /* VIRTIO_ID_CONSOLE is 3, check virtio_ids.h in linux*/
+ virtio_dev_init(vdev, "virtio-console", 3, sizeof(struct virtio_console_config));
+ vdev->user_feature_bits = user_feature_bits;
+ vhost_user_console_init(vdev);
+
+ /* add queues */
+ vdev->vhuconsole->vhost_dev->nvqs = 4;
+ vdev->vhuconsole->num_queues = 4;
+ vdev->vhuconsole->queue_size = 128;
+
+ /* NOTE: vdev->vqs == vhuconsole->virtqs */
+ vdev->vqs = (VirtQueue **)malloc(sizeof(VirtQueue *)
+ * vdev->vhuconsole->num_queues);
+ vdev->vqs[0] = virtio_add_queue(vdev, 128, vhost_user_console_handle_output);
+ vdev->vqs[1] = virtio_add_queue(vdev, 128, vhost_user_console_handle_output);
+ vdev->vqs[2] = virtio_add_queue(vdev, 128, vhost_user_console_handle_output);
+ vdev->vqs[3] = virtio_add_queue(vdev, 128, vhost_user_console_handle_output);
+
+ vdev->vhuconsole->vhost_vqs = (struct vhost_virtqueue *)malloc(
+ sizeof(struct vhost_virtqueue) *
+ vdev->vhuconsole->num_queues);
+
+ /* Set up vhost device */
+ vdev->vhuconsole->vhost_dev->num_queues = vdev->vhuconsole->num_queues;
+ vdev->vhuconsole->vhost_dev->nvqs = vdev->vhuconsole->num_queues;
+ vdev->vhuconsole->vhost_dev->vqs = vdev->vhuconsole->vhost_vqs;
+ vdev->vhuconsole->vhost_dev->vq_index = 0;
+ vdev->vhuconsole->vhost_dev->backend_features = 0;
+
+ vhost_dev_set_config_notifier(vdev->vhuconsole->vhost_dev,
+ &console_config_ops);
+
+ /* TODO: Add error handling */
+ vhost_dev_init(vdev->vhuconsole->vhost_dev);
+
+ /* Pass the new obtained features */
+ vdev->host_features = vdev->vhuconsole->vhost_dev->features;
+
+ ret = vhost_dev_get_config(vdev->vhdev,
+ (uint8_t *)vdev->config,
+ sizeof(struct virtio_console_config));
+ if (ret < 0) {
+ goto vhost_dev_init_failed;
+ }
+
+ vdev->vdev_class->print_config((uint8_t *)&vdev->config);
+
+ return;
+
+vhost_dev_init_failed:
+ DBG("vhost_dev_init_failed\n");
+ return;
+}
+
+static void print_config_console(uint8_t *config_data)
+{
+ struct virtio_console_config *config_strct =
+ (struct virtio_console_config *)config_data;
+
+ (void)config_strct;
+ DBG("print_config_console:\n");
+ DBG("\tuint16_t cols: %u\n", config_strct->cols);
+ DBG("\tuint16_t rows: %u\n", config_strct->rows);
+ DBG("\tuint16_t max_nr_ports: %u\n", config_strct->max_nr_ports);
+ DBG("\tuint16_t emerg_wr: %u\n", config_strct->emerg_wr);
+}
+
+static void vhost_user_dev_class_init_extra(VirtIODevice *vdev)
+{
+ DBG("virtio_dev_class_init\n");
+
+ vdev->vdev_class->realize = vhost_user_console_realize;
+ vdev->vdev_class->print_config = print_config_console;
+}
+
+static void vhost_user_console_init(VirtIODevice *vdev)
+{
+
+ DBG("vhost_user_console_init\n");
+
+ VHostUserConsole *vhuconsole =
+ (VHostUserConsole *)malloc(sizeof(VHostUserConsole));
+ vdev->vhuconsole = vhuconsole;
+ vdev->nvqs = (int *)&vdev->vhdev->nvqs;
+ vhuconsole->parent = vdev;
+ vhuconsole->virtqs = vdev->vqs;
+ vhuconsole->vhost_dev = vdev->vhdev;
+
+ vhost_user_dev_class_init(vdev);
+ vhost_user_dev_class_init_extra(vdev);
+ virtio_loopback_bus_init(vdev->vbus);
+}
diff --git a/src/devices/vhost_user_gpio.c b/src/devices/vhost_user_gpio.c
new file mode 100644
index 0000000..0858020
--- /dev/null
+++ b/src/devices/vhost_user_gpio.c
@@ -0,0 +1,204 @@
+/*
+ * Based on vhost-user-gpio.c of QEMU project
+ *
+ * Copyright (c) 2022 Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * Copyright (c) 2023 Virtual Open Systems SAS.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/param.h>
+#include <errno.h>
+
+/* Project header files */
+#include "vhost_user_gpio.h"
+
+#ifdef DEBUG
+#define DBG(...) printf("vhost-user-gpio: " __VA_ARGS__)
+#else
+#define DBG(...)
+#endif /* DEBUG */
+
+static const int user_feature_bits[] = {
+ VIRTIO_F_VERSION_1,
+ VIRTIO_F_NOTIFY_ON_EMPTY,
+ VIRTIO_RING_F_INDIRECT_DESC,
+ VIRTIO_RING_F_EVENT_IDX,
+ VIRTIO_GPIO_F_IRQ,
+ VIRTIO_F_RING_RESET,
+ VHOST_INVALID_FEATURE_BIT
+};
+
+static int vu_gpio_config_notifier(struct vhost_dev *dev)
+{
+ DBG("vu_gpio_config_notifier\n");
+
+ /* TODO: Investigate if we need that */
+ //memcpy(dev->vdev->config, &dev->vdev->vhugpio->config, sizeof(gpio->config));
+
+ virtio_notify_config(dev->vdev);
+
+ return 0;
+}
+
+const VhostDevConfigOps gpio_ops = {
+ .vhost_dev_config_notifier = vu_gpio_config_notifier,
+};
+
+static void vu_gpio_handle_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+ /*
+ * Not normally called; it's the daemon that handles the queue;
+ * however virtio's cleanup path can call this.
+ */
+ DBG("vu_gpio_handle_output not yet implemented\n");
+ (void)vdev;
+ (void)vq;
+}
+
+static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserGPIO *gpio)
+{
+ DBG("do_vhost_user_cleanup not yet implemented\n");
+ (void)vdev;
+ (void)gpio;
+}
+
+static void print_config_gpio(uint8_t *config_data)
+{
+ struct virtio_gpio_config *config =
+ (struct virtio_gpio_config *)config_data;
+
+ (void)config;
+ DBG("ngpio: %hu\n", config->ngpio);
+ DBG("gpio_names_size: %u\n", config->gpio_names_size);
+}
+
+void vhost_user_gpio_init(VirtIODevice *vdev);
+
+void vu_gpio_device_realize(struct adapter_dev *adev)
+{
+ VirtIODevice *vdev = &adev->virtio_dev;
+ VirtIOMMIOProxy *proxy = &adev->proxy;
+ int ret;
+
+ DBG("vu_gpio_device_realize()\n");
+
+ /* Initialize proxy */
+ proxy->legacy = 1;
+
+ /* VIRTIO_ID_GPIO is 41, check virtio_ids.h in linux */
+ virtio_dev_init(vdev, "virtio-gpio", 41,
+ sizeof(struct virtio_gpio_config));
+ vdev->user_feature_bits = user_feature_bits;
+
+ vhost_user_gpio_init(vdev);
+ if (!vdev->vhugpio) {
+ DBG("vhugpio memory allocation failed\n");
+ goto out_with_error;
+ }
+
+ /* add queues */
+ vdev->vhugpio->num_queues = 2;
+ vdev->vhugpio->queue_size = 64;
+
+ vdev->vqs = (VirtQueue **)malloc(sizeof(VirtQueue *)
+ * vdev->vhugpio->num_queues);
+ vdev->vqs[0] = virtio_add_queue(vdev, 64, vu_gpio_handle_output);
+ vdev->vqs[1] = virtio_add_queue(vdev, 64, vu_gpio_handle_output);
+
+
+ vdev->vhugpio->vhost_vqs = (struct vhost_virtqueue *)
+ malloc(sizeof(struct vhost_virtqueue *));
+ if (!vdev->vhugpio->vhost_vqs) {
+ DBG("vhost_vqs memory allocation failed\n");
+ goto out_with_dev;
+ }
+
+ /* Set up vhost device */
+ vdev->vhdev->num_queues = vdev->vhugpio->num_queues;
+ vdev->vhdev->nvqs = vdev->vhugpio->num_queues;
+ vdev->vhdev->vqs = vdev->vhugpio->vhost_vqs;
+ vdev->vhdev->vq_index = 0;
+ vdev->vhdev->backend_features = 0;
+
+ vhost_dev_set_config_notifier(vdev->vhdev, &gpio_ops);
+
+ /* TODO: Add error handling */
+ vhost_dev_init(vdev->vhdev);
+
+ /* Pass the new obtained features */
+ vdev->host_features = vdev->vhdev->features;
+
+ ret = vhost_dev_get_config(vdev->vhdev, (uint8_t *)vdev->config,
+ vdev->config_len);
+ if (ret < 0) {
+ DBG("vu_gpio_realize_connect(): -EPROTO\n");
+ do_vhost_user_cleanup(vdev, vdev->vhugpio);
+ }
+
+ print_config_gpio((uint8_t *)(vdev->config));
+ DBG("(realize completed)\n");
+
+ return;
+
+ /*
+ * TODO: Fix the following considering also do_vhost_user_cleanup()
+ *
+ * out_with_cmd_vq:
+ * free(vdev->vhugpio->command_vq);
+ */
+out_with_dev:
+ free(vdev->vhugpio);
+out_with_error:
+ DBG("Realize funciton return error\n");
+ return;
+}
+
+static void vhost_user_dev_class_init_extra(VirtIODevice *vdev)
+{
+ DBG("vu_gpio_class_init()\n");
+
+ vdev->vdev_class->realize = vu_gpio_device_realize;
+}
+
+void vhost_user_gpio_init(VirtIODevice *vdev)
+{
+ DBG("vhost_user_gpio_init(...)\n");
+
+ VHostUserGPIO *vhugpio = (VHostUserGPIO *)malloc(sizeof(VHostUserGPIO));
+ if (!vhugpio) {
+ DBG("proxy memory allocation failed\n");
+ goto out;
+ }
+
+ vdev->vhugpio = vhugpio;
+ vdev->nvqs = (int *)&vdev->vhdev->nvqs;
+ vhugpio->parent = vdev;
+ vhugpio->vhost_dev = vdev->vhdev;
+
+ vhost_user_dev_class_init(vdev);
+ vhost_user_dev_class_init_extra(vdev);
+ virtio_loopback_bus_init(vdev->vbus);
+
+out:
+ return;
+}
diff --git a/src/devices/vhost_user_input.c b/src/devices/vhost_user_input.c
new file mode 100644
index 0000000..1ea18a9
--- /dev/null
+++ b/src/devices/vhost_user_input.c
@@ -0,0 +1,154 @@
+/*
+ * Based on vhost-user-input.c of QEMU project
+ *
+ * Copyright (c) 2022-2024 Virtual Open Systems SAS.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/param.h>
+
+/* Project header files */
+#include "vhost_user_input.h"
+
+#ifdef DEBUG
+#define DBG(...) printf("vhost-user-input: " __VA_ARGS__)
+#else
+#define DBG(...)
+#endif /* DEBUG */
+
+static int vhost_input_config_change(struct vhost_dev *dev)
+{
+ DBG("vhost-user-input: unhandled backend config change\n");
+ (void)dev;
+
+ return -1;
+}
+
+const VhostDevConfigOps config_ops = {
+ .vhost_dev_config_notifier = vhost_input_config_change,
+};
+
+static void vhost_input_set_config(VirtIODevice *vdev, const uint8_t *config_data)
+{
+ int ret;
+
+ DBG("vhost_input_set_config(...)\n");
+
+ ret = vhost_dev_set_config(vdev->vhdev, config_data,
+ 0, sizeof(struct virtio_input_config),
+ VHOST_SET_CONFIG_TYPE_MASTER);
+ if (ret < 0) {
+ DBG("vhost_input_set_config failed\n");
+ return;
+ }
+
+ virtio_notify_config(vdev);
+}
+
+static void print_config_input(uint8_t *config_data)
+{
+ struct virtio_input_config *config_strct =
+ (struct virtio_input_config *)config_data;
+
+ DBG("print_config_input: Not yet implemented\n");
+ (void)config_strct;
+}
+
+static void virtio_input_handle(VirtIODevice *vdev, VirtQueue *vq)
+{
+ DBG("virtio_input_handle_evt(...) not yet implemeted\n");
+ (void)vdev;
+ (void)vq;
+}
+
+static const int user_feature_bits[] = {
+ VIRTIO_F_VERSION_1,
+ VIRTIO_RING_F_INDIRECT_DESC,
+ VIRTIO_RING_F_EVENT_IDX,
+ VIRTIO_F_RING_RESET,
+ VIRTIO_F_NOTIFY_ON_EMPTY,
+ VHOST_INVALID_FEATURE_BIT
+};
+
+static void vhost_user_input_init(VirtIODevice *vdev);
+
+void virtio_input_device_realize(struct adapter_dev *adev)
+{
+ VirtIODevice *vdev = &adev->virtio_dev;
+ VirtIOMMIOProxy *proxy = &adev->proxy;
+
+ int nvqs = 2; /* qemu choice: 2 */
+
+ DBG("virtio_input_device_realize(...)\n");
+
+ /* Initialize proxy */
+ proxy->legacy = 1;
+
+ virtio_dev_init(vdev, "virtio-input", 18, sizeof(struct virtio_input_config));
+ vdev->user_feature_bits = user_feature_bits;
+ vhost_user_input_init(vdev);
+
+ vdev->vqs = (struct VirtQueue **)malloc(
+ sizeof(struct VirtQueue *) * nvqs);
+
+ vdev->vqs[0] = virtio_add_queue(vdev, 64, virtio_input_handle);
+ vdev->vqs[1] = virtio_add_queue(vdev, 64, virtio_input_handle);
+
+ vhost_dev_set_config_notifier(vdev->vhdev,
+ &config_ops);
+
+ vdev->vhdev->nvqs = nvqs;
+ vdev->vhdev->num_queues = nvqs;
+ vdev->vhdev->vq_index = 0;
+ vdev->vhdev->backend_features = 0;
+ vdev->vhdev->vqs = (struct vhost_virtqueue *)malloc(
+ sizeof(struct vhost_virtqueue) * nvqs);
+
+ vhost_dev_init(vdev->vhdev);
+
+ /* Pass the new obtained features */
+ vdev->host_features = vdev->vhuinput->vhost_dev->features;
+
+ DBG("final features: 0x%lx\n", vdev->host_features);
+}
+
+static void vhost_user_dev_class_init_extra(VirtIODevice *vdev)
+{
+
+ DBG("vhost_user_dev_class_init_extra(...)\n");
+
+ vdev->vdev_class->realize = virtio_input_device_realize;
+ vdev->vdev_class->set_config = vhost_input_set_config;
+ vdev->vdev_class->print_config = print_config_input;
+}
+
+static void vhost_user_input_init(VirtIODevice *vdev)
+{
+ DBG("vhost_user_input_init(...)\n");
+
+ VhostUserInput *vhuinput = (VhostUserInput *)malloc(sizeof(VhostUserInput));
+ vdev->vhuinput = vhuinput;
+ vdev->nvqs = (int*)&vdev->vhdev->nvqs;
+ vhuinput->parent = vdev;
+ vhuinput->vhost_dev = vdev->vhdev;
+
+ /*
+ * Call first the virtio_input class init to set up
+ * the basic functionality.
+ */
+ vhost_user_dev_class_init(vdev);
+ vhost_user_dev_class_init_extra(vdev);
+
+ /* finally initialize the bus */
+ virtio_loopback_bus_init(vdev->vbus);
+}
+
diff --git a/src/devices/vhost_user_rng.c b/src/devices/vhost_user_rng.c
new file mode 100644
index 0000000..b58fa59
--- /dev/null
+++ b/src/devices/vhost_user_rng.c
@@ -0,0 +1,112 @@
+/*
+ * Based on vhost-user-rng of QEMU project
+ *
+ * Copyright (c) 2021 Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * Copyright (c) 2022-2023 Virtual Open Systems SAS.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/param.h>
+
+/* Project header files */
+#include "vhost_loopback.h"
+#include "vhost_user_rng.h"
+
+#ifdef DEBUG
+#define DBG(...) printf("vhost-user-rng: " __VA_ARGS__)
+#else
+#define DBG(...)
+#endif /* DEBUG */
+
+static const int user_feature_bits[] = {
+ VIRTIO_F_VERSION_1,
+ VIRTIO_F_NOTIFY_ON_EMPTY,
+ VIRTIO_RING_F_INDIRECT_DESC,
+ VIRTIO_RING_F_EVENT_IDX,
+ VIRTIO_F_RING_RESET,
+ VHOST_INVALID_FEATURE_BIT
+};
+
+static void vu_rng_handle_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+ (void)vdev;
+ (void)vq;
+ /*
+ * Not normally called; it's the daemon that handles the queue;
+ * however virtio's cleanup path can call this.
+ */
+ DBG("vu_rng_handle_output\n");
+}
+
+void vhost_user_rng_init(VirtIODevice *vdev);
+
+void vhost_user_rng_realize(struct adapter_dev *adev)
+{
+ VirtIODevice *vdev = &adev->virtio_dev;
+ struct vhost_dev *vhdev = &adev->vdev;
+ VirtIOMMIOProxy *proxy = &adev->proxy;
+
+ /* Initialize proxy */
+ proxy->legacy = 1;
+
+ /* Initiliaze virtio_dev data structures */
+ virtio_dev_init(vdev, "virtio-rng", 4, 0);
+ vdev->user_feature_bits = user_feature_bits;
+
+ /* This needs to be change to vhost-user-rng init */
+ vhost_user_rng_init(vdev);
+
+ vdev->vq = virtio_add_queue(vdev, 4, vu_rng_handle_output);
+ vdev->host_features = 0x39000000;
+
+ /* Virtqueues conf */
+ vhdev->nvqs = 1;
+ vhdev->vqs = (struct vhost_virtqueue *)malloc(vhdev->nvqs *
+ sizeof(struct vhost_virtqueue));
+
+ /* Initiale vhost-user communication */
+ vhost_dev_init(vhdev);
+
+ /* Write the final features */
+ vdev->host_features = vhdev->features;
+ DBG("final features: 0x%lx\n", vhdev->features);
+}
+
+static void vhost_user_dev_class_init_extra(VirtIODevice *vdev)
+{
+ vdev->vdev_class->realize = vhost_user_rng_realize;
+}
+
+void vhost_user_rng_init(VirtIODevice *vdev)
+{
+ VHostUserRNG *vhrng = (VHostUserRNG *)malloc(sizeof(VHostUserRNG));
+ vdev->vhrng = vhrng;
+ vdev->nvqs = (int *)&vdev->vhdev->nvqs;
+ vhrng->parent = vdev;
+ vhrng->req_vq = vdev->vq;
+ vhrng->vhost_dev = vdev->vhdev;
+
+ vhost_user_dev_class_init(vdev);
+ vhost_user_dev_class_init_extra(vdev);
+ virtio_loopback_bus_init(vdev->vbus);
+}
diff --git a/src/devices/vhost_user_sound.c b/src/devices/vhost_user_sound.c
new file mode 100644
index 0000000..cd3881f
--- /dev/null
+++ b/src/devices/vhost_user_sound.c
@@ -0,0 +1,178 @@
+/*
+ * Based on vhost-user-sound.c of QEMU project
+ *
+ * Copyright 2020 Red Hat, Inc.
+ *
+ * Copyright (c) 2023 Virtual Open Systems SAS.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ *
+ */
+
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/param.h>
+
+/* Project header files */
+#include "vhost_user_sound.h"
+
+#ifdef DEBUG
+#define DBG(...) printf("vhost-user-sound: " __VA_ARGS__)
+#else
+#define DBG(...)
+#endif /* DEBUG */
+
+/***************************** vhost-user-sound ******************************/
+
+static const int user_feature_bits[] = {
+ VIRTIO_F_VERSION_1,
+ VIRTIO_RING_F_INDIRECT_DESC,
+ VIRTIO_RING_F_EVENT_IDX,
+ VIRTIO_F_RING_RESET,
+ VIRTIO_F_NOTIFY_ON_EMPTY,
+ VHOST_INVALID_FEATURE_BIT
+};
+
+static void vus_snd_handle_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+ /*
+ * Not normally called; it's the daemon that handles the queue;
+ * however virtio's cleanup path can call this.
+ */
+ (void)vdev;
+ (void)vq;
+}
+
+static int vus_sound_config_change(struct vhost_dev *dev)
+{
+ DBG("vus_sound_config_change\n");
+
+ int ret = vhost_dev_get_config(dev, (uint8_t *)dev->vdev->config,
+ sizeof(struct virtio_snd_config));
+ if (ret < 0) {
+ DBG("vus_sound_config_change error\n");
+ return -1;
+ }
+
+ virtio_notify_config(dev->vdev);
+
+ return 0;
+}
+
+const VhostDevConfigOps snd_config_ops = {
+ .vhost_dev_config_notifier = vus_sound_config_change,
+};
+
+static void vhost_user_snd_init(VirtIODevice *vdev);
+
+void vus_device_realize(struct adapter_dev *adev)
+{
+ VirtIODevice *vdev = &adev->virtio_dev;
+ VirtIOMMIOProxy *proxy = &adev->proxy;
+ int ret;
+
+ DBG("vus_device_realize\n");
+
+ /* Initialize proxy */
+ proxy->legacy = 1;
+
+ /* VIRTIO_ID_SOUND is 25, check virtio_ids.h in linux*/
+ virtio_dev_init(vdev, "virtio-sound", 25, sizeof(struct virtio_snd_config));
+ vdev->user_feature_bits = user_feature_bits;
+ vhost_user_snd_init(vdev);
+
+ /* add queues */
+ vdev->vhusnd->vhost_dev->nvqs = 4;
+ vdev->vhusnd->num_queues = 4;
+ vdev->vhusnd->queue_size = 64;
+
+ /* NOTE: vdev->vqs == vhublk->virtqs */
+ vdev->vqs = (VirtQueue **)malloc(sizeof(VirtQueue *)
+ * vdev->vhusnd->num_queues);
+ vdev->vqs[0] = virtio_add_queue(vdev, 64, vus_snd_handle_output);
+ vdev->vqs[1] = virtio_add_queue(vdev, 64, vus_snd_handle_output);
+ vdev->vqs[2] = virtio_add_queue(vdev, 64, vus_snd_handle_output);
+ vdev->vqs[3] = virtio_add_queue(vdev, 64, vus_snd_handle_output);
+
+ vdev->vhusnd->vhost_vqs = (struct vhost_virtqueue *)malloc(
+ sizeof(struct vhost_virtqueue) *
+ vdev->vhusnd->num_queues);
+
+ /* Set up vhost device */
+ vdev->vhusnd->vhost_dev->num_queues = vdev->vhusnd->num_queues;
+ vdev->vhusnd->vhost_dev->nvqs = vdev->vhusnd->num_queues;
+ vdev->vhusnd->vhost_dev->vqs = vdev->vhusnd->vhost_vqs;
+ vdev->vhusnd->vhost_dev->vq_index = 0;
+ vdev->vhusnd->vhost_dev->backend_features = 0;
+
+ vhost_dev_set_config_notifier(vdev->vhusnd->vhost_dev, &snd_config_ops);
+
+ /* TODO: Add error handling */
+ vhost_dev_init(vdev->vhusnd->vhost_dev);
+
+ /* Pass the new obtained features */
+ vdev->host_features = vdev->vhusnd->vhost_dev->features;
+
+ ret = vhost_dev_get_config(vdev->vhusnd->vhost_dev,
+ (uint8_t *)vdev->config,
+ sizeof(struct virtio_snd_config));
+ if (ret < 0) {
+ goto vhost_dev_init_failed;
+ }
+
+ vdev->vdev_class->print_config((uint8_t *)&vdev->config);
+
+ return;
+
+vhost_dev_init_failed:
+ DBG("vhost_dev_init_failed\n");
+ return;
+}
+
+static void print_config_snd(uint8_t *config_data)
+{
+ struct virtio_snd_config *config_strct =
+ (struct virtio_snd_config *)config_data;
+
+ (void)config_strct;
+
+ DBG("print_config_snd:\n");
+ /* # of available physical jacks */
+ DBG("\tuint32_t jacks: %u\n", config_strct->jacks);
+ /* # of available PCM streams */
+ DBG("\tuint32_t streams: %u\n", config_strct->streams);
+ /* # of available channel maps */
+ DBG("\tuint32_t chmaps: %u\n", config_strct->chmaps);
+}
+
+static void vhost_user_dev_class_init_extra(VirtIODevice *vdev)
+{
+ DBG("vhost_user_dev_class_init_extra\n");
+
+ vdev->vdev_class->realize = vus_device_realize;
+ vdev->vdev_class->print_config = print_config_snd;
+}
+
+static void vhost_user_snd_init(VirtIODevice *vdev)
+{
+
+ DBG("vhost_user_blk_init\n");
+
+ VHostUserSound *vhusnd = (VHostUserSound *)malloc(sizeof(VHostUserSound));
+ vdev->vhusnd = vhusnd;
+ vdev->nvqs = (int *)&vdev->vhdev->nvqs;
+ vhusnd->parent = vdev;
+ vhusnd->virtqs = vdev->vqs;
+ vhusnd->vhost_dev = vdev->vhdev;
+
+ vhost_user_dev_class_init(vdev);
+ vhost_user_dev_class_init_extra(vdev);
+ virtio_loopback_bus_init(vdev->vbus);
+}
diff --git a/virtio_rng.c b/src/devices/virtio_rng.c
index f230b23..cfb95d2 100644
--- a/virtio_rng.c
+++ b/src/devices/virtio_rng.c
@@ -60,7 +60,7 @@ void virtio_rng_set_status(VirtIODevice *vdev, uint8_t status)
}
/* Send data from a char device over to the guest */
-void chr_read(VirtIORNG *vrng, const void *buf, size_t size)
+void chr_read(VirtIORNG *vrng, const char *buf, size_t size)
{
VirtIODevice *vdev = vrng->parent_obj;
VirtQueueElement *elem;
@@ -129,7 +129,7 @@ void virtio_rng_process(VirtIORNG *vrng)
size = MIN(vrng->quota_remaining, size);
if (size) {
- chr_read(vrng, &test_str, size);
+ chr_read(vrng, (const char *)&test_str, size);
}
}
@@ -158,25 +158,22 @@ void virtio_rng_init(VirtIODevice *vdev)
virtio_dev_class_init(vdev);
}
-
-void virtio_rng_realize(int queue_num, int queue_size)
+void virtio_rng_realize(struct adapter_dev *adev)
{
- (void)queue_num;
- (void)queue_size;
+ VirtIODevice *vdev = &adev->virtio_dev;
+ VirtIOMMIOProxy *proxy = &adev->proxy;
- /* prepare procy and virtio dev*/
- proxy = (VirtIOMMIOProxy *)malloc(sizeof(VirtIOMMIOProxy));
+ DBG("virtio_rng_realize(...)\n");
- virtio_dev_init(global_vdev, "virtio-rng", 4, 0);
+ /* Initialize proxy */
+ proxy->legacy = 1;
- virtio_rng_init(global_vdev);
+ virtio_dev_init(vdev, "virtio-rng", 4, 0);
- global_vdev->vq = virtio_add_queue(global_vdev, 8, handle_input);
+ virtio_rng_init(vdev);
- global_vdev->host_features = 0x39000000;
+ vdev->vq = virtio_add_queue(vdev, 8, handle_input);
- *proxy = (VirtIOMMIOProxy) {
- .legacy = 1,
- };
+ vdev->host_features = 0x39000000;
}
diff --git a/vhost_loopback.c b/src/lib/vhost_loopback.c
index 5fd3b05..3ea18b7 100644
--- a/vhost_loopback.c
+++ b/src/lib/vhost_loopback.c
@@ -196,8 +196,6 @@ void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits,
}
}
-
-
/* Mask/unmask events from this vq. */
void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
bool mask)
@@ -214,7 +212,7 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
file.index = vhost_user_get_vq_index(hdev, n);
- r = vhost_user_set_vring_call(&file);
+ r = vhost_user_set_vring_call(hdev, &file);
if (r < 0) {
DBG("vhost_set_vring_call failed\n");
}
@@ -260,10 +258,10 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
}
vq->desc_size = s = l = virtio_queue_get_desc_size(vdev, idx);
- vq->desc_phys = vring_phys_addrs[idx] << 12;
+ vq->desc_phys = vdev->vring_phys_addrs[idx] << 12;
vq->desc = (void *)virtio_queue_get_desc_addr(vdev, idx);
if (!vq->desc || l != s) {
- DBG("Error : vq->desc = a\n");
+ DBG("Error : vq->desc\n");
r = -ENOMEM;
return r;
}
@@ -273,7 +271,7 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
- virtio_queue_get_desc_addr(vdev, idx);
vq->avail = (void *)virtio_queue_get_avail_addr(vdev, idx);
if (!vq->avail || l != s) {
- DBG("Error : vq->avail = a\n");
+ DBG("Error : vq->avail\n");
r = -ENOMEM;
return r;
}
@@ -283,14 +281,14 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
- virtio_queue_get_avail_addr(vdev, idx);
vq->used = (void *)virtio_queue_get_used_addr(vdev, idx);
if (!vq->used || l != s) {
- DBG("Error : vq->used = a\n");
+ DBG("Error : vq->used\n");
r = -ENOMEM;
return r;
}
r = vhost_virtqueue_set_addr(dev, vq, vhost_vq_index, dev->log_enabled);
if (r < 0) {
- DBG("Fail vhost_virtqueue_set_addr\n");
+ DBG("vhost_virtqueue_set_addr failed\n");
return r;
}
@@ -299,7 +297,7 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
event_notifier_test_and_clear(virtio_queue_get_host_notifier(vvq));
file.fd = event_notifier_get_fd(virtio_queue_get_host_notifier(vvq));
- r = vhost_user_set_vring_kick(&file);
+ r = vhost_user_set_vring_kick(dev, &file);
if (r < 0) {
DBG("vhost_set_vring_kick failed\n");
return r;
@@ -396,7 +394,6 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings)
return 0;
}
-
int vhost_dev_get_config(struct vhost_dev *hdev, uint8_t *config,
uint32_t config_len)
{
@@ -467,4 +464,3 @@ int vhost_dev_get_inflight(struct vhost_dev *dev, uint16_t queue_size,
return 0;
}
-
diff --git a/vhost_user_loopback.c b/src/lib/vhost_user_loopback.c
index 1d52f05..3181cb9 100644
--- a/vhost_user_loopback.c
+++ b/src/lib/vhost_user_loopback.c
@@ -9,7 +9,7 @@
* Marc-André Lureau <mlureau@redhat.com>
* Victor Kaplansky <victork@redhat.com>
*
- * Copyright 2022-2023 Virtual Open Systems SAS.
+ * Copyright 2022-2024 Virtual Open Systems SAS.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -58,7 +58,6 @@
#define DBG(...)
#endif /* DEBUG */
-
bool vhost_user_one_time_request(VhostUserRequest request)
{
switch (request) {
@@ -73,7 +72,6 @@ bool vhost_user_one_time_request(VhostUserRequest request)
}
}
-
void vmsg_close_fds(VhostUserMsg *vmsg)
{
int i;
@@ -83,8 +81,7 @@ void vmsg_close_fds(VhostUserMsg *vmsg)
}
}
-
-static int vu_message_write(int conn_fd, VhostUserMsg *vmsg)
+static int vu_message_write(struct vhost_dev *dev, VhostUserMsg *vmsg)
{
int rc;
uint8_t *p = (uint8_t *)vmsg;
@@ -94,6 +91,11 @@ static int vu_message_write(int conn_fd, VhostUserMsg *vmsg)
.iov_base = (char *)vmsg,
.iov_len = VHOST_USER_HDR_SIZE,
};
+ struct adapter_dev *adev = to_adapter_device(dev, vdev);
+ Device *dev_par = adev->device_params;
+ int conn_fd = adev->device_params->client_socket;
+
+ (void)dev_par;
struct msghdr msg = {
.msg_iov = &iov,
@@ -137,7 +139,7 @@ static int vu_message_write(int conn_fd, VhostUserMsg *vmsg)
return rc;
}
-static int vu_message_read(int conn_fd, VhostUserMsg *vmsg)
+static int vu_message_read(struct vhost_dev *dev, VhostUserMsg *vmsg)
{
char control[CMSG_SPACE(VHOST_MEMORY_BASELINE_NREGIONS * sizeof(int))] = {};
struct iovec iov = {
@@ -153,6 +155,8 @@ static int vu_message_read(int conn_fd, VhostUserMsg *vmsg)
size_t fd_size;
struct cmsghdr *cmsg;
int rc;
+ struct adapter_dev *adev = to_adapter_device(dev, vdev);
+ int conn_fd = adev->device_params->client_socket;
do {
rc = recvmsg(conn_fd, &msg, 0);
@@ -200,17 +204,17 @@ fail:
return rc;
}
-int vhost_user_set_owner(void)
+int vhost_user_set_owner(struct vhost_dev *dev)
{
VhostUserMsg msg = {
.request = VHOST_USER_SET_OWNER,
.flags = VHOST_USER_VERSION,
};
- return vu_message_write(client_sock, &msg);
+ return vu_message_write(dev, &msg);
}
-int process_message_reply(const VhostUserMsg *msg)
+int process_message_reply(struct vhost_dev *dev, const VhostUserMsg *msg)
{
int ret;
VhostUserMsg msg_reply;
@@ -220,7 +224,7 @@ int process_message_reply(const VhostUserMsg *msg)
return 0;
}
- ret = vu_message_read(client_sock, &msg_reply);
+ ret = vu_message_read(dev, &msg_reply);
if (ret < 0) {
return ret;
}
@@ -235,7 +239,7 @@ int process_message_reply(const VhostUserMsg *msg)
return msg_reply.payload.u64 ? -EIO : 0;
}
-int vhost_user_get_u64(int request, uint64_t *u64)
+int vhost_user_get_u64(struct vhost_dev *dev, int request, uint64_t *u64)
{
int ret;
VhostUserMsg msg = {
@@ -249,12 +253,12 @@ int vhost_user_get_u64(int request, uint64_t *u64)
return 0;
}
- ret = vu_message_write(client_sock, &msg);
+ ret = vu_message_write(dev, &msg);
if (ret < 0) {
return ret;
}
- ret = vu_message_read(client_sock, &msg);
+ ret = vu_message_read(dev, &msg);
if (ret < 0) {
return ret;
}
@@ -271,27 +275,25 @@ int vhost_user_get_u64(int request, uint64_t *u64)
}
*u64 = msg.payload.u64;
- DBG("\tGet value: 0x%lx\n", msg.payload.u64);
return 0;
}
-
-int vhost_user_get_features(uint64_t *features)
+int vhost_user_get_features(struct vhost_dev *dev, uint64_t *features)
{
- if (vhost_user_get_u64(VHOST_USER_GET_FEATURES, features) < 0) {
+ if (vhost_user_get_u64(dev, VHOST_USER_GET_FEATURES, features) < 0) {
return -EPROTO;
}
return 0;
}
-int enforce_reply(const VhostUserMsg *msg)
+int enforce_reply(struct vhost_dev *dev, const VhostUserMsg *msg)
{
uint64_t dummy;
if (msg->flags & VHOST_USER_NEED_REPLY_MASK) {
- return process_message_reply(msg);
+ return process_message_reply(dev, msg);
}
/*
@@ -300,10 +302,10 @@ int enforce_reply(const VhostUserMsg *msg)
* Send VHOST_USER_GET_FEATURES which makes all backends
* send a reply.
*/
- return vhost_user_get_features(&dummy);
+ return vhost_user_get_features(dev, &dummy);
}
-int vhost_user_set_u64(int request, uint64_t u64, bool wait_for_reply)
+int vhost_user_set_u64(struct vhost_dev *dev, int request, uint64_t u64, bool wait_for_reply)
{
int ret = 0;
@@ -315,7 +317,6 @@ int vhost_user_set_u64(int request, uint64_t u64, bool wait_for_reply)
};
print_vhost_user_messages(request);
- DBG("\tSet value: 0x%lx\n", u64);
if (wait_for_reply) {
bool reply_supported = virtio_has_feature(dev->protocol_features,
@@ -326,13 +327,13 @@ int vhost_user_set_u64(int request, uint64_t u64, bool wait_for_reply)
}
}
- ret = vu_message_write(client_sock, &msg);
+ ret = vu_message_write(dev, &msg);
if (ret < 0) {
return ret;
}
if (wait_for_reply) {
- return enforce_reply(&msg);
+ return enforce_reply(dev, &msg);
}
return ret;
@@ -351,22 +352,23 @@ int vhost_user_set_features(struct vhost_dev *dev,
/* Pass hdev as parameter! */
DBG("vhost_user_set_features: 0x%lx\n", features | dev->backend_features);
- return vhost_user_set_u64(VHOST_USER_SET_FEATURES,
+ return vhost_user_set_u64(dev, VHOST_USER_SET_FEATURES,
features | dev->backend_features, log_enabled);
}
-int vhost_user_set_protocol_features(uint64_t features)
+int vhost_user_set_protocol_features(struct vhost_dev *dev, uint64_t features)
{
- return vhost_user_set_u64(VHOST_USER_SET_PROTOCOL_FEATURES, features,
+ return vhost_user_set_u64(dev, VHOST_USER_SET_PROTOCOL_FEATURES, features,
false);
}
-int vhost_user_get_max_memslots(uint64_t *max_memslots)
+int vhost_user_get_max_memslots(struct vhost_dev *dev, uint64_t *max_memslots)
{
uint64_t backend_max_memslots;
int err;
- err = vhost_user_get_u64(VHOST_USER_GET_MAX_MEM_SLOTS,
+ err = vhost_user_get_u64(dev,
+ VHOST_USER_GET_MAX_MEM_SLOTS,
&backend_max_memslots);
if (err < 0) {
return err;
@@ -377,8 +379,6 @@ int vhost_user_get_max_memslots(uint64_t *max_memslots)
return 0;
}
-
-
int vhost_setup_slave_channel(struct vhost_dev *dev)
{
VhostUserMsg msg = {
@@ -406,18 +406,17 @@ int vhost_setup_slave_channel(struct vhost_dev *dev)
/* FIXME: something missing here */
-
if (reply_supported) {
msg.flags |= VHOST_USER_NEED_REPLY_MASK;
}
- ret = vu_message_write(client_sock, &msg);
+ ret = vu_message_write(dev, &msg);
if (ret < 0) {
goto out;
}
if (reply_supported) {
- ret = process_message_reply(&msg);
+ ret = process_message_reply(dev, &msg);
DBG("Reply is done!\n");
}
@@ -445,7 +444,8 @@ int vhost_user_get_vq_index(struct vhost_dev *dev, int idx)
return idx;
}
-static int vhost_user_write_sync(VhostUserMsg *msg,
+static int vhost_user_write_sync(struct vhost_dev *dev,
+ VhostUserMsg *msg,
bool wait_for_reply)
{
int ret;
@@ -458,7 +458,7 @@ static int vhost_user_write_sync(VhostUserMsg *msg,
}
}
- ret = vu_message_write(client_sock, msg);
+ ret = vu_message_write(dev, msg);
if (ret < 0) {
return ret;
}
@@ -468,7 +468,7 @@ static int vhost_user_write_sync(VhostUserMsg *msg,
DBG("Wait for reply\n");
if (msg->flags & VHOST_USER_NEED_REPLY_MASK) {
- return process_message_reply(msg);
+ return process_message_reply(dev, msg);
}
/*
@@ -477,14 +477,15 @@ static int vhost_user_write_sync(VhostUserMsg *msg,
* Send VHOST_USER_GET_FEATURES which makes all backends
* send a reply.
*/
- return vhost_user_get_features(&dummy);
+ return vhost_user_get_features(dev, &dummy);
}
return 0;
}
-int vhost_set_vring_file(VhostUserRequest request,
- struct vhost_vring_file *file)
+int vhost_set_vring_file(struct vhost_dev *dev,
+ VhostUserRequest request,
+ struct vhost_vring_file *file)
{
int fds[VHOST_USER_MAX_RAM_SLOTS];
size_t fd_num = 0;
@@ -514,19 +515,17 @@ int vhost_set_vring_file(VhostUserRequest request,
msg.fd_num = fd_num;
memcpy(msg.fds, &fds, fd_num * sizeof(int));
- return vu_message_write(client_sock, &msg);
+ return vu_message_write(dev, &msg);
}
-int vhost_user_set_vring_kick(struct vhost_vring_file *file)
+int vhost_user_set_vring_kick(struct vhost_dev *dev, struct vhost_vring_file *file)
{
- DBG("Call vhost_user_set_vring_kick()\n");
- return vhost_set_vring_file(VHOST_USER_SET_VRING_KICK, file);
+ return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_KICK, file);
}
-int vhost_user_set_vring_call(struct vhost_vring_file *file)
+int vhost_user_set_vring_call(struct vhost_dev *dev, struct vhost_vring_file *file)
{
- DBG("Call vhost_user_set_vring_call()\n");
- return vhost_set_vring_file(VHOST_USER_SET_VRING_CALL, file);
+ return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_CALL, file);
}
static int vhost_set_vring(struct vhost_dev *dev,
@@ -542,7 +541,7 @@ static int vhost_set_vring(struct vhost_dev *dev,
};
(void)dev;
- return vhost_user_write_sync(&msg, wait_for_reply);
+ return vhost_user_write_sync(dev, &msg, wait_for_reply);
}
int vhost_user_set_vring_num(struct vhost_dev *dev,
@@ -557,7 +556,6 @@ int vhost_user_set_vring_base(struct vhost_dev *dev,
return vhost_set_vring(dev, VHOST_USER_SET_VRING_BASE, ring, false);
}
-
int vhost_user_set_vring_addr(struct vhost_dev *dev,
struct vhost_vring_addr *addr)
{
@@ -569,10 +567,9 @@ int vhost_user_set_vring_addr(struct vhost_dev *dev,
};
(void)dev;
- return vhost_user_write_sync(&msg, true);
+ return vhost_user_write_sync(dev, &msg, true);
}
-
int vhost_virtqueue_init(struct vhost_dev *dev,
struct vhost_virtqueue *vq, int n)
{
@@ -589,7 +586,7 @@ int vhost_virtqueue_init(struct vhost_dev *dev,
file.fd = event_notifier_get_wfd(&vq->masked_notifier);
- r = vhost_user_set_vring_call(&file);
+ r = vhost_user_set_vring_call(dev, &file);
if (r < 0) {
DBG("vhost_set_vring_call failed\n");
return r;
@@ -621,14 +618,14 @@ int vhost_user_get_config(struct vhost_dev *dev, uint8_t *config,
msg.payload.config.offset = 0;
msg.payload.config.size = config_len;
- ret = vu_message_write(client_sock, &msg);
+ ret = vu_message_write(dev, &msg);
DBG("vu_message_write return: %d\n", ret);
if (ret < 0) {
DBG("vhost_get_config failed\n");
return ret;
}
- ret = vu_message_read(client_sock, &msg);
+ ret = vu_message_read(dev, &msg);
if (ret < 0) {
DBG("vhost_get_config failed\n");
return ret;
@@ -649,8 +646,6 @@ int vhost_user_get_config(struct vhost_dev *dev, uint8_t *config,
DBG("Received config: %u, config_len: %u\n", *config, config_len);
- DBG("vhost_user_get_config return successfully\n");
-
return 0;
}
@@ -662,6 +657,8 @@ int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data,
bool reply_supported = virtio_has_feature(dev->protocol_features,
VHOST_USER_PROTOCOL_F_REPLY_ACK);
+ DBG("vhost_user_set_config(...)\n");
+
VhostUserMsg msg = {
.request = VHOST_USER_SET_CONFIG,
.flags = VHOST_USER_VERSION,
@@ -688,14 +685,13 @@ int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data,
p = msg.payload.config.region;
memcpy(p, data, size);
- ret = vu_message_write(client_sock, &msg);
- DBG("vu_message_write return: %d\n", ret);
+ ret = vu_message_write(dev, &msg);
if (ret < 0) {
return ret;
}
if (reply_supported) {
- return process_message_reply(&msg);
+ return process_message_reply(dev, &msg);
DBG("Reply is done!\n");
}
@@ -718,7 +714,7 @@ int vhost_user_get_inflight_fd(struct vhost_dev *dev,
.size = sizeof(msg.payload.inflight),
};
- DBG("vhost_user_get_inflight_fd\n");
+ DBG("vhost_user_get_inflight_fd()\n");
if (!virtio_has_feature(dev->protocol_features,
VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) {
@@ -726,14 +722,14 @@ int vhost_user_get_inflight_fd(struct vhost_dev *dev,
}
/* NOTE: This stays here as a reference */
- ret = vu_message_write(client_sock, &msg);
+ ret = vu_message_write(dev, &msg);
if (ret < 0) {
DBG("vhost_user_get_inflight_fd\n\t->write error\n");
return ret;
}
/* NOTE: This stays here as a reference */
- ret = vu_message_read(client_sock, &msg);
+ ret = vu_message_read(dev, &msg);
if (ret < 0) {
DBG("vhost_user_get_inflight_fd\n\t->read error\n");
return ret;
@@ -781,7 +777,6 @@ int vhost_user_get_inflight_fd(struct vhost_dev *dev,
return 0;
}
-
int vhost_user_set_inflight_fd(struct vhost_dev *dev,
struct vhost_inflight *inflight)
{
@@ -805,17 +800,18 @@ int vhost_user_set_inflight_fd(struct vhost_dev *dev,
msg.fd_num = 1;
memcpy(msg.fds, &inflight->fd, msg.fd_num * sizeof(int));
- return vu_message_write(client_sock, &msg);
+ return vu_message_write(dev, &msg);
}
-
/* -------------------- Mem regions functions -------------------- */
-
-static MemoryRegion *vhost_user_get_mr_data(struct vhost_memory_region *reg,
+static MemoryRegion *vhost_user_get_mr_data(struct vhost_dev *dev,
+ struct vhost_memory_region *reg,
ram_addr_t *offset, int *fd)
{
MemoryRegion *mr;
+ struct adapter_dev *adev = to_adapter_device(dev, vdev);
+ int loopback_fd = adev->loopback_fd;
(void)reg;
mr = (MemoryRegion *)malloc(sizeof(MemoryRegion));
@@ -855,7 +851,7 @@ static int vhost_user_fill_set_mem_table_msg(struct vhost_user *u,
for (i = 0; i < dev->mem->nregions; ++i) {
reg = dev->mem->regions + i;
- mr = vhost_user_get_mr_data(reg, &offset, &fd);
+ mr = vhost_user_get_mr_data(dev, reg, &offset, &fd);
if (fd > 0) {
if (track_ramblocks) {
u->region_rb_offset[i] = offset;
@@ -896,7 +892,6 @@ static inline bool reg_equal(struct vhost_memory_region *shadow_reg,
shadow_reg->memory_size == vdev_reg->memory_size;
}
-
/* Sync the two region lists (device / adapter) */
static void scrub_shadow_regions(struct vhost_dev *dev,
struct scrub_regions *add_reg,
@@ -905,7 +900,7 @@ static void scrub_shadow_regions(struct vhost_dev *dev,
int *nr_rem_reg, uint64_t *shadow_pcb,
bool track_ramblocks)
{
- struct vhost_user *u = adev->vudev;
+ struct vhost_user *u = dev->vhudev;
bool found[VHOST_USER_MAX_RAM_SLOTS] = {};
struct vhost_memory_region *reg, *shadow_reg;
int fd, add_idx = 0, rm_idx = 0, fd_num = 0;
@@ -930,7 +925,7 @@ static void scrub_shadow_regions(struct vhost_dev *dev,
for (j = 0; j < dev->mem->nregions; j++) {
reg = &dev->mem->regions[j];
- mr = vhost_user_get_mr_data(reg, &offset, &fd);
+ mr = vhost_user_get_mr_data(dev, reg, &offset, &fd);
if (reg_equal(shadow_reg, reg)) {
matching = true;
@@ -963,7 +958,7 @@ static void scrub_shadow_regions(struct vhost_dev *dev,
reg = &dev->mem->regions[i];
- mr = vhost_user_get_mr_data(reg, &offset, &fd);
+ mr = vhost_user_get_mr_data(dev, reg, &offset, &fd);
/*
* If the region was in both the shadow and device state we don't
@@ -984,7 +979,6 @@ static void scrub_shadow_regions(struct vhost_dev *dev,
return;
}
-
static int send_remove_regions(struct vhost_dev *dev,
struct scrub_regions *remove_reg,
int nr_rem_reg, VhostUserMsg *msg,
@@ -994,6 +988,8 @@ static int send_remove_regions(struct vhost_dev *dev,
int i, fd, shadow_reg_idx, ret = 0;
ram_addr_t offset;
VhostUserMemoryRegion region_buffer;
+ struct adapter_dev *adev = to_adapter_device(dev, vdev);
+ int loopback_fd = adev->loopback_fd;
(void)ret;
(void)dev;
@@ -1009,7 +1005,7 @@ static int send_remove_regions(struct vhost_dev *dev,
DBG("Try to remove: 0x%llx\n", remove_reg[i].region->guest_phys_addr);
- (void)vhost_user_get_mr_data(shadow_reg, &offset, &fd);
+ (void)vhost_user_get_mr_data(dev, shadow_reg, &offset, &fd);
if (fd > 0) {
msg->request = VHOST_USER_REM_MEM_REG;
@@ -1019,14 +1015,14 @@ static int send_remove_regions(struct vhost_dev *dev,
msg->fd_num = 1;
memcpy(msg->fds, &loopback_fd, sizeof(int));
- ret = vu_message_write(client_sock, msg);
+ ret = vu_message_write(dev, msg);
if (ret < 0) {
return ret;
}
if (reply_supported) {
msg->flags |= VHOST_USER_NEED_REPLY_MASK;
- ret = process_message_reply(msg);
+ ret = process_message_reply(dev, msg);
/*
* TODO: For this release do not process the message:
@@ -1047,12 +1043,14 @@ static int send_add_regions(struct vhost_dev *dev,
VhostUserMsg *msg, uint64_t *shadow_pcb,
bool reply_supported, bool track_ramblocks)
{
- struct vhost_user *u = adev->vudev;
+ struct vhost_user *u = dev->vhudev;
int i, fd, ret = 0, reg_idx, reg_fd_idx;
struct vhost_memory_region *reg;
MemoryRegion *mr;
ram_addr_t offset;
VhostUserMemoryRegion region_buffer;
+ struct adapter_dev *adev = to_adapter_device(dev, vdev);
+ int loopback_fd = adev->loopback_fd;
(void)dev;
(void)shadow_pcb;
@@ -1067,7 +1065,7 @@ static int send_add_regions(struct vhost_dev *dev,
DBG("Try to add: 0x%llx\n", add_reg[i].region->guest_phys_addr);
- mr = vhost_user_get_mr_data(reg, &offset, &fd);
+ mr = vhost_user_get_mr_data(dev, reg, &offset, &fd);
if (fd > 0) {
@@ -1078,7 +1076,7 @@ static int send_add_regions(struct vhost_dev *dev,
msg->fd_num = 1;
memcpy(msg->fds, &loopback_fd, sizeof(int));
- ret = vu_message_write(client_sock, msg);
+ ret = vu_message_write(dev, msg);
if (ret < 0) {
DBG("send_add_regions -> write failed\n");
return ret;
@@ -1086,7 +1084,7 @@ static int send_add_regions(struct vhost_dev *dev,
if (reply_supported) {
msg->flags |= VHOST_USER_NEED_REPLY_MASK;
- ret = process_message_reply(msg);
+ ret = process_message_reply(dev, msg);
/*
* TODO: For this release do not process the message:
@@ -1109,7 +1107,7 @@ static int vhost_user_add_remove_regions(struct vhost_dev *dev,
bool reply_supported,
bool track_ramblocks)
{
- struct vhost_user *u = adev->vudev;
+ struct vhost_user *u = dev->vhudev;
struct scrub_regions add_reg[VHOST_USER_MAX_RAM_SLOTS];
struct scrub_regions rem_reg[VHOST_USER_MAX_RAM_SLOTS];
uint64_t shadow_pcb[VHOST_USER_MAX_RAM_SLOTS] = {};
@@ -1135,7 +1133,6 @@ static int vhost_user_add_remove_regions(struct vhost_dev *dev,
goto err;
}
-
/* TODO: At this point we need to update the shadow list */
u->num_shadow_regions = dev->mem->nregions;
memcpy(u->shadow_regions, dev->mem->regions,
@@ -1148,7 +1145,6 @@ err:
return -1;
}
-
/* TODO: This funciton might be implemented in a later release */
static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev,
bool reply_supported,
@@ -1161,7 +1157,6 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev,
return 0;
}
-
/*
* TODO: This function is not yet fully optimized because in the current release
* it is not used. t will be implemented or deleted in a later release.
@@ -1176,7 +1171,8 @@ int vhost_user_set_mem_table(struct vhost_dev *dev)
bool config_mem_slots =
virtio_has_feature(dev->protocol_features,
VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS);
- struct vhost_user *u = adev->vudev;
+ //struct vhost_user *u = to_vhost_user_device(dev, dev);
+ struct vhost_user *u = dev->vhudev;
bool do_postcopy = false;
if (do_postcopy) {
@@ -1215,22 +1211,20 @@ int vhost_user_set_mem_table(struct vhost_dev *dev)
msg.fd_num = fd_num;
memcpy(msg.fds, fds, fd_num * sizeof(int));
- ret = vu_message_write(client_sock, &msg);
+ ret = vu_message_write(dev, &msg);
if (ret < 0) {
DBG("vhost_user_set_mem_table failed write msg\n");
return ret;
}
if (reply_supported) {
- ret = process_message_reply(&msg);
+ ret = process_message_reply(dev, &msg);
}
}
return ret;
}
-
-
void print_mem_table(struct vhost_dev *dev)
{
struct vhost_memory_region *cur_vmr;
@@ -1313,41 +1307,33 @@ static bool find_reg(struct vhost_dev *dev, uint64_t hpa, uint64_t len)
return false;
}
-int last_avail = -1;
-
void find_add_new_reg(struct vhost_dev *dev)
{
- int sglist_elem_num;
uint64_t i, j;
+ VirtIODevice *vdev = dev->vdev;
- (void)sglist_elem_num;
DBG("Total nvqs: %d\n", dev->nvqs);
for (i = 0; (unsigned int)i < dev->nvqs; i++) {
- VRing *vring = &dev->vdev->vq[i].vring;
+ VRing *vring = &vdev->vq[i].vring;
uint64_t vring_num = vring->num;
DBG("For vq[%lu]:\n", i);
- DBG("vqs[%lu] hpa 0x%lx\n", i, vring_phys_addrs[i]);
+ DBG("vqs[%lu] hpa 0x%lx\n", i, vdev->vring_phys_addrs[i]);
DBG("vq[%lu].vring.num: %ld\n", i, vring_num);
DBG("We got avail buf: %d\n",
- ((VRingAvail *)(dev->vdev->vq[i].vring.avail))->idx);
-
- int avail_diff = ((VRingAvail *)(dev->vdev->vq[i].vring.avail))->idx
- - last_avail;
+ ((VRingAvail *)(vdev->vq[i].vring.avail))->idx);
for (j = 0; j < vring_num; j++) {
- uint64_t desc_addr = dev->vdev->vq[i].vring.desc;
+ uint64_t desc_addr = vdev->vq[i].vring.desc;
VRingDesc desc_p = ((VRingDesc *)desc_addr)[j];
uint64_t sg_addr = desc_p.addr;
uint64_t sg_len = desc_p.len;
if (desc_p.addr == 0) {
- sglist_elem_num = j;
DBG("We got avail buf: %d\n",
- ((VRingAvail *)(dev->vdev->vq[i].vring.avail))->idx);
- DBG("We got sglist_ele_num: %d\n", sglist_elem_num);
+ ((VRingAvail *)(vdev->vq[i].vring.avail))->idx);
break;
}
@@ -1362,10 +1348,7 @@ void find_add_new_reg(struct vhost_dev *dev)
}
DBG("We got avail buf: %d\n",
- ((VRingAvail *)(dev->vdev->vq[i].vring.avail))->idx);
-
- last_avail = ((VRingAvail *)(dev->vdev->vq[i].vring.avail))->idx;
- sglist_elem_num = 3 * avail_diff;
+ ((VRingAvail *)(vdev->vq[i].vring.avail))->idx);
}
}
@@ -1373,6 +1356,9 @@ void vhost_commit_init_vqs(struct vhost_dev *dev)
{
size_t regions_size;
unsigned int i;
+ //struct adapter_dev *adev = to_adapter_device(dev, vdev);
+ //VirtIODevice *vdev = &adev->virtio_dev;
+ VirtIODevice *vdev = dev->vdev;
dev->n_mem_sections = dev->nvqs;
@@ -1385,8 +1371,8 @@ void vhost_commit_init_vqs(struct vhost_dev *dev)
for (i = 0; i < dev->nvqs; i++) {
struct vhost_memory_region *cur_vmr = dev->mem->regions + i;
- cur_vmr->guest_phys_addr = vring_phys_addrs[i] << PAGE_SHIFT;
- cur_vmr->memory_size = get_vqs_max_size(global_vdev);
+ cur_vmr->guest_phys_addr = vdev->vring_phys_addrs[i] << PAGE_SHIFT;
+ cur_vmr->memory_size = get_vqs_max_size(vdev);
cur_vmr->userspace_addr = 0;
cur_vmr->flags_padding = 0;
}
@@ -1430,7 +1416,7 @@ int vhost_user_backend_init(struct vhost_dev *vhdev)
DBG("vhost_user_backend_init (...)\n");
- err = vhost_user_get_features(&features);
+ err = vhost_user_get_features(vhdev, &features);
if (err < 0) {
DBG("vhost_backend_init failed\n");
return err;
@@ -1439,7 +1425,7 @@ int vhost_user_backend_init(struct vhost_dev *vhdev)
if (virtio_has_feature(features, VHOST_USER_F_PROTOCOL_FEATURES)) {
vhdev->backend_features |= 1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
- err = vhost_user_get_u64(VHOST_USER_GET_PROTOCOL_FEATURES,
+ err = vhost_user_get_u64(vhdev, VHOST_USER_GET_PROTOCOL_FEATURES,
&protocol_features);
if (err < 0) {
DBG("vhost_backend_init failed\n");
@@ -1463,7 +1449,7 @@ int vhost_user_backend_init(struct vhost_dev *vhdev)
!vhdev->config_ops->vhost_dev_config_notifier) {
DBG("There is no config_ops or vhost_dev_config_notifier\n");
/* Don't acknowledge CONFIG feature if device doesn't support it */
- dev->protocol_features &= ~(1ULL << VHOST_USER_PROTOCOL_F_CONFIG);
+ vhdev->protocol_features &= ~(1ULL << VHOST_USER_PROTOCOL_F_CONFIG);
} else if (!(protocol_features &
(1ULL << VHOST_USER_PROTOCOL_F_CONFIG))) {
DBG("Device expects VHOST_USER_PROTOCOL_F_CONFIG "
@@ -1471,7 +1457,7 @@ int vhost_user_backend_init(struct vhost_dev *vhdev)
return -EINVAL;
}
- err = vhost_user_set_protocol_features(vhdev->protocol_features);
+ err = vhost_user_set_protocol_features(vhdev, vhdev->protocol_features);
if (err < 0) {
DBG("vhost_backend_init failed\n");
return -EPROTO;
@@ -1479,7 +1465,7 @@ int vhost_user_backend_init(struct vhost_dev *vhdev)
/* query the max queues we support if backend supports Multiple Queue */
if (vhdev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_MQ)) {
- err = vhost_user_get_u64(VHOST_USER_GET_QUEUE_NUM,
+ err = vhost_user_get_u64(vhdev, VHOST_USER_GET_QUEUE_NUM,
&vhdev->max_queues);
if (err < 0) {
DBG("vhost_backend_init failed\n");
@@ -1510,7 +1496,7 @@ int vhost_user_backend_init(struct vhost_dev *vhdev)
VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS)) {
vhdev->memory_slots = VHOST_MEMORY_BASELINE_NREGIONS;
} else {
- err = vhost_user_get_max_memslots(&ram_slots);
+ err = vhost_user_get_max_memslots(vhdev, &ram_slots);
if (err < 0) {
DBG("vhost_backend_init failed\n");
return -EPROTO;
@@ -1567,12 +1553,12 @@ void vhost_dev_init(struct vhost_dev *vhdev)
(void)vhost_user_backend_init(vhdev);
- r = vhost_user_set_owner();
+ r = vhost_user_set_owner(vhdev);
if (r < 0) {
DBG("vhost_set_owner failed\n");
}
- r = vhost_user_get_features(&features);
+ r = vhost_user_get_features(vhdev, &features);
if (r < 0) {
DBG("vhost_get_features failed\n");
}
@@ -1596,7 +1582,6 @@ void vhost_dev_init(struct vhost_dev *vhdev)
vhdev->log_enabled = false;
vhdev->started = false;
-
/*
* TODO: busyloop == 0 in rng case, but we might need it for new devices:
*
@@ -1651,7 +1636,7 @@ int vhost_user_set_vring_enable(struct vhost_dev *dev, int enable)
static int vhost_user_set_status(struct vhost_dev *dev, uint8_t status)
{
(void)dev;
- return vhost_user_set_u64(VHOST_USER_SET_STATUS, status, false);
+ return vhost_user_set_u64(dev, VHOST_USER_SET_STATUS, status, false);
}
static int vhost_user_get_status(struct vhost_dev *dev, uint8_t *status)
@@ -1660,7 +1645,7 @@ static int vhost_user_get_status(struct vhost_dev *dev, uint8_t *status)
int ret;
(void)dev;
- ret = vhost_user_get_u64(VHOST_USER_GET_STATUS, &value);
+ ret = vhost_user_get_u64(dev, VHOST_USER_GET_STATUS, &value);
if (ret < 0) {
return ret;
}
@@ -1810,3 +1795,167 @@ void print_vhost_user_messages(int request)
DBG("Unhandled request: %d\n", request);
}
}
+
+static void vhost_user_device_reset(VirtIODevice *vdev)
+{
+ DBG("vhost_user_device_reset not yet implemented)\n");
+ (void)vdev;
+
+ /*
+ * TODO: To be added
+ *
+ * if (vdev->active) {
+ * vhost_user_backend_stop(vdev);
+ * }
+ */
+}
+
+
+static void vhost_user_device_unrealize(VirtIODevice *vdev)
+{
+ DBG("vhost_user_device_unrealize not yet implemented\n");
+ (void)vdev;
+}
+
+static void vhost_user_device_stop(VirtIODevice *vdev)
+{
+ DBG("vhost_user_device_stop: not yet implemented\n");
+ (void)vdev;
+}
+
+static uint64_t vhost_user_device_get_features(VirtIODevice *vdev,
+ uint64_t features)
+{
+ DBG("vhost_user_device_get_features()\n");
+
+ return vhost_get_features(vdev->vhdev, vdev->user_feature_bits, features);
+}
+
+
+static void vhost_user_device_set_status(VirtIODevice *vdev, uint8_t status)
+{
+ bool should_start = virtio_device_started(vdev, status);
+ DBG("vhost_user_device_set_status: %d\n", status);
+
+ if (vdev->vhdev->started == should_start) {
+ DBG("vdev->vhost_dev->started == should_start\n");
+ return;
+ }
+
+ if (should_start) {
+ vdev->vdev_class->start(vdev);
+ } else {
+ vdev->vdev_class->stop(vdev);
+ }
+}
+
+/* TODO: We need to implement this function in a future release */
+static void vhost_user_device_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
+{
+ DBG("vhost_user_device_guest_notifier_mask is not yet implemented\n");
+ (void)vdev;
+ (void)idx;
+ (void)mask;
+
+ /* ADD: vhost_virtqueue_mask(&rng->vhost_dev, vdev, idx, mask); */
+ vhost_virtqueue_mask(vdev->vhdev, vdev, idx, mask);
+}
+
+/* TODO: We need to implement this function in a future release */
+static bool vhost_user_device_guest_notifier_pending(VirtIODevice *vdev, int idx)
+{
+ DBG("vhost_user_device_guest_notifier_pending is not yet implemented\n");
+ (void)vdev;
+ (void)idx;
+
+ /* ADD: return vhost_virtqueue_pending(&rng->vhost_dev, idx); */
+ return 1;
+}
+
+static void vhost_user_device_get_config(VirtIODevice *vdev, uint8_t *config)
+{
+ int ret;
+
+ DBG("vhost_user_device_get_config\n");
+
+ memset(config, 0, vdev->config_len);
+
+ ret = vhost_dev_get_config(vdev->vhdev, config, vdev->config_len);
+ if (ret) {
+ DBG("vhost_input_get_config failed\n");
+ return;
+ }
+ //memcpy(config, vdev->config, vdev->config_len);
+}
+
+static void vhost_user_device_start(VirtIODevice *vdev)
+{
+ VirtioBus *k = vdev->vbus;
+ int ret;
+ unsigned int i;
+
+ DBG("vhost_user_device_start(...)\n");
+
+ if (!k->set_guest_notifiers) {
+ DBG("binding does not support guest notifiers\n");
+ return;
+ }
+
+ ret = vhost_dev_enable_notifiers(vdev->vhdev, vdev);
+ if (ret < 0) {
+ DBG("Error enabling host notifiers: %d\n", -ret);
+ return;
+ }
+
+ ret = k->set_guest_notifiers(k->vdev, vdev->vhdev->nvqs, true);
+ if (ret < 0) {
+ DBG("Error binding guest notifier: %d\n", -ret);
+ goto err_host_notifiers;
+ }
+
+ vdev->vhdev->acked_features = vdev->guest_features;
+
+ ret = vhost_dev_start(vdev->vhdev, vdev, true);
+ if (ret < 0) {
+ DBG("Error starting vhost: %d\n", -ret);
+ goto err_guest_notifiers;
+ }
+
+ /*
+ * guest_notifier_mask/pending not used yet, so just unmask
+ * everything here. virtio-pci will do the right thing by
+ * enabling/disabling irqfd.
+ */
+ for (i = 0; i < vdev->vhdev->nvqs; i++) {
+ vhost_virtqueue_mask(vdev->vhdev, vdev, i, false);
+ }
+
+ return;
+
+err_guest_notifiers:
+err_host_notifiers:
+ DBG("vhu_start error\n");
+ return;
+}
+
+
+void vhost_user_dev_class_init(VirtIODevice *vdev)
+{
+ DBG("virtio_loopback_class_init(...)\n");
+ vdev->vdev_class = (VirtioDeviceClass *)malloc(sizeof(VirtioDeviceClass));
+ vdev->vdev_class->parent = vdev;
+
+ /* Define common functions */
+ vdev->vdev_class->realize = NULL;
+ vdev->vdev_class->start = vhost_user_device_start;
+ vdev->vdev_class->stop = vhost_user_device_stop;
+ vdev->vdev_class->unrealize = vhost_user_device_unrealize;
+ vdev->vdev_class->get_config = vhost_user_device_get_config;
+ vdev->vdev_class->get_features = vhost_user_device_get_features;
+ vdev->vdev_class->reset = vhost_user_device_reset;
+ vdev->vdev_class->set_status = vhost_user_device_set_status;
+ vdev->vdev_class->update_mem_table = update_mem_table;
+ vdev->vdev_class->guest_notifier_mask = vhost_user_device_guest_notifier_mask;
+ vdev->vdev_class->guest_notifier_pending = vhost_user_device_guest_notifier_pending;
+
+}
diff --git a/virtio_loopback.c b/src/lib/virtio_loopback.c
index 5457f20..1b57794 100644
--- a/virtio_loopback.c
+++ b/src/lib/virtio_loopback.c
@@ -54,6 +54,7 @@
/* Project header files */
#include "virtio_loopback.h"
+#include "vhost_user_loopback.h"
#include "virtio_rng.h"
#include <stddef.h>
@@ -66,23 +67,6 @@
#define DBG(...)
#endif /* DEBUG */
-/* Global variables */
-
-int s; /* To be deleted */
-int efd; /* Eventfd file descriptor */
-int efd_notify; /* Eventfd file descriptor */
-fd_set rfds;
-int fd;
-int loopback_fd;
-
-virtio_device_info_struct_t device_info;
-virtio_neg_t *address;
-
-VirtIOMMIOProxy *proxy;
-
-int eventfd_count;
-pthread_mutex_t interrupt_lock;
-
void virtio_add_feature(uint64_t *features, unsigned int fbit)
{
*features |= (1ULL << fbit);
@@ -122,8 +106,6 @@ bool virtio_device_started(VirtIODevice *vdev, uint8_t status)
return status & VIRTIO_CONFIG_S_DRIVER_OK;
}
-
-
void virtio_set_started(VirtIODevice *vdev, bool started)
{
if (started) {
@@ -160,7 +142,6 @@ int virtio_set_status(VirtIODevice *vdev, uint8_t val)
DBG("set vdev->status:%u\n", vdev->status);
if (k->set_status) {
- DBG("k->set_status\n");
k->set_status(vdev, val);
}
@@ -194,13 +175,11 @@ uint64_t virtio_queue_get_used_addr(VirtIODevice *vdev, int n)
return vdev->vq[n].vring.used;
}
-
int virtio_queue_get_num(VirtIODevice *vdev, int n)
{
return vdev->vq[n].vring.num;
}
-
uint64_t virtio_queue_get_avail_size(VirtIODevice *vdev, int n)
{
int s;
@@ -242,7 +221,6 @@ static uint16_t virtio_queue_split_get_last_avail_idx(VirtIODevice *vdev,
return vdev->vq[n].last_avail_idx;
}
-
unsigned int virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n)
{
return virtio_queue_split_get_last_avail_idx(vdev, n);
@@ -267,7 +245,6 @@ uint64_t virtio_queue_get_addr(VirtIODevice *vdev, int n)
return vdev->vq[n].vring.desc;
}
-
void virtio_queue_set_addr(VirtIODevice *vdev, int n, uint64_t addr)
{
if (!vdev->vq[n].vring.num) {
@@ -282,7 +259,6 @@ int virtio_queue_ready(VirtQueue *vq)
return vq->vring.avail != 0;
}
-
uint16_t vring_avail_idx(VirtQueue *vq)
{
vq->shadow_avail_idx = ((VRingAvail *)vq->vring.avail)->idx;
@@ -334,7 +310,6 @@ size_t iov_from_buf_full(const struct iovec *iov, unsigned int iov_cnt,
return done;
}
-
size_t qemu_iov_from_buf(const struct iovec *iov, unsigned int iov_cnt,
size_t offset, const void *buf, size_t bytes)
{
@@ -347,7 +322,6 @@ size_t qemu_iov_from_buf(const struct iovec *iov, unsigned int iov_cnt,
}
}
-
/* Called within rcu_read_lock(). */
static inline uint16_t vring_avail_flags(VirtQueue *vq)
{
@@ -366,18 +340,19 @@ static inline uint16_t vring_get_used_event(VirtQueue *vq)
* we have just incremented index from old to new_idx,
* should we trigger an event?
*/
-static inline int vring_need_event(uint16_t event_idx,
- uint16_t new_idx, uint16_t old)
-{
- /*
- * Note: Xen has similar logic for notification hold-off
- * in include/xen/interface/io/ring.h with req_event and req_prod
- * corresponding to event_idx + 1 and new_idx respectively.
- * Note also that req_event and req_prod in Xen start at 1,
- * event indexes in virtio start at 0.
- */
- return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old);
-}
+//static inline int vring_need_event(uint16_t event_idx,
+//static int vring_need_event(uint16_t event_idx,
+// uint16_t new_idx, uint16_t old)
+//{
+// /*
+// * Note: Xen has similar logic for notification hold-off
+// * in include/xen/interface/io/ring.h with req_event and req_prod
+// * corresponding to event_idx + 1 and new_idx respectively.
+// * Note also that req_event and req_prod in Xen start at 1,
+// * event indexes in virtio start at 0.
+// */
+// return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old);
+//}
/* Called within rcu_read_lock(). */
static bool virtio_split_should_notify(VirtIODevice *vdev, VirtQueue *vq)
@@ -408,7 +383,6 @@ static bool virtio_should_notify(VirtIODevice *vdev, VirtQueue *vq)
return virtio_split_should_notify(vdev, vq);
}
-
void virtio_set_isr(VirtIODevice *vdev, int value)
{
uint8_t old = vdev->isr;
@@ -454,7 +428,6 @@ void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
DBG("Do not notify!\n");
return;
}
- DBG("Go on and notify!\n");
virtio_irq(vq);
}
@@ -523,7 +496,6 @@ void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
virtqueue_flush(vq, 1);
}
-
void vring_set_avail_event(VirtQueue *vq, uint16_t val)
{
uint16_t *avail;
@@ -769,7 +741,6 @@ int virtqueue_split_read_next_desc(VirtIODevice *vdev, VRingDesc *desc,
return VIRTQUEUE_READ_DESC_MORE;
}
-
static void virtqueue_split_get_avail_bytes(VirtQueue *vq,
unsigned int *in_bytes, unsigned int *out_bytes,
unsigned max_in_bytes, unsigned max_out_bytes)
@@ -980,7 +951,7 @@ void print_neg_flag(uint64_t neg_flag, bool read)
if (neg_flag >= VIRTIO_MMIO_CONFIG) {
DBG("\tVIRTIO_MMIO_CONFIG\n");
} else {
- DBG("\tNegotiation flag Unknown: %ld\n", neg_flag);
+ DBG("\tNegotiation flag Unknown: %lu\n", neg_flag);
}
return;
}
@@ -1012,7 +983,6 @@ int virtio_set_features(VirtIODevice *vdev, uint64_t val)
return ret;
}
-
/* TODO: MMIO notifiers -- This might not be needed anymore */
static void virtio_queue_guest_notifier_read(EventNotifier *n)
{
@@ -1029,6 +999,7 @@ void *loopback_event_select(void *_e)
EventNotifier *e = (EventNotifier *)_e;
int rfd = e->rfd;
VirtQueue *vq = container_of(e, VirtQueue, guest_notifier);
+ VirtIODevice *vdev = vq->vdev;
DBG("\nWaiting event from vhost-user-device\n");
@@ -1043,24 +1014,23 @@ void *loopback_event_select(void *_e)
}
if (retval > 0) {
- if (pthread_mutex_lock(&interrupt_lock) != 0) {
+ if (pthread_mutex_lock(&vdev->interrupt_lock) != 0) {
printf("[ERROR] Locking failed\n");
exit(1);
}
DBG("\n\nEvent has come from the vhost-user-device "
"(eventfd: %d) -> event_count: %d (select value: %d)\n\n",
- rfd, eventfd_count, retval);
+ rfd, vdev->eventfd_count, retval);
if (event_notifier_test_and_clear(e)) {
- eventfd_count++;
+ vdev->eventfd_count++;
virtio_irq(vq);
}
- pthread_mutex_unlock(&interrupt_lock);
+ pthread_mutex_unlock(&vdev->interrupt_lock);
}
}
}
-
void event_notifier_set_handler(EventNotifier *e,
void *handler)
{
@@ -1077,7 +1047,6 @@ void event_notifier_set_handler(EventNotifier *e,
}
}
-
void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
bool with_irqfd)
{
@@ -1159,12 +1128,12 @@ void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled)
int virtio_bus_set_host_notifier(VirtioBus *vbus, int n, bool assign)
{
VirtIODevice *vdev = vbus->vdev;
+ struct adapter_dev *adev = to_adapter_device(vdev, virtio_dev);
VirtQueue *vq = virtio_get_queue(vdev, n);
EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
int r = 0;
-
if (!vbus->ioeventfd_assign) {
return -ENOSYS;
}
@@ -1175,12 +1144,12 @@ int virtio_bus_set_host_notifier(VirtioBus *vbus, int n, bool assign)
DBG("unable to init event notifier: %d", r);
return r;
}
- r = vbus->ioeventfd_assign(proxy, notifier, n, true);
+ r = vbus->ioeventfd_assign(&adev->proxy, notifier, n, true);
if (r < 0) {
DBG("unable to assign ioeventfd: %d", r);
}
} else {
- vbus->ioeventfd_assign(proxy, notifier, n, false);
+ vbus->ioeventfd_assign(&adev->proxy, notifier, n, false);
}
if (r == 0) {
@@ -1190,8 +1159,6 @@ int virtio_bus_set_host_notifier(VirtioBus *vbus, int n, bool assign)
return r;
}
-
-
/* On success, ioeventfd ownership belongs to the caller. */
int virtio_bus_grab_ioeventfd(VirtioBus *bus)
{
@@ -1224,12 +1191,10 @@ bool virtio_device_disabled(VirtIODevice *vdev)
return vdev->disabled || vdev->broken;
}
-static int prev_level;
-static int int_count;
-
void virtio_loopback_update_irq(VirtIODevice *vdev)
{
int level, irq_num = 44;
+ struct adapter_dev *adev = to_adapter_device(vdev, virtio_dev);
if (!vdev) {
return;
@@ -1237,24 +1202,19 @@ void virtio_loopback_update_irq(VirtIODevice *vdev)
level = (vdev->isr != 0);
- DBG("level: %d\n", level);
- DBG("prev_level: %d\n", prev_level);
-
- if (!((level == 1) && (prev_level == 0))) {
+ if (!((level == 1) && (vdev->prev_level == 0))) {
DBG("No interrupt\n");
- prev_level = level;
+ vdev->prev_level = level;
return;
}
- prev_level = level;
+ vdev->prev_level = level;
DBG("Trigger interrupt (ioctl)\n");
- DBG("Interrupt counter: %d\n", int_count++);
+ DBG("Interrupt counter: %d\n", vdev->int_count++);
- (void) ioctl(fd, IRQ, &irq_num);
+ (void) ioctl(adev->loopback_fd, IRQ, &irq_num);
}
-bool enable_virtio_interrupt;
-
/* virtio device */
void virtio_notify_vector(VirtIODevice *vdev)
{
@@ -1296,7 +1256,6 @@ void virtio_queue_notify(VirtIODevice *vdev, int n)
if (vq->host_notifier_enabled) {
event_notifier_set(&vq->host_notifier);
} else if (vq->handle_output) {
- DBG("vq->handle_output\n");
vq->handle_output(vdev, vq);
if (vdev->start_on_kick) {
@@ -1402,13 +1361,12 @@ void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data)
}
}
-
-
static uint64_t virtio_loopback_read(VirtIODevice *vdev, uint64_t offset,
unsigned size)
{
uint64_t ret;
+ struct adapter_dev *adev = to_adapter_device(vdev, virtio_dev);
if (!vdev) {
/*
@@ -1424,7 +1382,7 @@ static uint64_t virtio_loopback_read(VirtIODevice *vdev, uint64_t offset,
case VIRTIO_MMIO_MAGIC_VALUE:
return VIRT_MAGIC;
case VIRTIO_MMIO_VERSION:
- if (proxy->legacy) {
+ if (adev->proxy.legacy) {
return VIRT_VERSION_LEGACY;
} else {
return VIRT_VERSION;
@@ -1439,7 +1397,7 @@ static uint64_t virtio_loopback_read(VirtIODevice *vdev, uint64_t offset,
if (offset >= VIRTIO_MMIO_CONFIG) {
offset -= VIRTIO_MMIO_CONFIG;
- if (proxy->legacy) {
+ if (adev->proxy.legacy) {
switch (size) {
case 1:
ret = virtio_config_readb(vdev, offset);
@@ -1451,9 +1409,9 @@ static uint64_t virtio_loopback_read(VirtIODevice *vdev, uint64_t offset,
ret = virtio_config_readl(vdev, offset);
break;
default:
+ DBG("VIRTIO_MMIO_CONFIG abort\n");
abort();
}
- DBG("ret: %lu\n", ret);
return ret;
}
@@ -1469,7 +1427,7 @@ static uint64_t virtio_loopback_read(VirtIODevice *vdev, uint64_t offset,
case VIRTIO_MMIO_MAGIC_VALUE:
return VIRT_MAGIC;
case VIRTIO_MMIO_VERSION:
- if (proxy->legacy) {
+ if (adev->proxy.legacy) {
DBG("VIRTIO_MMIO_VERSION -> legacy\n");
return VIRT_VERSION_LEGACY;
} else {
@@ -1479,11 +1437,10 @@ static uint64_t virtio_loopback_read(VirtIODevice *vdev, uint64_t offset,
case VIRTIO_MMIO_DEVICE_ID:
return vdev->device_id;
case VIRTIO_MMIO_VENDOR_ID:
- DBG("READ\n");
return VIRT_VENDOR;
case VIRTIO_MMIO_DEVICE_FEATURES:
- if (proxy->legacy) {
- if (proxy->host_features_sel) {
+ if (adev->proxy.legacy) {
+ if (adev->proxy.host_features_sel) {
return vdev->host_features >> 32;
} else {
return vdev->host_features & (uint64_t)(((1ULL << 32) - 1));
@@ -1496,16 +1453,16 @@ static uint64_t virtio_loopback_read(VirtIODevice *vdev, uint64_t offset,
DBG("Return queue_size = %d\n", vdev->vq[vdev->queue_sel].vring.num);
return vdev->vq[vdev->queue_sel].vring.num;
case VIRTIO_MMIO_QUEUE_PFN:
- if (!proxy->legacy) {
+ if (!adev->proxy.legacy) {
DBG("VIRTIO_MMIO_QUEUE_PFN: read from legacy register (0x%lx) "
"in non-legacy mode\n", offset);
return 0;
}
return virtio_queue_get_addr(vdev, vdev->queue_sel) >>
- proxy->guest_page_shift;
+ adev->proxy.guest_page_shift;
case VIRTIO_MMIO_QUEUE_READY:
- if (proxy->legacy) {
+ if (adev->proxy.legacy) {
DBG("VIRTIO_MMIO_QUEUE_READY: read from legacy register (0x%lx) "
"in non-legacy mode\n", offset);
return 0;
@@ -1519,7 +1476,7 @@ static uint64_t virtio_loopback_read(VirtIODevice *vdev, uint64_t offset,
DBG("Read VIRTIO_MMIO_STATUS: %d\n", vdev->status);
return vdev->status;
case VIRTIO_MMIO_CONFIG_GENERATION:
- if (proxy->legacy) {
+ if (adev->proxy.legacy) {
DBG("VIRTIO_MMIO_CONFIG_GENERATION: read from legacy "
"register (0x%lx) in non-legacy mode\n", offset);
return 0;
@@ -1558,13 +1515,11 @@ static uint64_t virtio_loopback_read(VirtIODevice *vdev, uint64_t offset,
return 0;
}
-uint64_t vring_phys_addrs[10] = {0};
-uint32_t vring_phys_addrs_idx;
-static int notify_cnt;
-
void virtio_loopback_write(VirtIODevice *vdev, uint64_t offset,
uint64_t value, unsigned size)
{
+ struct adapter_dev *adev = to_adapter_device(vdev, virtio_dev);
+
if (!vdev) {
/*
* If no backend is present, we just make all registers
@@ -1577,7 +1532,7 @@ void virtio_loopback_write(VirtIODevice *vdev, uint64_t offset,
if (offset >= VIRTIO_MMIO_CONFIG) {
offset -= VIRTIO_MMIO_CONFIG;
- if (proxy->legacy) {
+ if (adev->proxy.legacy) {
switch (size) {
case 1:
virtio_config_writeb(vdev, offset, value);
@@ -1605,14 +1560,14 @@ void virtio_loopback_write(VirtIODevice *vdev, uint64_t offset,
case VIRTIO_MMIO_DEVICE_FEATURES_SEL:
DBG("VIRTIO_MMIO_DEVICE_FEATURES_SEL: 0x%lx\n", value);
if (value) {
- proxy->host_features_sel = 1;
+ adev->proxy.host_features_sel = 1;
} else {
- proxy->host_features_sel = 0;
+ adev->proxy.host_features_sel = 0;
}
break;
case VIRTIO_MMIO_DRIVER_FEATURES:
- if (proxy->legacy) {
- if (proxy->guest_features_sel) {
+ if (adev->proxy.legacy) {
+ if (adev->proxy.guest_features_sel) {
DBG("Set driver features: 0x%lx\n", value << 32);
virtio_set_features(vdev, value << 32);
} else {
@@ -1625,19 +1580,19 @@ void virtio_loopback_write(VirtIODevice *vdev, uint64_t offset,
break;
case VIRTIO_MMIO_DRIVER_FEATURES_SEL:
if (value) {
- proxy->guest_features_sel = 1;
+ adev->proxy.guest_features_sel = 1;
} else {
- proxy->guest_features_sel = 0;
+ adev->proxy.guest_features_sel = 0;
}
break;
case VIRTIO_MMIO_GUEST_PAGE_SIZE:
- if (!proxy->legacy) {
+ if (!adev->proxy.legacy) {
DBG("write to legacy register (0x%lx"
") in non-legacy mode\n", offset);
return;
}
- if (proxy->guest_page_shift > 31) {
- proxy->guest_page_shift = 0;
+ if (adev->proxy.guest_page_shift > 31) {
+ adev->proxy.guest_page_shift = 0;
}
break;
case VIRTIO_MMIO_QUEUE_SEL:
@@ -1650,7 +1605,7 @@ void virtio_loopback_write(VirtIODevice *vdev, uint64_t offset,
virtio_queue_set_num(vdev, vdev->queue_sel, value);
- if (proxy->legacy) {
+ if (adev->proxy.legacy) {
virtio_queue_update_rings(vdev, vdev->queue_sel);
} else {
/* TODO: To be implemented */
@@ -1658,7 +1613,7 @@ void virtio_loopback_write(VirtIODevice *vdev, uint64_t offset,
}
break;
case VIRTIO_MMIO_QUEUE_ALIGN:
- if (!proxy->legacy) {
+ if (!adev->proxy.legacy) {
DBG("write to legacy register (0x%lx) in "
"non-legacy mode\n", offset);
return;
@@ -1666,33 +1621,34 @@ void virtio_loopback_write(VirtIODevice *vdev, uint64_t offset,
/* TODO: To be implemented */
break;
case VIRTIO_MMIO_QUEUE_PFN:
- if (!proxy->legacy) {
+ if (!adev->proxy.legacy) {
DBG("write to legacy register (0x%lx) in "
"non-legacy mode\n", offset);
return;
}
if (value == 0) {
/* TODO: To be implemented */
+ DBG("Not implemented\n");
} else {
DBG("desc_addr: 0x%lx\n", value);
- vring_phys_addrs[vring_phys_addrs_idx++] = value;
+ vdev->vring_phys_addrs[vdev->vring_phys_addrs_idx++] = value;
uint64_t desc_addr;
- uint32_t vqs_size = get_vqs_max_size(global_vdev);
+ uint32_t vqs_size = get_vqs_max_size(vdev);
- ioctl(fd, SHARE_VQS, &vdev->queue_sel);
+ ioctl(adev->loopback_fd, SHARE_VQS, &vdev->queue_sel);
desc_addr = (uint64_t)mmap(NULL, vqs_size,
PROT_READ | PROT_WRITE,
- MAP_SHARED, fd, 0);
+ MAP_SHARED, adev->loopback_fd, 0);
virtio_queue_set_addr(vdev, vdev->queue_sel,
desc_addr);
}
break;
case VIRTIO_MMIO_QUEUE_READY:
- if (proxy->legacy) {
+ if (adev->proxy.legacy) {
DBG("write to non-legacy register (0x%lx) in "
"legacy mode\n", offset);
return;
@@ -1701,7 +1657,7 @@ void virtio_loopback_write(VirtIODevice *vdev, uint64_t offset,
break;
case VIRTIO_MMIO_QUEUE_NOTIFY:
DBG("VIRTIO_MMIO_QUEUE_NOTIFY: vq_index -> %lu, notify_cnt: %d\n",
- value, notify_cnt++);
+ value, vdev->notify_cnt++);
if (value < VIRTIO_QUEUE_MAX) {
virtio_queue_notify(vdev, value);
}
@@ -1716,32 +1672,32 @@ void virtio_loopback_write(VirtIODevice *vdev, uint64_t offset,
* TODO: Add it in a future release later
*
* if (!(value & VIRTIO_CONFIG_S_DRIVER_OK)) {
- * virtio_loopback_stop_ioeventfd(proxy);
+ * virtio_loopback_stop_ioeventfd(adev->proxy);
* }
*/
- if (!proxy->legacy && (value & VIRTIO_CONFIG_S_FEATURES_OK)) {
+ if (!adev->proxy.legacy && (value & VIRTIO_CONFIG_S_FEATURES_OK)) {
virtio_set_features(vdev,
- ((uint64_t)proxy->guest_features[1]) << 32 |
- proxy->guest_features[0]);
+ ((uint64_t)adev->proxy.guest_features[1]) << 32 |
+ adev->proxy.guest_features[0]);
}
virtio_set_status(vdev, value & 0xff);
- DBG("STATUS -> %ld\n", value);
+ DBG("STATUS -> %lu\n", value);
/*
* TODO: Check if this is still needed
*
* if (vdev->status == 0) {
* virtio_reset(vdev);
- * virtio_loopback_soft_reset(proxy);
+ * virtio_loopback_soft_reset(adev->proxy);
* }
*/
break;
case VIRTIO_MMIO_QUEUE_DESC_LOW:
- if (proxy->legacy) {
+ if (adev->proxy.legacy) {
DBG("write to non-legacy register (0x%lx) in "
"legacy mode\n", offset);
return;
@@ -1749,7 +1705,7 @@ void virtio_loopback_write(VirtIODevice *vdev, uint64_t offset,
/* TODO: To be implemented */
break;
case VIRTIO_MMIO_QUEUE_DESC_HIGH:
- if (proxy->legacy) {
+ if (adev->proxy.legacy) {
DBG("write to non-legacy register (0x%lx) in "
"legacy mode\n", offset);
return;
@@ -1757,7 +1713,7 @@ void virtio_loopback_write(VirtIODevice *vdev, uint64_t offset,
/* TODO: To be implemented */
break;
case VIRTIO_MMIO_QUEUE_AVAIL_LOW:
- if (proxy->legacy) {
+ if (adev->proxy.legacy) {
DBG("write to non-legacy register (0x%lx) in "
"legacy mode\n", offset);
return;
@@ -1765,7 +1721,7 @@ void virtio_loopback_write(VirtIODevice *vdev, uint64_t offset,
/* TODO: To be implemented */
break;
case VIRTIO_MMIO_QUEUE_AVAIL_HIGH:
- if (proxy->legacy) {
+ if (adev->proxy.legacy) {
DBG("write to non-legacy register (0x%lx) in "
"legacy mode\n", offset);
return;
@@ -1773,7 +1729,7 @@ void virtio_loopback_write(VirtIODevice *vdev, uint64_t offset,
/* TODO: To be implemented */
break;
case VIRTIO_MMIO_QUEUE_USED_LOW:
- if (proxy->legacy) {
+ if (adev->proxy.legacy) {
DBG("write to non-legacy register (0x%lx) in "
"legacy mode\n", offset);
return;
@@ -1781,7 +1737,7 @@ void virtio_loopback_write(VirtIODevice *vdev, uint64_t offset,
/* TODO: To be implemented */
break;
case VIRTIO_MMIO_QUEUE_USED_HIGH:
- if (proxy->legacy) {
+ if (adev->proxy.legacy) {
DBG("write to non-legacy register (0x%lx) in "
"legacy mode\n", offset);
return;
@@ -1803,44 +1759,43 @@ void virtio_loopback_write(VirtIODevice *vdev, uint64_t offset,
}
}
-VirtIODevice *global_vdev;
-VirtioBus *global_vbus;
-
-void adapter_read_write_cb(void)
+void adapter_read_write_cb(struct adapter_dev *adev)
{
/*
* Enabling the next line, all the incoming
* read/write events will be printed:
*
- * print_neg_flag (address->notification, address->read);
+ * print_neg_flag (adev->address->notification, adev->address->read);
*/
- print_neg_flag(address->notification, address->read);
+ print_neg_flag(adev->address->notification, adev->address->read);
- if (address->read) {
- address->data = virtio_loopback_read(global_vdev,
- address->notification, address->size);
+ if (adev->address->read) {
+ adev->address->data = virtio_loopback_read(&adev->virtio_dev,
+ adev->address->notification, adev->address->size);
} else {
- virtio_loopback_write(global_vdev, address->notification,
- address->data, address->size);
+ virtio_loopback_write(&adev->virtio_dev, adev->address->notification,
+ adev->address->data, adev->address->size);
}
DBG("Return to the driver\n");
/*
* Note the driver that we have done
- * All the required actions.
+ * all the required actions.
*/
- (void)ioctl(fd, WAKEUP);
+ (void)ioctl(adev->loopback_fd, WAKEUP);
}
void *driver_event_select(void *data)
{
- int retval;
+ int retval, s;
uint64_t eftd_ctr;
- int efd = *(int *)data;
+ fd_set rfds;
+ struct adapter_dev *adev = (struct adapter_dev *)data;
+ int efd = adev->efd;
- DBG("\nWaiting for loopback read/write events\n");
+ DBG("\nWaiting for loopback read/write events (efd :%d)\n", efd);
FD_ZERO(&rfds);
FD_SET(efd, &rfds);
@@ -1859,7 +1814,7 @@ void *driver_event_select(void *data)
DBG("\neventfd read error. Exiting...");
exit(1);
} else {
- adapter_read_write_cb();
+ adapter_read_write_cb(adev);
}
} else if (retval == 0) {
@@ -1868,14 +1823,6 @@ void *driver_event_select(void *data)
}
}
-void create_rng_struct(void)
-{
- device_info.magic = 0x74726976;
- device_info.version = 0x1;
- device_info.device_id = 0x4;
- device_info.vendor = 0x554d4551;
-}
-
VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n)
{
return vdev->vq + n;
@@ -1910,20 +1857,21 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
void virtio_dev_init(VirtIODevice *vdev, const char *name,
uint16_t device_id, size_t config_size)
{
+ struct adapter_dev *adev = to_adapter_device(vdev, virtio_dev);
int i;
DBG("virtio_dev_init\n");
/* Initialize global variables */
- prev_level = 0;
- int_count = 0;
- eventfd_count = 0;
- enable_virtio_interrupt = false;
- vring_phys_addrs_idx = 0;
- notify_cnt = 0;
+ vdev->prev_level = 0;
+ vdev->int_count = 0;
+ vdev->enable_virtio_interrupt = false;
+ vdev->vring_phys_addrs_idx = 0;
+ vdev->eventfd_count = 0;
+ vdev->notify_cnt = 0;
/* Initialize interrupt mutex */
- if (pthread_mutex_init(&interrupt_lock, NULL) != 0) {
+ if (pthread_mutex_init(&vdev->interrupt_lock, NULL) != 0) {
printf("[ERROR] mutex init has failed\n");
exit(1);
}
@@ -1932,6 +1880,7 @@ void virtio_dev_init(VirtIODevice *vdev, const char *name,
vdev->started = false;
vdev->device_id = device_id;
vdev->status = 0;
+ vdev->last_avail = -1;
vdev->queue_sel = 0;
vdev->config_vector = VIRTIO_NO_VECTOR;
/* TODO: check malloc return value */
@@ -1953,14 +1902,20 @@ void virtio_dev_init(VirtIODevice *vdev, const char *name,
vdev->config = NULL;
}
+ /* Initialize device_info */
+ adev->device_info.magic = 0x74726976;
+ adev->device_info.version = 0x1;
+ adev->device_info.device_id = device_id;
+ adev->device_info.vendor = 0x554d4551;
+
vdev->use_guest_notifier_mask = true;
- DBG("virtio_dev_init return\n");
}
static bool virtio_loopback_ioeventfd_enabled(VirtIODevice *d)
{
- (void)d;
- return (proxy->flags & VIRTIO_IOMMIO_FLAG_USE_IOEVENTFD) != 0;
+ struct adapter_dev *adev = to_adapter_device(d, virtio_dev);
+
+ return (adev->proxy.flags & VIRTIO_IOMMIO_FLAG_USE_IOEVENTFD) != 0;
}
/* TODO: This function might not be needed anymore */
@@ -1992,63 +1947,61 @@ void virtio_loopback_bus_init(VirtioBus *k)
k->set_guest_notifiers = virtio_loopback_set_guest_notifiers;
k->ioeventfd_enabled = virtio_loopback_ioeventfd_enabled;
k->ioeventfd_assign = virtio_loopback_ioeventfd_assign;
- DBG("virtio_loopback_bus_init(...) return\n");
}
-
-int virtio_loopback_start(void)
+int virtio_loopback_start(struct adapter_dev *adev, pthread_t *thread_id)
{
efd_data_t info;
- pthread_t thread_id;
int ret = -1;
- fd = open("/dev/loopback", O_RDWR);
- if (fd < 0) {
+ adev->loopback_fd = open("/dev/loopback", O_RDWR);
+ if (adev->loopback_fd < 0) {
perror("Open call failed");
return -1;
}
- loopback_fd = fd;
/* Create eventfd */
- efd = eventfd(0, 0);
- if (efd == -1) {
+ adev->efd = eventfd(0, 0);
+ if (adev->efd == -1) {
DBG("\nUnable to create eventfd! Exiting...\n");
exit(EXIT_FAILURE);
}
info.pid = getpid();
- info.efd[0] = efd;
+ info.efd[0] = adev->efd;
/*
* Send the appropriate information to the driver
* so to be able to trigger an eventfd
*/
- (void)ioctl(fd, EFD_INIT, &info);
+ (void)ioctl(adev->loopback_fd, EFD_INIT, &info);
/* Map communication mechanism */
- (void)ioctl(fd, SHARE_COM_STRUCT);
- address = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (address == MAP_FAILED) {
+ (void)ioctl(adev->loopback_fd, SHARE_COM_STRUCT);
+ adev->address = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, adev->loopback_fd, 0);
+ if (adev->address == MAP_FAILED) {
perror("mmap operation failed");
return -1;
}
/* Wait the eventfd */
- ret = pthread_create(&thread_id, NULL, driver_event_select, (void *)&efd);
+ ret = pthread_create(thread_id, NULL, driver_event_select, (void *)adev);
if (ret != 0) {
- exit(1);
+ goto error_start;
}
/* Start loopback transport */
- (void)ioctl(fd, START_LOOPBACK, &device_info);
+ (void)ioctl(adev->loopback_fd, START_LOOPBACK, &adev->device_info);
- ret = pthread_join(thread_id, NULL);
- if (ret != 0) {
- exit(1);
- }
+error_start:
+ return ret;
+}
- DBG("\nClosing eventfd. Exiting...\n");
- close(efd);
+void virtio_loopback_stop(struct adapter_dev *adev)
+{
+ DBG("\nClosing eventfd\n");
+ close(adev->efd);
- exit(EXIT_SUCCESS);
+ DBG("\nClosing loopback fd. Exiting...\n");
+ close(adev->loopback_fd);
}
diff --git a/vhost_user_can.c b/vhost_user_can.c
deleted file mode 100644
index c645948..0000000
--- a/vhost_user_can.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Virtio CAN Device
- *
- * Based on virtio_can.h of OpenSynergy's virtio-can RFC
- * https://github.com/OpenSynergy/qemu/tree/virtio-can-spec-rfc-v3
- *
- * Copyright (C) 2021-2023 OpenSynergy GmbH
- * Copyright (c) 2023 Virtual Open Systems SAS.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <stdbool.h>
-#include <sys/param.h>
-
-/* Project header files */
-#include "vhost_user_can.h"
-
-#ifdef DEBUG
-#define DBG(...) printf("vhost-user-can: " __VA_ARGS__)
-#else
-#define DBG(...)
-#endif /* DEBUG */
-
-/***************************** vhost-user-can ******************************/
-
-static const int user_feature_bits[] = {
- VIRTIO_F_VERSION_1,
- VIRTIO_RING_F_INDIRECT_DESC,
- VIRTIO_RING_F_EVENT_IDX,
- VIRTIO_F_RING_RESET,
- VIRTIO_F_NOTIFY_ON_EMPTY,
- VHOST_INVALID_FEATURE_BIT
-};
-
-static void vhost_user_can_get_config(VirtIODevice *vdev, uint8_t *config)
-{
- VHostUserCan *can = vdev->vhucan;
-
- DBG("vhost_user_can_get_config: Not yet implemented!\n");
-
- /*
- * TODO : Add this check depend on 'busoff' value
- * if (vcan->busoff) {
- * config->status = cpu_to_le32(VIRTIO_CAN_S_CTRL_BUSOFF);
- * } else {
- * config->status = cpu_to_le32(0);
- * }
- */
-
- memcpy(config, &can->config, sizeof(struct virtio_can_config));
-}
-
-
-static void vhost_user_can_start(VirtIODevice *vdev)
-{
- VHostUserCan *vhucan = vdev->vhucan;
- VirtioBus *k = vdev->vbus;
- int ret;
- unsigned int i;
-
- DBG("vhost_user_can_start(...)\n");
-
- if (!k->set_guest_notifiers) {
- DBG("binding does not support guest notifiers\n");
- return;
- }
-
- ret = vhost_dev_enable_notifiers(vhucan->vhost_dev, vdev);
- if (ret < 0) {
- DBG("Error enabling host notifiers: %d\n", -ret);
- return;
- }
-
- ret = k->set_guest_notifiers(k->vdev, vhucan->vhost_dev->nvqs, true);
- if (ret < 0) {
- DBG("Error binding guest notifier: %d\n", -ret);
- goto err_host_notifiers;
- }
-
- vhucan->vhost_dev->acked_features = vdev->guest_features;
-
- ret = vhost_dev_start(vhucan->vhost_dev, vdev, true);
- if (ret < 0) {
- DBG("Error starting vhost: %d\n", -ret);
- goto err_guest_notifiers;
- }
-
- /*
- * guest_notifier_mask/pending not used yet, so just unmask
- * everything here. virtio-pci will do the right thing by
- * enabling/disabling irqfd.
- */
- for (i = 0; i < vhucan->vhost_dev->nvqs; i++) {
- vhost_virtqueue_mask(vhucan->vhost_dev, vdev, i, false);
- }
-
- return;
-
-err_guest_notifiers:
-err_host_notifiers:
- DBG("vhu_start error\n");
- return;
-}
-
-static void vhost_user_can_stop(VirtIODevice *vdev)
-{
- DBG("vhost_user_can_stop: not yet implemented\n");
- (void)vdev;
-}
-
-static void vhost_user_can_set_status(VirtIODevice *vdev, uint8_t status)
-{
- VHostUserCan *vhucan = vdev->vhucan;
- bool should_start = virtio_device_started(vdev, status);
- DBG("vhost_user_can_set_status: %d\n", status);
-
- if (vhucan->vhost_dev->started == should_start) {
- DBG("can->vhost_dev->started == should_start\n");
- return;
- }
-
- if (should_start) {
- vhost_user_can_start(vdev);
- } else {
- vhost_user_can_stop(vdev);
- }
-}
-
-static uint64_t vhost_user_can_get_features(VirtIODevice *vdev,
- uint64_t features)
-{
- VHostUserCan *s = vdev->vhucan;
-
- DBG("vhost_user_can_get_features()\n");
-
- return vhost_get_features(s->vhost_dev, user_feature_bits, features);
-}
-
-static void vhost_user_can_can_handle_output(VirtIODevice *vdev, VirtQueue *vq)
-{
- /*
- * Not normally called; it's the daemon that handles the queue;
- * however virtio's cleanup path can call this.
- */
- DBG("vhost_user_can_can_handle_output: Not yet implemented!\n");
- (void)vdev;
- (void)vq;
-}
-
-/*
- * TODO: Add it later
- * static void vhost_sound_guest_notifier_mask(VirtIODevice *vdev, int idx,
- * bool mask)
- */
-
-/*
- * TODO: Add it later
- * static bool vhost_sound_guest_notifier_pending(VirtIODevice *vdev,
- * int idx)
- */
-
-static int vhost_user_can_can_config_change(struct vhost_dev *dev)
-{
- VHostUserCan *vhucan = dev->vdev->vhucan;
- DBG("vhost_user_can_can_config_change: Not yet implemented!\n");
-
- int ret = vhost_dev_get_config(dev, (uint8_t *)&vhucan->config,
- sizeof(struct virtio_can_config));
- if (ret < 0) {
- DBG("vhost_user_can_sound_config_change error\n");
- return -1;
- }
-
- virtio_notify_config(dev->vdev);
-
- return 0;
-}
-
-const VhostDevConfigOps can_config_ops = {
- .vhost_dev_config_notifier = vhost_user_can_can_config_change,
-};
-
-static void vhost_user_can_init(VirtIODevice *vdev);
-
-void vhost_user_can_realize(int queue_num, int queue_size)
-{
- VirtIODevice *vdev = global_vdev;
- int ret;
-
- DBG("vhost_user_can_device_realize\n");
- (void)queue_num;
- (void)queue_size;
-
- /* This needs to be added */
- proxy = (VirtIOMMIOProxy *)malloc(sizeof(VirtIOMMIOProxy));
- *proxy = (VirtIOMMIOProxy) {
- .legacy = 1,
- };
-
- /* VIRTIO_ID_CAN is 36, check virtio_ids.h in linux*/
- virtio_dev_init(vdev, "virtio-can", 36, sizeof(vdev->vhucan->config));
- vhost_user_can_init(global_vdev);
-
- /* add queues */
- vdev->vhucan->ctrl_vq = virtio_add_queue(vdev, 64,
- vhost_user_can_can_handle_output);
- vdev->vhucan->tx_vq = virtio_add_queue(vdev, 64,
- vhost_user_can_can_handle_output);
- vdev->vhucan->rx_vq = virtio_add_queue(vdev, 64,
- vhost_user_can_can_handle_output);
- vdev->vhucan->vhost_dev->nvqs = 3;
- vdev->vhucan->num_queues = 3;
- vdev->vhucan->queue_size = 64;
-
- /* NOTE: global_vdev->vqs == vhucan->virtqs */
- vdev->vqs = (VirtQueue **)malloc(sizeof(VirtQueue *)
- * global_vdev->vhucan->num_queues);
- vdev->vqs[0] = vdev->vhucan->tx_vq;
- vdev->vqs[1] = vdev->vhucan->rx_vq;
- vdev->vqs[2] = vdev->vhucan->ctrl_vq;
-
- vdev->vhucan->vhost_vqs = (struct vhost_virtqueue *)malloc(
- sizeof(struct vhost_virtqueue) *
- vdev->vhucan->num_queues);
-
- /* Set up vhost device */
- vdev->vhucan->vhost_dev->num_queues = vdev->vhucan->num_queues;
- vdev->vhucan->vhost_dev->nvqs = vdev->vhucan->num_queues;
- vdev->vhucan->vhost_dev->vqs = vdev->vhucan->vhost_vqs;
- vdev->vhucan->vhost_dev->vq_index = 0;
- vdev->vhucan->vhost_dev->backend_features = 0;
-
- vhost_dev_set_config_notifier(vdev->vhucan->vhost_dev, &can_config_ops);
-
- /* TODO: Add error handling */
- vhost_dev_init(vdev->vhucan->vhost_dev);
-
- /* Pass the new obtained features */
- global_vdev->host_features = vdev->vhucan->vhost_dev->features;
-
- ret = vhost_dev_get_config(vdev->vhucan->vhost_dev,
- (uint8_t *)&vdev->vhucan->config,
- sizeof(struct virtio_can_config));
- if (ret < 0) {
- goto vhost_dev_init_failed;
- }
-
- vdev->vdev_class->print_config((uint8_t *)&vdev->vhucan->config);
-
- return;
-
-vhost_dev_init_failed:
- DBG("vhost_dev_init_failed\n");
- return;
-}
-
-static void vhost_user_can_device_unrealize(VirtIODevice *vdev)
-{
- DBG("vhost_user_blk_device_unrealize not yet implemented\n");
- (void)vdev;
-}
-
-/* This funciton might be useful in the future
- *
- * static struct vhost_dev *vhost_user_can_get_vhost(VirtIODevice *vdev)
- * {
- * VHostUserCan *vhucan = vdev->vhucan;
- * return vhucan->vhost_dev;
- * }
- *
- */
-
-static void print_config_can(uint8_t *config_data)
-{
- struct virtio_can_config *config_strct =
- (struct virtio_can_config *)config_data;
-
- (void)config_strct;
- DBG("print_config_can:\n");
-
- DBG("\tuint16_t status: %u\n", config_strct->status);
-}
-
-static void virtio_dev_class_init(VirtIODevice *vdev)
-{
- DBG("virtio_dev_class_init\n");
-
- vdev->vdev_class = (VirtioDeviceClass *)malloc(sizeof(VirtioDeviceClass));
- vdev->vdev_class->parent = vdev;
- vdev->vdev_class->realize = vhost_user_can_realize;
- vdev->vdev_class->unrealize = vhost_user_can_device_unrealize;
- vdev->vdev_class->get_config = vhost_user_can_get_config;
- vdev->vdev_class->get_features = vhost_user_can_get_features;
- vdev->vdev_class->set_status = vhost_user_can_set_status;
- vdev->vdev_class->update_mem_table = update_mem_table;
- vdev->vdev_class->print_config = print_config_can;
-}
-
-static void vhost_user_can_init(VirtIODevice *vdev)
-{
- DBG("vhost_user_can_init\n");
-
- VHostUserCan *vhucan = (VHostUserCan *)malloc(sizeof(VHostUserCan));
- vdev->vhucan = vhucan;
- vdev->nvqs = (int *)&vdev->vhdev->nvqs;
- vhucan->parent = vdev;
- vhucan->virtqs = vdev->vqs;
- vhucan->vhost_dev = vdev->vhdev;
-
- virtio_dev_class_init(vdev);
- virtio_loopback_bus_init(vdev->vbus);
-}
diff --git a/vhost_user_console.c b/vhost_user_console.c
deleted file mode 100644
index ac453b5..0000000
--- a/vhost_user_console.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (c) 2023 Virtual Open Systems SAS.
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or
- * (at your option) any later version. See the COPYING file in the
- * top-level directory.
- *
- */
-
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <stdbool.h>
-#include <sys/param.h>
-
-/* Project header files */
-#include "vhost_user_console.h"
-
-#ifdef DEBUG
-#define DBG(...) printf("vhost-user-console: " __VA_ARGS__)
-#else
-#define DBG(...)
-#endif /* DEBUG */
-
-static const int user_feature_bits[] = {
- VIRTIO_F_VERSION_1,
- VIRTIO_RING_F_INDIRECT_DESC,
- VIRTIO_RING_F_EVENT_IDX,
- VIRTIO_F_RING_RESET,
- VIRTIO_F_NOTIFY_ON_EMPTY,
- VHOST_INVALID_FEATURE_BIT
-};
-
-static void vhost_user_console_get_config(VirtIODevice *vdev, uint8_t *config)
-{
- VHostUserConsole *console = vdev->vhuconsole;
-
- DBG("vhost_user_console_get_config: Not yet implemented!\n");
-
- memcpy(config, &console->config, sizeof(struct virtio_console_config));
-}
-
-static void vhost_user_console_start(VirtIODevice *vdev)
-{
- VHostUserConsole *vhuconsole = vdev->vhuconsole;
- VirtioBus *k = vdev->vbus;
- unsigned int i;
- int ret;
-
- DBG("vhost_user_console_start(...)\n");
-
- if (!k->set_guest_notifiers) {
- DBG("binding does not support guest notifiers\n");
- return;
- }
-
- ret = vhost_dev_enable_notifiers(vhuconsole->vhost_dev, vdev);
- if (ret < 0) {
- DBG("Error enabling host notifiers: %d\n", -ret);
- return;
- }
-
- ret = k->set_guest_notifiers(k->vdev, vhuconsole->vhost_dev->nvqs, true);
- if (ret < 0) {
- DBG("Error binding guest notifier: %d\n", -ret);
- goto err_host_notifiers;
- }
-
- vhuconsole->vhost_dev->acked_features = vdev->guest_features;
-
- ret = vhost_dev_start(vhuconsole->vhost_dev, vdev, true);
- if (ret < 0) {
- DBG("Error starting vhost: %d\n", -ret);
- goto err_guest_notifiers;
- }
-
- /*
- * guest_notifier_mask/pending not used yet, so just unmask
- * everything here. virtio-pci will do the right thing by
- * enabling/disabling irqfd.
- */
- for (i = 0; i < vhuconsole->vhost_dev->nvqs; i++) {
- vhost_virtqueue_mask(vhuconsole->vhost_dev, vdev, i, false);
- }
-
- return;
-
-err_guest_notifiers:
-err_host_notifiers:
- DBG("vhu_start error\n");
- return;
-}
-
-static void vhost_user_console_stop(VirtIODevice *vdev)
-{
- DBG("vhost_user_console_stop: not yet implemented\n");
- (void)vdev;
-}
-
-static void vhost_user_console_set_status(VirtIODevice *vdev, uint8_t status)
-{
- VHostUserConsole *vhuconsole = vdev->vhuconsole;
- bool should_start = virtio_device_started(vdev, status);
- DBG("vhost_user_console_set_status: %d\n", status);
-
- if (vhuconsole->vhost_dev->started == should_start) {
- DBG("console->vhost_dev->started == should_start\n");
- return;
- }
-
- if (should_start) {
- vhost_user_console_start(vdev);
- } else {
- vhost_user_console_stop(vdev);
- }
-}
-
-static uint64_t vhost_user_console_get_features(VirtIODevice *vdev,
- uint64_t features)
-{
- VHostUserConsole *s = vdev->vhuconsole;
-
- DBG("vhost_user_console_get_features()\n");
-
- return vhost_get_features(s->vhost_dev, user_feature_bits, features);
-}
-
-static void vhost_user_console_handle_output(VirtIODevice *vdev, VirtQueue *vq)
-{
- /*
- * Not normally called; it's the daemon that handles the queue;
- * however virtio's cleanup path console call this.
- */
- DBG("vhost_user_console_handle_output: Not yet implemented!\n");
- (void)vdev;
- (void)vq;
-}
-
-static int vhost_user_console_config_change(struct vhost_dev *dev)
-{
- VHostUserConsole *vhuconsole = dev->vdev->vhuconsole;
- DBG("vhost_user_console_console_config_change: Not yet implemented!\n");
-
- int ret = vhost_dev_get_config(dev, (uint8_t *)&vhuconsole->config,
- sizeof(struct virtio_console_config));
- if (ret < 0) {
- DBG("vhost_user_console_sound_config_change error\n");
- return -1;
- }
-
- virtio_notify_config(dev->vdev);
-
- return 0;
-}
-
-const VhostDevConfigOps console_config_ops = {
- .vhost_dev_config_notifier = vhost_user_console_config_change,
-};
-
-static void vhost_user_console_init(VirtIODevice *vdev);
-
-void vhost_user_console_realize(int queue_num, int queue_size)
-{
- VirtIODevice *vdev = global_vdev;
- int ret;
-
- DBG("vhost_user_console_device_realize\n");
- (void)queue_num;
- (void)queue_size;
-
- /* This needs to be added */
- proxy = (VirtIOMMIOProxy *)malloc(sizeof(VirtIOMMIOProxy));
- *proxy = (VirtIOMMIOProxy) {
- .legacy = 1,
- };
-
- /* VIRTIO_ID_CAN is 36, check virtio_ids.h in linux*/
- virtio_dev_init(vdev, "virtio-console", 3,
- sizeof(vdev->vhuconsole->config));
- vhost_user_console_init(global_vdev);
-
- /* add queues */
- vdev->vhuconsole->rx_vq = virtio_add_queue(vdev, 64,
- vhost_user_console_handle_output);
- vdev->vhuconsole->tx_vq = virtio_add_queue(vdev, 64,
- vhost_user_console_handle_output);
- vdev->vhuconsole->ctrl_rx_vq = virtio_add_queue(vdev, 64,
- vhost_user_console_handle_output);
- vdev->vhuconsole->ctrl_tx_vq = virtio_add_queue(vdev, 64,
- vhost_user_console_handle_output);
- vdev->vhuconsole->vhost_dev->nvqs = 4;
- vdev->vhuconsole->num_queues = 4;
- vdev->vhuconsole->queue_size = 64;
-
- /* NOTE: global_vdev->vqs == vhuconsole->virtqs */
- vdev->vqs = (VirtQueue **)malloc(sizeof(VirtQueue *)
- * global_vdev->vhuconsole->num_queues);
- vdev->vqs[0] = vdev->vhuconsole->rx_vq;
- vdev->vqs[1] = vdev->vhuconsole->tx_vq;
- vdev->vqs[2] = vdev->vhuconsole->ctrl_rx_vq;
- vdev->vqs[3] = vdev->vhuconsole->ctrl_tx_vq;
-
- vdev->vhuconsole->vhost_vqs = (struct vhost_virtqueue *)malloc(
- sizeof(struct vhost_virtqueue) *
- vdev->vhuconsole->num_queues);
-
- /* Set up vhost device */
- vdev->vhuconsole->vhost_dev->num_queues = vdev->vhuconsole->num_queues;
- vdev->vhuconsole->vhost_dev->nvqs = vdev->vhuconsole->num_queues;
- vdev->vhuconsole->vhost_dev->vqs = vdev->vhuconsole->vhost_vqs;
- vdev->vhuconsole->vhost_dev->vq_index = 0;
- vdev->vhuconsole->vhost_dev->backend_features = 0;
-
- vhost_dev_set_config_notifier(vdev->vhuconsole->vhost_dev,
- &console_config_ops);
-
- /* TODO: Add error handling */
- vhost_dev_init(vdev->vhuconsole->vhost_dev);
-
- /* Pass the new obtained features */
- global_vdev->host_features = vdev->vhuconsole->vhost_dev->features;
-
- ret = vhost_dev_get_config(vdev->vhuconsole->vhost_dev,
- (uint8_t *)&vdev->vhuconsole->config,
- sizeof(struct virtio_console_config));
- if (ret < 0) {
- goto vhost_dev_init_failed;
- }
-
- vdev->vdev_class->print_config((uint8_t *)&vdev->vhuconsole->config);
-
- return;
-
-vhost_dev_init_failed:
- DBG("vhost_dev_init_failed\n");
- return;
-}
-
-static void vhost_user_console_device_unrealize(VirtIODevice *vdev)
-{
- DBG("vhost_user_blk_device_unrealize not yet implemented\n");
- (void)vdev;
-}
-
-/*
- * This function might be useful in the future:
- *
- * static struct vhost_dev *vhost_user_console_get_vhost(VirtIODevice *vdev)
- * {
- * VHostUserConsole *vhuconsole = vdev->vhuconsole;
- * return vhuconsole->vhost_dev;
- * }
- *
- */
-
-static void print_config_console(uint8_t *config_data)
-{
- struct virtio_console_config *config_strct =
- (struct virtio_console_config *)config_data;
-
- (void)config_strct;
- DBG("print_config_console:\n");
- DBG("\tuint16_t cols: %u\n", config_strct->cols);
- DBG("\tuint16_t rows: %u\n", config_strct->rows);
- DBG("\tuint16_t max_nr_ports: %u\n", config_strct->max_nr_ports);
- DBG("\tuint16_t emerg_wr: %u\n", config_strct->emerg_wr);
-}
-
-static void virtio_dev_class_init(VirtIODevice *vdev)
-{
- DBG("virtio_dev_class_init\n");
-
- vdev->vdev_class = (VirtioDeviceClass *)malloc(sizeof(VirtioDeviceClass));
- vdev->vdev_class->parent = vdev;
- vdev->vdev_class->realize = vhost_user_console_realize;
- vdev->vdev_class->unrealize = vhost_user_console_device_unrealize;
- vdev->vdev_class->get_config = vhost_user_console_get_config;
- vdev->vdev_class->get_features = vhost_user_console_get_features;
- vdev->vdev_class->set_status = vhost_user_console_set_status;
- vdev->vdev_class->update_mem_table = update_mem_table;
- vdev->vdev_class->print_config = print_config_console;
-}
-
-static void vhost_user_console_init(VirtIODevice *vdev)
-{
-
- DBG("vhost_user_console_init\n");
-
- VHostUserConsole *vhuconsole =
- (VHostUserConsole *)malloc(sizeof(VHostUserConsole));
- vdev->vhuconsole = vhuconsole;
- vdev->nvqs = (int *)&vdev->vhdev->nvqs;
- vhuconsole->parent = vdev;
- vhuconsole->virtqs = vdev->vqs;
- vhuconsole->vhost_dev = vdev->vhdev;
-
- virtio_dev_class_init(vdev);
- virtio_loopback_bus_init(vdev->vbus);
-}
diff --git a/vhost_user_gpio.c b/vhost_user_gpio.c
deleted file mode 100644
index fd525fe..0000000
--- a/vhost_user_gpio.c
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Based on vhost-user-gpio.c of QEMU project
- *
- * Copyright (c) 2022 Viresh Kumar <viresh.kumar@linaro.org>
- *
- * Copyright (c) 2023 Virtual Open Systems SAS.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <stdbool.h>
-#include <sys/param.h>
-#include <errno.h>
-
-/* Project header files */
-#include "vhost_user_gpio.h"
-
-#ifdef DEBUG
-#define DBG(...) printf("vhost-user-gpio: " __VA_ARGS__)
-#else
-#define DBG(...)
-#endif /* DEBUG */
-
-#define REALIZE_CONNECTION_RETRIES 3
-#define VHOST_NVQS 2
-
-static const int feature_bits[] = {
- VIRTIO_F_VERSION_1,
- VIRTIO_F_NOTIFY_ON_EMPTY,
- VIRTIO_RING_F_INDIRECT_DESC,
- VIRTIO_RING_F_EVENT_IDX,
- VIRTIO_GPIO_F_IRQ,
- VIRTIO_F_RING_RESET,
- VHOST_INVALID_FEATURE_BIT
-};
-
-static void vu_gpio_get_config(VirtIODevice *vdev, uint8_t *config)
-{
- VHostUserGPIO *gpio = dev->vdev->vhugpio;
-
- DBG("vu_gpio_get_config()\n");
- (void)vdev;
- memcpy(config, &gpio->config, sizeof(gpio->config));
-}
-
-static int vu_gpio_config_notifier(struct vhost_dev *dev)
-{
- VHostUserGPIO *gpio = dev->vdev->vhugpio;
-
- DBG("vu_gpio_config_notifier\n");
-
- memcpy(dev->vdev->config, &gpio->config, sizeof(gpio->config));
- virtio_notify_config(dev->vdev);
-
- return 0;
-}
-
-const VhostDevConfigOps gpio_ops = {
- .vhost_dev_config_notifier = vu_gpio_config_notifier,
-};
-
-static int vu_gpio_start(VirtIODevice *vdev)
-{
- VirtioBus *k = vdev->vbus;
- VHostUserGPIO *gpio = vdev->vhugpio;
- unsigned int i;
- int ret;
-
- DBG("vu_gpio_start()\n");
-
- if (!k->set_guest_notifiers) {
- DBG("binding does not support guest notifiers");
- return -ENOSYS;
- }
-
- ret = vhost_dev_enable_notifiers(gpio->vhost_dev, vdev);
- if (ret < 0) {
- DBG("Error enabling host notifiers: %d", ret);
- return ret;
- }
-
- ret = k->set_guest_notifiers(k->vdev, gpio->vhost_dev->nvqs, true);
- if (ret < 0) {
- DBG("Error binding guest notifier: %d", ret);
- goto out_with_err_host_notifiers;
- }
-
- vhost_ack_features(gpio->vhost_dev, feature_bits, vdev->guest_features);
-
- ret = vhost_dev_start(gpio->vhost_dev, vdev, true);
- if (ret < 0) {
- DBG("Error starting vhost-user-gpio: %d", ret);
- goto out_with_err_guest_notifiers;
- }
- gpio->started_vu = true;
-
- for (i = 0; i < gpio->vhost_dev->nvqs; i++) {
- vhost_virtqueue_mask(gpio->vhost_dev, vdev, i, false);
- }
-
- /*
- * TODO: check if we need the following is needed
- * ret = gpio->vhost_dev->vhost_ops->vhost_set_vring_enable(gpio->vhost_dev,
- * true);
- */
-
- return 0;
-
-out_with_err_guest_notifiers:
- k->set_guest_notifiers(k->vdev, gpio->vhost_dev->nvqs, false);
-out_with_err_host_notifiers:
- /*
- * TODO: implement the following functions:
- * vhost_dev_disable_notifiers(&gpio->vhost_dev, vdev);
- */
-
- return ret;
-}
-
-static void vu_gpio_stop(VirtIODevice *vdev)
-{
- DBG("vu_gpio_stop() not yet implemented\n");
- (void)vdev;
-}
-
-static void vu_gpio_set_status(VirtIODevice *vdev, uint8_t status)
-{
- VHostUserGPIO *gpio = vdev->vhugpio;
- bool should_start = virtio_device_started(vdev, status);
-
- DBG("vu_gpio_set_status()\n");
-
- if (!gpio->connected) {
- return;
- }
-
-printf("should_start: %d\n", should_start);
- if (gpio->vhost_dev->started) {
- return;
- }
-
- if (should_start) {
- if (vu_gpio_start(vdev)) {
- DBG("vu_gpio_start() failed\n");
- }
- } else {
- vu_gpio_stop(vdev);
- }
-}
-
-static uint64_t vu_gpio_get_features(VirtIODevice *vdev, uint64_t features)
-{
- VHostUserGPIO *gpio = vdev->vhugpio;
-
- DBG("vu_gpio_get_features()\n");
- return vhost_get_features(gpio->vhost_dev, feature_bits, features);
-}
-
-static void vu_gpio_handle_output(VirtIODevice *vdev, VirtQueue *vq)
-{
- /*
- * Not normally called; it's the daemon that handles the queue;
- * however virtio's cleanup path can call this.
- */
- DBG("vu_gpio_handle_output not yet implemented\n");
- (void)vdev;
- (void)vq;
-}
-
-static void vu_gpio_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
-{
- VHostUserGPIO *gpio = vdev->vhugpio;
-
- DBG("vu_gpio_guest_notifier_mask() not yet implemented\n");
-
- vhost_virtqueue_mask(gpio->vhost_dev, vdev, idx, mask);
-}
-
-static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserGPIO *gpio)
-{
- DBG("do_vhost_user_cleanup() not yet implemented\n");
- (void)vdev;
- (void)gpio;
-}
-
-static int vu_gpio_connect(VirtIODevice *vdev)
-{
- VHostUserGPIO *gpio = vdev->vhugpio;
-
- DBG("vu_gpio_connect()\n");
-
- if (gpio->connected) {
- return 0;
- }
- gpio->connected = true;
-
- vhost_dev_set_config_notifier(gpio->vhost_dev, &gpio_ops);
- /*
- * TODO: Investigate if the following is needed
- * gpio->vhost_user.supports_config = true;
- */
-
- gpio->vhost_dev->nvqs = VHOST_NVQS;
- gpio->vhost_dev->vqs = gpio->vhost_vqs;
-
- vhost_dev_init(gpio->vhost_dev);
- /*
- * TODO: Add error handling
- * if (ret < 0) {
- * return ret;
- * }
- */
-
- /* restore vhost state */
- if (virtio_device_started(vdev, vdev->status)) {
- vu_gpio_start(vdev);
- }
-
- return 0;
-}
-
-static int vu_gpio_realize_connect(VHostUserGPIO *gpio)
-{
- int ret;
-
- DBG("vu_gpio_realize_connect()\n");
-
- ret = vu_gpio_connect(gpio->parent);
- if (ret < 0) {
- return ret;
- }
-
- ret = vhost_dev_get_config(gpio->vhost_dev, (uint8_t *)&gpio->config,
- sizeof(gpio->config));
-
- if (ret < 0) {
- DBG("vhost-user-gpio: get config failed\n");
- /*
- * TODO: Add cleanup function
- * vhost_dev_cleanup(vhost_dev);
- */
- return ret;
- }
-
- return 0;
-}
-
-static void vu_gpio_device_unrealize(VirtIODevice *vdev)
-{
- DBG("vu_gpio_device_unrealize() not yet implemented\n");
- (void)vdev;
-}
-
-static void print_config_gpio(uint8_t *config_data)
-{
- struct virtio_gpio_config *config =
- (struct virtio_gpio_config *)config_data;
-
- (void)config;
- DBG("ngpio: %hu\n", config->ngpio);
- DBG("gpio_names_size: %u\n", config->gpio_names_size);
-}
-
-static void vu_gpio_class_init(VirtIODevice *vdev)
-{
- DBG("vu_gpio_class_init()\n");
-
- vdev->vdev_class = (VirtioDeviceClass *)malloc(sizeof(VirtioDeviceClass));
- if (!vdev->vdev_class) {
- DBG("vdev_class memory allocation failed\n");
- return;
- }
- vdev->vdev_class->realize = vu_gpio_device_realize;
- vdev->vdev_class->unrealize = vu_gpio_device_unrealize;
- vdev->vdev_class->get_features = vu_gpio_get_features;
- vdev->vdev_class->get_config = vu_gpio_get_config;
- vdev->vdev_class->set_status = vu_gpio_set_status;
- vdev->vdev_class->guest_notifier_mask = vu_gpio_guest_notifier_mask;
-}
-
-void vu_gpio_init(VirtIODevice *vdev)
-{
- DBG("vu_gpio_init()\n");
-
- VHostUserGPIO *vhugpio = (VHostUserGPIO *)malloc(sizeof(VHostUserGPIO));
- if (!proxy) {
- DBG("proxy memory allocation failed\n");
- goto out;
- }
-
- vdev->vhugpio = vhugpio;
- vdev->nvqs = (int *)&dev->nvqs;
- vhugpio->parent = vdev;
- vhugpio->vhost_dev = dev;
-
- vu_gpio_class_init(vdev);
- virtio_loopback_bus_init(vdev->vbus);
-
-out:
- return;
-}
-
-/* TODO: Add queue_num, queue_size as parameters */
-void vu_gpio_device_realize(int queue_num, int queue_size)
-{
- int retries, ret;
-
- DBG("vu_gpio_device_realize()\n");
- (void)queue_num;
- (void)queue_size;
-
- /* This needs to be added */
- proxy = (VirtIOMMIOProxy *)malloc(sizeof(VirtIOMMIOProxy));
- if (!proxy) {
- DBG("proxy memory allocation failed\n");
- goto out_with_error;
- }
-
- *proxy = (VirtIOMMIOProxy) {
- .legacy = 1,
- };
-
- /* VIRTIO_ID_GPIO is 41, check virtio_ids.h in linux */
- virtio_dev_init(global_vdev, "virtio-gpio", 41,
- sizeof(struct virtio_gpio_config));
-
- vu_gpio_init(global_vdev);
- if (!global_vdev->vhugpio) {
- DBG("vhugpio memory allocation failed\n");
- goto out_with_proxy;
- }
-
- global_vdev->vhugpio->command_vq = virtio_add_queue(global_vdev, 64,
- vu_gpio_handle_output);
- global_vdev->vhugpio->interrupt_vq = virtio_add_queue(global_vdev, 64,
- vu_gpio_handle_output);
-
- global_vdev->vhugpio->vhost_vqs = (struct vhost_virtqueue *)
- malloc(sizeof(struct vhost_virtqueue *));
- if (!global_vdev->vhugpio->vhost_vqs) {
- DBG("vhost_vqs memory allocation failed\n");
- goto out_with_dev;
- }
-
- global_vdev->vhugpio->connected = false;
-
- retries = REALIZE_CONNECTION_RETRIES;
-
- do {
- ret = vu_gpio_realize_connect(global_vdev->vhugpio);
- } while (ret < 0 && retries--);
-
- if (ret < 0) {
- DBG("vu_gpio_realize_connect(): -EPROTO\n");
- do_vhost_user_cleanup(global_vdev, global_vdev->vhugpio);
- }
-
- print_config_gpio((uint8_t *)(&global_vdev->vhugpio->config));
- DBG("(realize completed)\n");
-
- return;
-
- /*
- * TODO: Fix the following considering also do_vhost_user_cleanup()
- *
- * out_with_cmd_vq:
- * free(global_vdev->vhugpio->command_vq);
- */
-out_with_dev:
- free(global_vdev->vhugpio);
-out_with_proxy:
- free(proxy);
-out_with_error:
- DBG("Realize funciton return error\n");
- return;
-}
diff --git a/vhost_user_input.c b/vhost_user_input.c
deleted file mode 100644
index 5cb4ca6..0000000
--- a/vhost_user_input.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Based on vhost-user-input.c of QEMU project
- *
- * Copyright (c) 2022-2023 Virtual Open Systems SAS.
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or
- * (at your option) any later version. See the COPYING file in the
- * top-level directory.
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <stdbool.h>
-#include <sys/param.h>
-
-/* Project header files */
-#include "vhost_user_input.h"
-
-#ifdef DEBUG
-#define DBG(...) printf("vhost-user-input: " __VA_ARGS__)
-#else
-#define DBG(...)
-#endif /* DEBUG */
-
-
-static int vhost_input_config_change(struct vhost_dev *dev)
-{
- DBG("vhost-user-input: unhandled backend config change\n");
- (void)dev;
-
- return -1;
-}
-
-const VhostDevConfigOps config_ops = {
- .vhost_dev_config_notifier = vhost_input_config_change,
-};
-
-static void vhost_input_change_active(VirtIOInput *vinput)
-{
- DBG("vhost_input_change_active(...)\n");
-
- if (vinput->active) {
- vhost_user_backend_start(global_vdev);
- } else {
- vhost_user_backend_stop(global_vdev);
- }
-}
-
-static void vhost_input_get_config(VirtIODevice *vdev, uint8_t *config_data)
-{
- DBG("vhost_input_get_config(...)\n");
-
- VirtIOInput *vinput = vdev->vinput;
- VhostUserInput *vhi = vdev->vhuinput;
- int ret;
-
- memset(config_data, 0, vinput->cfg_size);
-
- ret = vhost_dev_get_config(vhi->vhost_dev, config_data, vinput->cfg_size);
- if (ret) {
- DBG("vhost_input_get_config failed\n");
- return;
- }
-}
-
-static void vhost_input_set_config(VirtIODevice *vdev,
- const uint8_t *config_data)
-{
- DBG("vhost_input_set_config(...)\n");
-
- VhostUserInput *vhi = vdev->vhuinput;
- int ret;
-
- ret = vhost_dev_set_config(vhi->vhost_dev, config_data,
- 0, sizeof(virtio_input_config),
- VHOST_SET_CONFIG_TYPE_MASTER);
- if (ret < 0) {
- DBG("vhost_input_set_config failed\n");
- return;
- }
-
- virtio_notify_config(vdev);
-}
-
-static struct vhost_dev *vhost_input_get_vhost(VirtIODevice *vdev)
-{
- DBG("vhost_input_get_vhost(...)\n");
-
- return vdev->vhuinput->vhost_dev;
-}
-
-static void print_config_input(uint8_t *config_data)
-{
- struct virtio_input_config *config_strct =
- (struct virtio_input_config *)config_data;
-
- DBG("print_config_input: Not yet implemented\n");
- (void)config_strct;
-}
-
-static void vhost_input_class_init(VirtIODevice *vdev)
-{
- DBG("vhost_input_class_init(...)\n");
-
-
- /* Comment out the following lines to get the local config */
- vdev->vdev_class->get_config = vhost_input_get_config;
- vdev->vdev_class->set_config = vhost_input_set_config;
- vdev->vdev_class->get_vhost = vhost_input_get_vhost;
- vdev->vhuinput->vdev_input->input_class->realize = vhost_user_input_realize;
- vdev->vhuinput->vdev_input->input_class->change_active =
- vhost_input_change_active;
- vdev->vdev_class->update_mem_table = update_mem_table;
- vdev->vdev_class->print_config = print_config_input;
-}
-
-
-void vhost_user_input_init(VirtIODevice *vdev)
-{
-
- DBG("vhost_user_input_init(...)\n");
-
- struct VirtIOInputClass *input_class = (struct VirtIOInputClass *)malloc(
- sizeof(struct VirtIOInputClass));
- VirtIOInput *vinput = (VirtIOInput *)malloc(sizeof(VirtIOInput));
- VhostUserInput *vhuinput = (VhostUserInput *)malloc(sizeof(VhostUserInput));
-
- vdev->vinput = vinput;
- vdev->vinput->input_class = input_class;
-
- vdev->vhuinput = vhuinput;
- vdev->nvqs = (int*)&dev->nvqs;
- vhuinput->vdev = vdev;
- vhuinput->vhost_dev = dev;
- vhuinput->vdev_input = vinput;
-
- /*
- * Call first the virtio_input class init to set up
- * the basic functionality.
- */
- virtio_input_class_init(vdev);
-
- /* Then call the vhost_user class init */
- vhost_input_class_init(vdev);
-
- /* finally initialize the bus */
- virtio_loopback_bus_init(vdev->vbus);
-}
-
-
-void vhost_user_input_realize(int queue_num, int queue_size)
-{
- int nvqs = 2; /* qemu choice: 2 */
-
- DBG("vhost_user_input_realize()\n");
- (void)queue_num;
- (void)queue_size;
-
- vhost_dev_set_config_notifier(global_vdev->vhuinput->vhost_dev,
- &config_ops);
-
- global_vdev->vhuinput->vdev_input->cfg_size =
- sizeof_field(virtio_input_config, u);
-
- global_vdev->vhuinput->vhost_dev->vq_index = 0;
- global_vdev->vhuinput->vhost_dev->backend_features = 0;
- global_vdev->vhuinput->vhost_dev->num_queues = nvqs;
-
-
- global_vdev->vq = (struct VirtQueue *)malloc(
- sizeof(struct VirtQueue) * nvqs);
-
- global_vdev->vhuinput->vhost_dev->nvqs = nvqs;
- global_vdev->vhuinput->vhost_dev->vqs = (struct vhost_virtqueue *)malloc(
- sizeof(struct vhost_virtqueue) * nvqs);
- vhost_dev_init(global_vdev->vhuinput->vhost_dev);
-
- /* Pass the new obtained features */
- global_vdev->host_features = global_vdev->vhuinput->vhost_dev->features;
-}
-
-void vhost_user_backend_start(VirtIODevice *vdev)
-{
- VirtioBus *k = vdev->vbus;
- unsigned int i;
- int ret;
-
- DBG("vhost_user_backend_start(...)\n");
-
- if (vdev->started) {
- DBG("Device has already been started!\n");
- return;
- }
-
- if (!k->set_guest_notifiers) {
- DBG("binding does not support guest notifiers\n");
- return;
- }
-
- ret = vhost_dev_enable_notifiers(vdev->vhuinput->vhost_dev, vdev);
- if (ret < 0) {
- DBG("vhost_dev_enable_notifiers failed!\n");
- return;
- }
-
- DBG("k->set_guest_notifiers, nvqs: %d\n", vdev->vhuinput->vhost_dev->nvqs);
- ret = k->set_guest_notifiers(vdev, vdev->vhuinput->vhost_dev->nvqs, true);
- if (ret < 0) {
- DBG("Error binding guest notifier\n");
- }
-
- vdev->vhuinput->vhost_dev->acked_features = vdev->guest_features;
- ret = vhost_dev_start(vdev->vhuinput->vhost_dev, vdev, false);
- if (ret < 0) {
- DBG("Error start vhost dev\n");
- return;
- }
-
- /*
- * guest_notifier_mask/pending not used yet, so just unmask
- * everything here. virtio-pci will do the right thing by
- * enabling/disabling irqfd.
- */
- for (i = 0; i < vdev->vhuinput->vhost_dev->nvqs; i++) {
- vhost_virtqueue_mask(vdev->vhuinput->vhost_dev, vdev,
- vdev->vhuinput->vhost_dev->vq_index + i, false);
- }
-
- vdev->started = true;
- return;
-
-}
-
-void vhost_user_backend_stop(VirtIODevice *vdev)
-{
- DBG("vhost_user_backend_stop() not yet implemented\n");
- (void)vdev;
-}
diff --git a/vhost_user_input.h b/vhost_user_input.h
deleted file mode 100644
index 23f4ddd..0000000
--- a/vhost_user_input.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Based on virtio-input.h of QEMU project
- *
- * Copyright (c) 2022-2023 Virtual Open Systems SAS.
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or
- * (at your option) any later version. See the COPYING file in the
- * top-level directory.
- */
-
-#ifndef VHOST_USER_INPUT
-#define VHOST_USER_INPUT
-
-#include "vhost_loopback.h"
-#include "vhost_user_loopback.h"
-#include "virtio_loopback.h"
-#include <linux/virtio_input.h>
-#include "queue.h"
-#include <sys/mman.h>
-
-/* ----------------------------------------------------------------- */
-/* virtio input protocol */
-
-typedef struct virtio_input_absinfo virtio_input_absinfo;
-typedef struct virtio_input_config virtio_input_config;
-typedef struct virtio_input_event virtio_input_event;
-
-/* ----------------------------------------------------------------- */
-/* qemu internals */
-
-#define TYPE_VIRTIO_INPUT "virtio-input-device"
-#define TYPE_VIRTIO_INPUT_HID "virtio-input-hid-device"
-#define TYPE_VIRTIO_KEYBOARD "virtio-keyboard-device"
-#define TYPE_VIRTIO_MOUSE "virtio-mouse-device"
-#define TYPE_VIRTIO_TABLET "virtio-tablet-device"
-
-#define TYPE_VIRTIO_INPUT_HOST "virtio-input-host-device"
-
-#define TYPE_VHOST_USER_INPUT "vhost-user-input"
-
-typedef struct VirtIOInputConfig {
- virtio_input_config config;
- QTAILQ_ENTRY(VirtIOInputConfig) node;
-} VirtIOInputConfig;
-
-struct VirtIOInputClass;
-
-typedef struct VirtIOInput {
- VirtIODevice *parent_dev;
- struct VirtIOInputClass *input_class;
- uint8_t cfg_select;
- uint8_t cfg_subsel;
- uint32_t cfg_size;
- QTAILQ_HEAD(, VirtIOInputConfig) cfg_list;
- VirtQueue *evt, *sts;
- char *serial;
- struct {
- virtio_input_event event;
- VirtQueueElement *elem;
- } *queue;
- uint32_t qindex, qsize;
- bool active;
-
-} VirtIOInput;
-
-typedef struct VirtIOInputClass {
- VirtioDeviceClass *parent_class;
- void (*realize)();
- void (*unrealize)(VirtIODevice *dev);
- void (*change_active)(VirtIOInput *vinput);
- void (*handle_status)(VirtIOInput *vinput, virtio_input_event *event);
-} VirtIOInputClass;
-
-struct VirtIOInputHID {
- VirtIOInput parent_obj;
- char *display;
- uint32_t head;
- int ledstate;
- bool wheel_axis;
-};
-
-struct VirtIOInputHost {
- VirtIOInput parent_obj;
- char *evdev;
- int fd;
-};
-
-typedef struct VhostUserInput {
- VirtIOInput *vdev_input;
- struct vhost_dev *vhost_dev;
- VirtIODevice *vdev;
- bool started;
- bool completed;
-} VhostUserInput;
-
-#define VIRTIO_ID_NAME_KEYBOARD "QEMU Virtio Keyboard"
-#define BUS_VIRTUAL 0x06
-
-
-/*
- * Event types
- */
-
-#define EV_SYN 0x00
-#define EV_KEY 0x01
-#define EV_REL 0x02
-#define EV_ABS 0x03
-#define EV_MSC 0x04
-#define EV_SW 0x05
-#define EV_LED 0x11
-#define EV_SND 0x12
-#define EV_REP 0x14
-#define EV_FF 0x15
-#define EV_PWR 0x16
-#define EV_FF_STATUS 0x17
-#define EV_MAX 0x1f
-#define EV_CNT (EV_MAX + 1)
-
-/*
- * LEDs
- */
-
-#define LED_NUML 0x00
-#define LED_CAPSL 0x01
-#define LED_SCROLLL 0x02
-#define LED_COMPOSE 0x03
-#define LED_KANA 0x04
-#define LED_SLEEP 0x05
-#define LED_SUSPEND 0x06
-#define LED_MUTE 0x07
-#define LED_MISC 0x08
-#define LED_MAIL 0x09
-#define LED_CHARGING 0x0a
-#define LED_MAX 0x0f
-#define LED_CNT (LED_MAX + 1)
-
-/*
- * Keys and buttons
- *
- * Most of the keys/buttons are modeled after USB HUT 1.12
- * (see http://www.usb.org/developers/hidpage).
- * Abbreviations in the comments:
- * AC - Application Control
- * AL - Application Launch Button
- * SC - System Control
- */
-#define KEY_G 34
-
-void vhost_user_backend_start(VirtIODevice *vdev);
-void vhost_user_backend_stop(VirtIODevice *vdev);
-void virtio_input_init_config(VirtIOInput *vinput,
- virtio_input_config *config);
-void virtio_input_class_init(VirtIODevice *vdev);
-void virtio_input_device_realize(int queue_num, int queue_size);
-void vhost_user_input_init(VirtIODevice *vdev);
-void vhost_user_input_realize();
-
-#endif /* VHOST_USER_INPUT */
diff --git a/vhost_user_rng.c b/vhost_user_rng.c
deleted file mode 100644
index 96eb13e..0000000
--- a/vhost_user_rng.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Based on vhost-user-rng of QEMU project
- *
- * Copyright (c) 2021 Mathieu Poirier <mathieu.poirier@linaro.org>
- *
- * Copyright (c) 2022-2023 Virtual Open Systems SAS.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <stdbool.h>
-#include <sys/param.h>
-
-/* Project header files */
-#include "vhost_loopback.h"
-#include "vhost_user_rng.h"
-
-#ifdef DEBUG
-#define DBG(...) printf("vhost-user-rng: " __VA_ARGS__)
-#else
-#define DBG(...)
-#endif /* DEBUG */
-
-static void vu_rng_start(VirtIODevice *vdev)
-{
- VHostUserRNG *rng = vdev->vhrng;
- VirtioBus *k = vdev->vbus;
- int ret;
- int i;
-
- /* TODO: This might be deleted in future */
- if (!k->set_guest_notifiers) {
- DBG("binding does not support guest notifiers\n");
- return;
- }
-
- ret = vhost_dev_enable_notifiers(rng->vhost_dev, vdev);
- if (ret < 0) {
- DBG("Error enabling host notifiers: %d\n", ret);
- return;
- }
-
- ret = k->set_guest_notifiers(vdev, rng->vhost_dev->nvqs, true);
- if (ret < 0) {
- DBG("Error binding guest notifier: %d\n", ret);
- return;
- }
-
- rng->vhost_dev->acked_features = vdev->guest_features;
- DBG("rng->vhost_dev->acked_features: 0x%lx\n", vdev->guest_features);
-
- ret = vhost_dev_start(rng->vhost_dev, vdev, true);
- if (ret < 0) {
- DBG("Error starting vhost-user-rng: %d\n", ret);
- return;
- }
-
- /*
- * guest_notifier_mask/pending not used yet, so just unmask
- * everything here. virtio-pci will do the right thing by
- * enabling/disabling irqfd.
- */
- for (i = 0; i < (int)rng->vhost_dev->nvqs; i++) {
- vhost_virtqueue_mask(rng->vhost_dev, vdev, i, false);
- }
-}
-
-/* To be used in future release
- *
- * static void vu_rng_stop(VirtIODevice *vdev)
- * {
- * DBG("vu_rng_stop is not yet implemented\n");
- * (void)vdev;
- * }
- *
- */
-
-static uint64_t vu_rng_get_features(VirtIODevice *vdev,
- uint64_t requested_features)
-{
- DBG("vu_rng_get_features is not yet implemented\n");
- (void)vdev;
-
- /* No feature bits used yet */
- return requested_features;
-}
-
-/* TODO: We need to implement this function in a future release */
-static void vu_rng_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
-{
- VHostUserRNG *rng = vdev->vhrng;
-
- DBG("vu_rng_guest_notifier_mask is not yet implemented\n");
- (void)vdev;
- (void)idx;
- (void)mask;
- (void)rng;
-
- /* ADD: vhost_virtqueue_mask(&rng->vhost_dev, vdev, idx, mask); */
-}
-
-/* TODO: We need to implement this function in a future release */
-static bool vu_rng_guest_notifier_pending(VirtIODevice *vdev, int idx)
-{
- VHostUserRNG *rng = vdev->vhrng;
-
- DBG("vu_rng_guest_notifier_pending is not yet implemented\n");
- (void)vdev;
- (void)idx;
- (void)rng;
-
- /* ADD: return vhost_virtqueue_pending(&rng->vhost_dev, idx); */
- return 1;
-}
-
-static void vu_rng_set_status(VirtIODevice *vdev, uint8_t status)
-{
- VHostUserRNG *rng = vdev->vhrng;
- bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK;
-
- if (rng->vhost_dev->started == should_start) {
- DBG("rng->vhost_dev->started != should_start\n");
- return;
- }
-
- if (should_start) {
- vu_rng_start(vdev);
- } else {
- DBG("vu_rng_stop(vdev)\n");
- /* TODO: Add vu_rng_stop(vdev); when this function is implemented */
- }
-}
-
-static void virtio_dev_class_init(VirtIODevice *vdev)
-{
- vdev->vdev_class = (VirtioDeviceClass *)malloc(sizeof(VirtioDeviceClass));
- vdev->vdev_class->parent = vdev;
- vdev->vdev_class->set_status = vu_rng_set_status;
- vdev->vdev_class->get_features = vu_rng_get_features;
- vdev->vdev_class->guest_notifier_mask = vu_rng_guest_notifier_mask;
- vdev->vdev_class->guest_notifier_pending = vu_rng_guest_notifier_pending;
- vdev->vdev_class->update_mem_table = update_mem_table;
-}
-
-
-void vhost_user_rng_init(VirtIODevice *vdev)
-{
- VHostUserRNG *vhrng = (VHostUserRNG *)malloc(sizeof(VHostUserRNG));
- vdev->vhrng = vhrng;
- vdev->nvqs = (int *)&dev->nvqs;
- vhrng->parent = vdev;
- vhrng->req_vq = vdev->vq;
- vhrng->vhost_dev = dev;
-
- virtio_dev_class_init(vdev);
- virtio_loopback_bus_init(vdev->vbus);
-}
-
-static void vu_rng_handle_output(VirtIODevice *vdev, VirtQueue *vq)
-{
- (void)vdev;
- (void)vq;
- /*
- * Not normally called; it's the daemon that handles the queue;
- * however virtio's cleanup path can call this.
- */
- DBG("vu_rng_handle_output\n");
-}
-
-
-void vhost_user_rng_realize(int queue_num, int queue_size)
-{
- (void)queue_num;
- (void)queue_size;
-
- /* Initiliaze virtio_dev data structures */
- virtio_dev_init(global_vdev, "virtio-rng", 4, 0);
-
- /* This needs to be change to vhost-user-rng init */
- vhost_user_rng_init(global_vdev);
-
- global_vdev->vq = virtio_add_queue(global_vdev, 4, vu_rng_handle_output);
-
- global_vdev->host_features = 0x39000000;
-
- proxy = (VirtIOMMIOProxy *)malloc(sizeof(VirtIOMMIOProxy));
- *proxy = (VirtIOMMIOProxy) {
- .legacy = 1,
- };
-
- /* Virtqueues conf */
- dev->nvqs = 1;
- dev->vqs = (struct vhost_virtqueue *)malloc(dev->nvqs *
- sizeof(struct vhost_virtqueue));
-
- /* Initiale vhost-user communication */
- vhost_dev_init(dev);
-
- /* Write the final features */
- global_vdev->host_features = dev->features;
- DBG("dev->host_features: 0x%lx\n", dev->features);
-}
diff --git a/vhost_user_sound.c b/vhost_user_sound.c
deleted file mode 100644
index d9f6a98..0000000
--- a/vhost_user_sound.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Based on vhost-user-sound.c of QEMU project
- *
- * Copyright 2020 Red Hat, Inc.
- *
- * Copyright (c) 2023 Virtual Open Systems SAS.
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or
- * (at your option) any later version. See the COPYING file in the
- * top-level directory.
- *
- */
-
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <stdbool.h>
-#include <sys/param.h>
-
-/* Project header files */
-#include "vhost_user_sound.h"
-
-#ifdef DEBUG
-#define DBG(...) printf("vhost-user-sound: " __VA_ARGS__)
-#else
-#define DBG(...)
-#endif /* DEBUG */
-
-/***************************** vhost-user-sound ******************************/
-
-/*
- * Features supported by the vhost-user-sound frontend:
- * VIRTIO_F_VERSION_1,
- * VIRTIO_RING_F_INDIRECT_DESC,
- * VIRTIO_RING_F_EVENT_IDX,
- * VIRTIO_F_RING_RESET,
- * VIRTIO_F_NOTIFY_ON_EMPTY,
- * VHOST_INVALID_FEATURE_BIT
- */
-static const int user_feature_bits[] = {
- VIRTIO_F_VERSION_1,
- VIRTIO_RING_F_INDIRECT_DESC,
- VIRTIO_RING_F_EVENT_IDX,
- VIRTIO_F_RING_RESET,
- VIRTIO_F_NOTIFY_ON_EMPTY,
- VHOST_INVALID_FEATURE_BIT
-};
-
-static void vus_get_config(VirtIODevice *vdev, uint8_t *config)
-{
- VHostUserSound *snd = vdev->vhusnd;
-
- memcpy(config, &snd->config, sizeof(struct virtio_snd_config));
-}
-
-
-static void vus_start(VirtIODevice *vdev)
-{
- VHostUserSound *vhusnd = vdev->vhusnd;
- VirtioBus *k = vdev->vbus;
- int ret;
- unsigned int i;
-
- DBG("vus_start(...)\n");
-
- if (!k->set_guest_notifiers) {
- DBG("binding does not support guest notifiers\n");
- return;
- }
-
- ret = vhost_dev_enable_notifiers(vhusnd->vhost_dev, vdev);
- if (ret < 0) {
- DBG("Error enabling host notifiers: %d\n", -ret);
- return;
- }
-
- ret = k->set_guest_notifiers(k->vdev, vhusnd->vhost_dev->nvqs, true);
- if (ret < 0) {
- DBG("Error binding guest notifier: %d\n", -ret);
- goto err_host_notifiers;
- }
-
- vhusnd->vhost_dev->acked_features = vdev->guest_features;
-
- ret = vhost_dev_start(vhusnd->vhost_dev, vdev, true);
- if (ret < 0) {
- DBG("Error starting vhost: %d\n", -ret);
- goto err_guest_notifiers;
- }
-
- /*
- * guest_notifier_mask/pending not used yet, so just unmask
- * everything here. virtio-pci will do the right thing by
- * enabling/disabling irqfd.
- */
- for (i = 0; i < vhusnd->vhost_dev->nvqs; i++) {
- vhost_virtqueue_mask(vhusnd->vhost_dev, vdev, i, false);
- }
-
- return;
-
-err_guest_notifiers:
-err_host_notifiers:
- DBG("vhu_start error\n");
- return;
-}
-
-static void vus_stop(VirtIODevice *vdev)
-{
- DBG("vus_stop: not yet implemented\n");
- (void)vdev;
-}
-
-static void vus_set_status(VirtIODevice *vdev, uint8_t status)
-{
- VHostUserSound *vhusnd = vdev->vhusnd;
- bool should_start = virtio_device_started(vdev, status);
- DBG("vus_set_status\n");
-
- if (vhusnd->vhost_dev->started == should_start) {
- DBG("snd->vhost_dev->started == should_start\n");
- return;
- }
-
- if (should_start) {
- vus_start(vdev);
- } else {
- vus_stop(vdev);
- }
-}
-
-static uint64_t vus_get_features(VirtIODevice *vdev, uint64_t features)
-{
- VHostUserSound *s = vdev->vhusnd;
-
- DBG("vus_get_features()\n");
-
- return vhost_get_features(s->vhost_dev, user_feature_bits, features);
-}
-
-static void vus_snd_handle_output(VirtIODevice *vdev, VirtQueue *vq)
-{
- /*
- * Not normally called; it's the daemon that handles the queue;
- * however virtio's cleanup path can call this.
- */
- (void)vdev;
- (void)vq;
-}
-
-/*
- * TODO: Add it later
- * static void vhost_sound_guest_notifier_mask(VirtIODevice *vdev, int idx,
- * bool mask)
- */
-
-/*
- * TODO: Add it later
- * static bool vhost_sound_guest_notifier_pending(VirtIODevice *vdev,
- * int idx)
- */
-
-static int vus_sound_config_change(struct vhost_dev *dev)
-{
- VHostUserSound *vhusnd = dev->vdev->vhusnd;
- DBG("vus_sound_config_change\n");
-
- int ret = vhost_dev_get_config(dev, (uint8_t *)&vhusnd->config,
- sizeof(struct virtio_snd_config));
- if (ret < 0) {
- DBG("vus_sound_config_change error\n");
- return -1;
- }
-
- virtio_notify_config(dev->vdev);
-
- return 0;
-}
-
-const VhostDevConfigOps snd_config_ops = {
- .vhost_dev_config_notifier = vus_sound_config_change,
-};
-
-static void vhost_user_snd_init(VirtIODevice *vdev);
-
-void vus_device_realize(int queue_num, int queue_size)
-{
- VirtIODevice *vdev = global_vdev;
- int ret;
-
- DBG("vus_device_realize\n");
- (void)queue_num;
- (void)queue_size;
-
- /* This needs to be added */
- proxy = (VirtIOMMIOProxy *)malloc(sizeof(VirtIOMMIOProxy));
- *proxy = (VirtIOMMIOProxy) {
- .legacy = 1,
- };
-
- /* VIRTIO_ID_SOUND is 25, check virtio_ids.h in linux*/
- virtio_dev_init(vdev, "virtio-sound", 25, sizeof(vdev->vhusnd->config));
- vhost_user_snd_init(global_vdev);
-
- /* add queues */
- vdev->vhusnd->ctrl_vq = virtio_add_queue(vdev, 64, vus_snd_handle_output);
- vdev->vhusnd->event_vq = virtio_add_queue(vdev, 64, vus_snd_handle_output);
- vdev->vhusnd->tx_vq = virtio_add_queue(vdev, 64, vus_snd_handle_output);
- vdev->vhusnd->rx_vq = virtio_add_queue(vdev, 64, vus_snd_handle_output);
- vdev->vhusnd->vhost_dev->nvqs = 4;
- vdev->vhusnd->num_queues = 4;
- vdev->vhusnd->queue_size = 64;
-
- /* NOTE: global_vdev->vqs == vhublk->virtqs */
- vdev->vqs = (VirtQueue **)malloc(sizeof(VirtQueue *)
- * global_vdev->vhusnd->num_queues);
- vdev->vqs[0] = vdev->vhusnd->ctrl_vq;
- vdev->vqs[1] = vdev->vhusnd->event_vq;
- vdev->vqs[2] = vdev->vhusnd->tx_vq;
- vdev->vqs[3] = vdev->vhusnd->rx_vq;
-
- vdev->vhusnd->vhost_vqs = (struct vhost_virtqueue *)malloc(
- sizeof(struct vhost_virtqueue) *
- vdev->vhusnd->num_queues);
-
- /* Set up vhost device */
- vdev->vhusnd->vhost_dev->num_queues = vdev->vhusnd->num_queues;
- vdev->vhusnd->vhost_dev->nvqs = vdev->vhusnd->num_queues;
- vdev->vhusnd->vhost_dev->vqs = vdev->vhusnd->vhost_vqs;
- vdev->vhusnd->vhost_dev->vq_index = 0;
- vdev->vhusnd->vhost_dev->backend_features = 0;
-
- vhost_dev_set_config_notifier(vdev->vhusnd->vhost_dev, &snd_config_ops);
-
- /* TODO: Add error handling */
- vhost_dev_init(vdev->vhusnd->vhost_dev);
-
- /* Pass the new obtained features */
- global_vdev->host_features = vdev->vhusnd->vhost_dev->features;
-
- ret = vhost_dev_get_config(vdev->vhusnd->vhost_dev,
- (uint8_t *)&vdev->vhusnd->config,
- sizeof(struct virtio_snd_config));
- if (ret < 0) {
- goto vhost_dev_init_failed;
- }
-
- vdev->vdev_class->print_config((uint8_t *)&vdev->vhusnd->config);
-
- return;
-
-vhost_dev_init_failed:
- DBG("vhost_dev_init_failed\n");
- return;
-}
-
-static void vus_device_unrealize(VirtIODevice *vdev)
-{
- DBG("vhost_user_blk_device_unrealize not yet implemented\n");
- (void)vdev;
-}
-
-/*
- * This will be might be useful in the future
- *
- * static struct vhost_dev *vus_get_vhost(VirtIODevice *vdev)
- * {
- * VHostUserSound *vhusnd = vdev->vhusnd;
- * return vhusnd->vhost_dev;
- * }
- *
- */
-
-static void print_config_snd(uint8_t *config_data)
-{
- struct virtio_snd_config *config_strct =
- (struct virtio_snd_config *)config_data;
-
- (void)config_strct;
-
- DBG("print_config_snd:\n");
- /* # of available physical jacks */
- DBG("\tuint32_t jacks: %u\n", config_strct->jacks);
- /* # of available PCM streams */
- DBG("\tuint32_t streams: %u\n", config_strct->streams);
- /* # of available channel maps */
- DBG("\tuint32_t chmaps: %u\n", config_strct->chmaps);
-}
-
-static void virtio_dev_class_init(VirtIODevice *vdev)
-{
- DBG("virtio_dev_class_init\n");
-
- vdev->vdev_class = (VirtioDeviceClass *)malloc(sizeof(VirtioDeviceClass));
- vdev->vdev_class->parent = vdev;
- vdev->vdev_class->realize = vus_device_realize;
- vdev->vdev_class->unrealize = vus_device_unrealize;
- vdev->vdev_class->get_config = vus_get_config;
- vdev->vdev_class->get_features = vus_get_features;
- vdev->vdev_class->set_status = vus_set_status;
- vdev->vdev_class->update_mem_table = update_mem_table;
- vdev->vdev_class->print_config = print_config_snd;
-}
-
-static void vhost_user_snd_init(VirtIODevice *vdev)
-{
-
- DBG("vhost_user_blk_init\n");
-
- VHostUserSound *vhusnd = (VHostUserSound *)malloc(sizeof(VHostUserSound));
- vdev->vhusnd = vhusnd;
- vdev->nvqs = (int *)&vdev->vhdev->nvqs;
- vhusnd->parent = vdev;
- vhusnd->virtqs = vdev->vqs;
- vhusnd->vhost_dev = vdev->vhdev;
-
- virtio_dev_class_init(vdev);
- virtio_loopback_bus_init(vdev->vbus);
-}
diff --git a/virtio_blk.h b/virtio_blk.h
deleted file mode 100644
index 75534ed..0000000
--- a/virtio_blk.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Virtio Block Device
- *
- * Copyright IBM, Corp. 2007
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- */
-
-#ifndef QEMU_VIRTIO_BLK_H
-#define QEMU_VIRTIO_BLK_H
-
-#include "standard-headers/linux/virtio_blk.h"
-#include "hw/virtio/virtio.h"
-#include "hw/block/block.h"
-#include "sysemu/iothread.h"
-#include "sysemu/block-backend.h"
-#include "qom/object.h"
-
-#define TYPE_VIRTIO_BLK "virtio-blk-device"
-#define VIRTIO_BLK_AUTO_NUM_QUEUES UINT16_MAX
-OBJECT_DECLARE_SIMPLE_TYPE(VirtIOBlock, VIRTIO_BLK)
-
-/* This is the last element of the write scatter-gather list */
-struct virtio_blk_inhdr {
- unsigned char status;
-};
-
-
-struct VirtIOBlkConf {
- BlockConf conf;
- IOThread *iothread;
- char *serial;
- uint32_t request_merging;
- uint16_t num_queues;
- uint16_t queue_size;
- bool seg_max_adjust;
- bool report_discard_granularity;
- uint32_t max_discard_sectors;
- uint32_t max_write_zeroes_sectors;
- bool x_enable_wce_if_config_wce;
-};
-
-
-struct VirtIOBlockDataPlane;
-
-struct VirtIOBlockReq;
-struct VirtIOBlock {
- VirtIODevice parent_obj;
- BlockBackend *blk;
- void *rq;
- QEMUBH *bh;
- VirtIOBlkConf conf;
- unsigned short sector_mask;
- bool original_wce;
- VMChangeStateEntry *change;
- bool dataplane_disabled;
- bool dataplane_started;
- struct VirtIOBlockDataPlane *dataplane;
- uint64_t host_features;
- size_t config_size;
-};
-
-typedef struct VirtIOBlockReq {
- VirtQueueElement elem;
- int64_t sector_num;
- VirtIOBlock *dev;
- VirtQueue *vq;
- IOVDiscardUndo inhdr_undo;
- IOVDiscardUndo outhdr_undo;
- struct virtio_blk_inhdr *in;
- struct virtio_blk_outhdr out;
- QEMUIOVector qiov;
- size_t in_len;
- struct VirtIOBlockReq *next;
- struct VirtIOBlockReq *mr_next;
- BlockAcctCookie acct;
-} VirtIOBlockReq;
-
-#define VIRTIO_BLK_MAX_MERGE_REQS 32
-
-typedef struct MultiReqBuffer {
- VirtIOBlockReq *reqs[VIRTIO_BLK_MAX_MERGE_REQS];
- unsigned int num_reqs;
- bool is_write;
-} MultiReqBuffer;
-
-bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq);
-void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh);
-
-#endif
diff --git a/virtio_input.c b/virtio_input.c
deleted file mode 100644
index 668abe6..0000000
--- a/virtio_input.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * Based on virtio-input.h of QEMU project
- *
- * Copyright (c) 2022-2023 Virtual Open Systems SAS.
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or
- * (at your option) any later version. See the COPYING file in the
- * top-level directory.
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <stdbool.h>
-#include <sys/param.h>
-
-/* Project header files */
-#include "vhost_user_input.h"
-
-#ifdef DEBUG
-#define DBG(...) printf("virtio-input: " __VA_ARGS__)
-#else
-#define DBG(...)
-#endif /* DEBUG */
-
-#define VIRTIO_INPUT_VM_VERSION 1
-
-/* ----------------------------------------------------------------- */
-
-/*
- * Example struct for keyboard
- */
-static struct virtio_input_config virtio_keyboard_config[] = {
- {
- .select = VIRTIO_INPUT_CFG_ID_NAME,
- .size = sizeof(VIRTIO_ID_NAME_KEYBOARD),
- .u.string = VIRTIO_ID_NAME_KEYBOARD,
- },{
- .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
- .size = sizeof(struct virtio_input_devids),
- .u.ids = {
- .bustype = (BUS_VIRTUAL),
- .vendor = (0x0627), /* same we use for usb hid devices */
- .product = (0x0001),
- .version = (0x0001),
- },
- },{
- .select = VIRTIO_INPUT_CFG_EV_BITS,
- .subsel = EV_KEY,
- .size = 1,
- .u.bitmap = {
- KEY_G,
- },
- },
- {}, /* End of list */
-};
-
-
-void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event)
-{
- DBG("virtio_input_send() not yet implemeted\n");
- (void)vinput;
- (void)event;
-}
-
-static void virtio_input_handle_evt(VirtIODevice *vdev, VirtQueue *vq)
-{
- DBG("virtio_input_handle_evt(...) not yet implemeted\n");
- (void)vdev;
- (void)vq;
-}
-
-static void virtio_input_handle_sts(VirtIODevice *vdev, VirtQueue *vq)
-{
- VirtIOInputClass *vic = vdev->vinput->input_class;
- VirtIOInput *vinput = vdev->vinput;
- virtio_input_event event;
- VirtQueueElement *elem;
- int len;
-
- DBG("virtio_input_handle_sts(...)\n");
- (void)vq;
-
- for (;;) {
- elem = virtqueue_pop(vinput->sts, sizeof(VirtQueueElement));
- if (!elem) {
- break;
- }
-
- memset(&event, 0, sizeof(event));
- /* FIXME: add iov_to_buf func */
- len = 1;
- /*
- * TODO: Will be added in a next release
- * len = iov_to_buf(elem->out_sg, elem->out_num,
- * 0, &event, sizeof(event));
- */
- if (vic->handle_status) {
- vic->handle_status(vinput, &event);
- }
- virtqueue_push(vinput->sts, elem, len);
- munmap(elem, sizeof(VirtQueueElement));
- }
- virtio_notify(vdev, vinput->sts);
-}
-
-virtio_input_config *virtio_input_find_config(VirtIOInput *vinput,
- uint8_t select,
- uint8_t subsel)
-{
- DBG("virtio_input_find_config(...)\n");
- VirtIOInputConfig *cfg;
-
- QTAILQ_FOREACH(cfg, &vinput->cfg_list, node) {
- if (select == cfg->config.select &&
- subsel == cfg->config.subsel) {
- return &cfg->config;
- }
- }
- return NULL;
-}
-
-void virtio_input_add_config(VirtIOInput *vinput,
- virtio_input_config *config)
-{
- DBG("virtio_input_add_config(...)\n");
- VirtIOInputConfig *cfg;
-
- if (virtio_input_find_config(vinput, config->select, config->subsel)) {
- /* should not happen */
- DBG("Error duplicate config: %d/%d\n", config->select, config->subsel);
- exit(1);
- }
-
- cfg = (VirtIOInputConfig *)malloc(sizeof(VirtIOInputConfig));
- cfg->config = *config;
-
- QTAILQ_INSERT_TAIL(&vinput->cfg_list, cfg, node);
-}
-
-void virtio_input_init_config(VirtIOInput *vinput,
- virtio_input_config *config)
-{
- DBG("virtio_input_init_config(...)\n");
- int i = 0;
-
- QTAILQ_INIT(&vinput->cfg_list);
- while (config[i].select) {
- virtio_input_add_config(vinput, config + i);
- i++;
- }
-}
-
-void virtio_input_idstr_config(VirtIOInput *vinput,
- uint8_t select, const char *string)
-{
- DBG("virtio_input_idstr_config(...)\n");
- virtio_input_config id;
-
- if (!string) {
- return;
- }
- memset(&id, 0, sizeof(id));
- id.select = select;
- id.size = snprintf(id.u.string, sizeof(id.u.string), "%s", string);
- virtio_input_add_config(vinput, &id);
-}
-
-static void virtio_input_get_config(VirtIODevice *vdev, uint8_t *config_data)
-{
- DBG("virtio_input_get_config(...)\n");
- VirtIOInput *vinput = vdev->vinput;
- virtio_input_config *config;
-
- config = virtio_input_find_config(vinput, vinput->cfg_select,
- vinput->cfg_subsel);
- if (config) {
- memcpy(config_data, config, vinput->cfg_size);
- } else {
- memset(config_data, 0, vinput->cfg_size);
- }
-}
-
-static void virtio_input_set_config(VirtIODevice *vdev,
- const uint8_t *config_data)
-{
- VirtIOInput *vinput = vdev->vinput;
- virtio_input_config *config = (virtio_input_config *)config_data;
-
- DBG("virtio_input_set_config(...)\n");
-
- vinput->cfg_select = config->select;
- vinput->cfg_subsel = config->subsel;
- virtio_notify_config(vdev);
-}
-
-static uint64_t virtio_input_get_features(VirtIODevice *vdev, uint64_t f)
-{
- DBG("virtio_input_get_features(...)\n");
- (void)vdev;
- (void)f;
-
- return f;
-}
-
-static void virtio_input_set_status(VirtIODevice *vdev, uint8_t val)
-{
- VirtIOInputClass *vic = vdev->vinput->input_class;
- VirtIOInput *vinput = vdev->vinput;
- bool should_start = virtio_device_started(vdev, val);
-
- DBG("virtio_input_set_status(...): %u\n", val);
-
- if (should_start) {
- if (!vinput->active) {
- vinput->active = true;
- if (vic->change_active) {
- vic->change_active(vinput);
- }
- }
- }
-}
-
-static void virtio_input_reset(VirtIODevice *vdev)
-{
- VirtIOInputClass *vic = vdev->vinput->input_class;
- VirtIOInput *vinput = vdev->vinput;
-
- DBG("virtio_input_reset(...)\n");
-
- if (vinput->active) {
- vinput->active = false;
- if (vic->change_active) {
- vic->change_active(vinput);
- }
- }
-}
-
-/*
- * Functions which might be used in the future:
- *
- * static int virtio_input_post_load(void *opaque, int version_id)
- * {
- * VirtIOInput *vinput = global_vdev->vinput;
- * VirtIOInputClass *vic = global_vdev->vinput->input_class;
- * VirtIODevice *vdev = global_vdev;
- *
- * DBG("virtio_input_post_load(...)\n");
- * (void)opaque;
- * (void)version_id;
- *
- * vinput->active = vdev->status & VIRTIO_CONFIG_S_DRIVER_OK;
- * if (vic->change_active) {
- * vic->change_active(vinput);
- * }
- * return 0;
- * }
- *
- * static void virtio_input_finalize(VirtIODevice *vdev)
- * {
- * DBG("virtio_input_finalize not yet implemented");
- * (void)vdev;
- * }
- *
- * static void virtio_input_device_unrealize(VirtIODevice *vdev)
- * {
- * DBG("virtio_input_device_unrealize not yet implemented");
- * (void)vdev;
- * }
- */
-
-void virtio_input_device_realize(int queue_num, int queue_size)
-{
- VirtIODevice *vdev = global_vdev;
- struct VirtIOInputClass *vic = vdev->vinput->input_class;
- VirtIOInput *vinput = vdev->vinput;
- VirtIOInputConfig *cfg;
-
- DBG("virtio_input_device_realize(...)\n");
- (void)queue_num;
- (void)queue_size;
-
- /* This needs to be added */
- proxy = (VirtIOMMIOProxy *)malloc(sizeof(VirtIOMMIOProxy));
- *proxy = (VirtIOMMIOProxy) {
- .legacy = 1,
- };
-
- if (vic->realize) {
- vic->realize(vdev);
- }
-
- virtio_input_idstr_config(vinput, VIRTIO_INPUT_CFG_ID_SERIAL,
- vinput->serial);
-
- QTAILQ_FOREACH(cfg, &vinput->cfg_list, node) {
- if (vinput->cfg_size < cfg->config.size) {
- vinput->cfg_size = cfg->config.size;
- }
- }
- vinput->cfg_size += 8;
-
- virtio_input_init_config(vinput, virtio_keyboard_config);
-
- virtio_dev_init(vdev, "virtio-input", 18, vinput->cfg_size);
- vinput->evt = virtio_add_queue(vdev, 64, virtio_input_handle_evt);
- vinput->sts = virtio_add_queue(vdev, 64, virtio_input_handle_sts);
-
- /* FIXME: do we need that? */
- memcpy(global_vdev->vq, vinput->evt, sizeof(VirtQueue));
- memcpy(&global_vdev->vq[1], vinput->sts, sizeof(VirtQueue));
-
- DBG("global_vdev->guest_features: 0x%lx\n", global_vdev->guest_features);
-}
-
-void virtio_input_class_init(VirtIODevice *vdev)
-{
- vdev->vdev_class = (VirtioDeviceClass *)malloc(sizeof(VirtioDeviceClass));
- vdev->vdev_class->parent = vdev;
-
- DBG("virtio_input_class_init(...)\n");
-
- vdev->vdev_class->realize = virtio_input_device_realize;
- vdev->vdev_class->get_config = virtio_input_get_config;
- vdev->vdev_class->set_config = virtio_input_set_config;
- vdev->vdev_class->get_features = virtio_input_get_features;
- vdev->vdev_class->set_status = virtio_input_set_status;
- vdev->vdev_class->reset = virtio_input_reset;
-}