diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | adapter.c | 20 | ||||
-rw-r--r-- | event_notifier.c | 2 | ||||
-rw-r--r-- | event_notifier.h | 2 | ||||
-rw-r--r-- | vhost_loopback.c | 2 | ||||
-rw-r--r-- | vhost_loopback.h | 2 | ||||
-rw-r--r-- | vhost_user_blk.c | 2 | ||||
-rw-r--r-- | vhost_user_blk.h | 2 | ||||
-rw-r--r-- | vhost_user_gpio.c | 381 | ||||
-rw-r--r-- | vhost_user_gpio.h | 37 | ||||
-rw-r--r-- | vhost_user_input.c | 2 | ||||
-rw-r--r-- | vhost_user_input.h | 2 | ||||
-rw-r--r-- | vhost_user_loopback.c | 2 | ||||
-rw-r--r-- | vhost_user_loopback.h | 2 | ||||
-rw-r--r-- | vhost_user_rng.c | 2 | ||||
-rw-r--r-- | vhost_user_rng.h | 2 | ||||
-rw-r--r-- | virtio_input.c | 2 | ||||
-rw-r--r-- | virtio_loopback.c | 112 | ||||
-rw-r--r-- | virtio_loopback.h | 11 | ||||
-rw-r--r-- | virtio_rng.c | 2 | ||||
-rw-r--r-- | virtio_rng.h | 2 |
21 files changed, 489 insertions, 108 deletions
@@ -1,4 +1,4 @@ -# Copyright 2022 Virtual Open Systems SAS. +# Copyright 2022-2023 Virtual Open Systems SAS # # Authors: # Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com> @@ -21,7 +21,7 @@ #CFLAGS := -Wall -Wextra -Werror #CFLAGS := -Wall -Wextra -Wno-unused-variable -Wno-unused-function CFLAGS := -Wno-unused-variable -Wno-unused-function -D_GNU_SOURCE -CFLAGS = -D_GNU_SOURCE -O2 -static +CFLAGS = -D_GNU_SOURCE -O2 CC ?= ifeq ($(ARCH), arm64) @@ -33,7 +33,7 @@ endif INCL += -I . 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_loopback.c adapter.c +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_gpio.c vhost_loopback.c adapter.c OBJS = $(SRC_C:.c=.o) BINS = adapter @@ -1,5 +1,5 @@ /* - * Copyright 2022 Virtual Open Systems SAS. + * Copyright 2022-2023 Virtual Open Systems SAS * * Authors: * Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com> @@ -47,6 +47,7 @@ #include "vhost_user_rng.h" #include "vhost_user_blk.h" #include "vhost_user_input.h" +#include "vhost_user_gpio.h" #ifdef DEBUG #define DBG(...) printf("adapter: " __VA_ARGS__) @@ -137,7 +138,7 @@ static void help_args(void) "\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\n"); + "\tvrng, vhurng, vhublk, vhuinput, vhugpio\n"); } int find_arg(int argc, char **argv, char *str) @@ -154,9 +155,10 @@ int find_arg(int argc, char **argv, char *str) int val_device_arg(char *str) { - char *adapter_devices[] = {"vrng", "vhurng", "vhublk", "vhuinput"}; - char *vhu_devices[] = {"vhurng", "vhublk", "vhuinput"}; - int adapter_devices_num = 4, i; + char *adapter_devices[] = {"vrng", "vhurng", "vhublk", "vhuinput", + "vhugpio"}; + char *vhu_devices[] = {"vhurng", "vhublk", "vhuinput", "vhugpio"}; + int adapter_devices_num = 5, i; for (i = 0; i < adapter_devices_num; i++) { if (!strcmp(adapter_devices[i], str)) { @@ -169,8 +171,8 @@ int val_device_arg(char *str) bool check_vhu_device(char *str) { - char *vhu_devices[] = {"vhurng", "vhublk", "vhuinput"}; - int vhu_devices_num = 3, i; + char *vhu_devices[] = {"vhurng", "vhublk", "vhuinput", "vhugpio"}; + int vhu_devices_num = 4, i; for (i = 0; i < vhu_devices_num; i++) { if (!strcmp(vhu_devices[i], str)) { @@ -269,6 +271,7 @@ int main(int argc, char **argv) vhost_user_adapter_init(); /* Initialize the virtio/vhost-user device */ + /* TODO: Switch numbers with name defs */ switch (device_id) { case 1: virtio_rng_realize(); @@ -286,6 +289,9 @@ int main(int argc, char **argv) vhost_user_input_init(global_vdev); virtio_input_device_realize(); break; + case 5: + vu_gpio_device_realize(); + break; default: exit(1); } diff --git a/event_notifier.c b/event_notifier.c index 5a5d1c3..5b7c1cd 100644 --- a/event_notifier.c +++ b/event_notifier.c @@ -16,7 +16,7 @@ * Copyright (c) 2003-2008 Fabrice Bellard * Copyright (c) 2010 Red Hat, Inc. * - * Copyright 2022 Virtual Open Systems SAS. + * Copyright 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 diff --git a/event_notifier.h b/event_notifier.h index 070b777..718f784 100644 --- a/event_notifier.h +++ b/event_notifier.h @@ -6,7 +6,7 @@ * Authors: * Michael S. Tsirkin <mst@redhat.com> * - * Copyright 2022 Virtual Open Systems SAS. + * Copyright 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 diff --git a/vhost_loopback.c b/vhost_loopback.c index 3e137eb..af725e3 100644 --- a/vhost_loopback.c +++ b/vhost_loopback.c @@ -11,7 +11,7 @@ * Authors: * Michael S. Tsirkin <mst@redhat.com> * - * Copyright 2022 Virtual Open Systems SAS. + * Copyright 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 diff --git a/vhost_loopback.h b/vhost_loopback.h index 78c2755..198a5af 100644 --- a/vhost_loopback.h +++ b/vhost_loopback.h @@ -1,7 +1,7 @@ /* * Based on vhost.h of QEMU project * - * Copyright 2022 Virtual Open Systems SAS. + * Copyright 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 diff --git a/vhost_user_blk.c b/vhost_user_blk.c index 756b0a5..d182a74 100644 --- a/vhost_user_blk.c +++ b/vhost_user_blk.c @@ -11,7 +11,7 @@ * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> * Nicholas Bellinger <nab@risingtidesystems.com> * - * Copyright (c) 2022 Virtual Open Systems SAS. + * 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 diff --git a/vhost_user_blk.h b/vhost_user_blk.h index 3b09f75..d5857c8 100644 --- a/vhost_user_blk.h +++ b/vhost_user_blk.h @@ -7,7 +7,7 @@ * Changpeng Liu <changpeng.liu@intel.com> * * - * Copyright (c) 2022 Virtual Open Systems SAS. + * Copyright (c) 2022-2023 Virtual Open Systems SAS. * * * This program is free software; you can redistribute it and/or modify diff --git a/vhost_user_gpio.c b/vhost_user_gpio.c new file mode 100644 index 0000000..6049bd5 --- /dev/null +++ b/vhost_user_gpio.c @@ -0,0 +1,381 @@ +/* + * 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"); + 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; + int ret, i; + + 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"); +} + +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"); +} + +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"); +} + +static int vu_gpio_connect(VirtIODevice *vdev) +{ + VHostUserGPIO *gpio = vdev->vhugpio; + int ret; + + 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"); +} + +static void print_config_gpio(uint8_t *config_data) +{ + struct virtio_gpio_config *config = + (struct virtio_gpio_config *)config_data; + + 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 = &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 retries, ret; + int i; + + DBG("vu_gpio_device_realize()\n"); + + /* 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_gpio.h b/vhost_user_gpio.h new file mode 100644 index 0000000..4477ba7 --- /dev/null +++ b/vhost_user_gpio.h @@ -0,0 +1,37 @@ +/* + * Based on virtio-gpio.h of QEMU project + * + * 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. + */ + +#ifndef VHOST_USER_GPIO +#define VHOST_USER_GPIO + +#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 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; +}; + +void vu_gpio_device_realize(); + +#endif /* VHOST_USER_GPIO */ diff --git a/vhost_user_input.c b/vhost_user_input.c index d6764cc..9cb2164 100644 --- a/vhost_user_input.c +++ b/vhost_user_input.c @@ -1,7 +1,7 @@ /* * Based on vhost-user-input.c of QEMU project * - * Copyright (c) 2022 Virtual Open Systems SAS. + * 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 diff --git a/vhost_user_input.h b/vhost_user_input.h index 0d5c900..741006e 100644 --- a/vhost_user_input.h +++ b/vhost_user_input.h @@ -1,7 +1,7 @@ /* * Based on virtio-input.h of QEMU project * - * Copyright (c) 2022 Virtual Open Systems SAS. + * 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 diff --git a/vhost_user_loopback.c b/vhost_user_loopback.c index 47ce1cd..85b9405 100644 --- a/vhost_user_loopback.c +++ b/vhost_user_loopback.c @@ -9,7 +9,7 @@ * Marc-André Lureau <mlureau@redhat.com> * Victor Kaplansky <victork@redhat.com> * - * Copyright 2022 Virtual Open Systems SAS. + * Copyright 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 diff --git a/vhost_user_loopback.h b/vhost_user_loopback.h index 2ced983..8aa7e05 100644 --- a/vhost_user_loopback.h +++ b/vhost_user_loopback.h @@ -7,7 +7,7 @@ * Victor Kaplansky <victork@redhat.com> * Marc-André Lureau <mlureau@redhat.com> * - * Copyright 2022 Virtual Open Systems SAS. + * Copyright 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 diff --git a/vhost_user_rng.c b/vhost_user_rng.c index 6d4fd5c..c727636 100644 --- a/vhost_user_rng.c +++ b/vhost_user_rng.c @@ -3,7 +3,7 @@ * * Copyright (c) 2021 Mathieu Poirier <mathieu.poirier@linaro.org> * - * Copyright (c) 2022 Virtual Open Systems SAS. + * 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 diff --git a/vhost_user_rng.h b/vhost_user_rng.h index fd39800..69b5916 100644 --- a/vhost_user_rng.h +++ b/vhost_user_rng.h @@ -3,7 +3,7 @@ * * Copyright (c) 2021 Mathieu Poirier <mathieu.poirier@linaro.org> * - * Copyright (c) 2022 Virtual Open Systems SAS. + * Copyright (c) 2022-2023 Virtual Open Systems SAS. * * Author: * Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com> diff --git a/virtio_input.c b/virtio_input.c index 18ef3d4..c0993ea 100644 --- a/virtio_input.c +++ b/virtio_input.c @@ -1,7 +1,7 @@ /* * Based on virtio-input.h of QEMU project * - * Copyright (c) 2022 Virtual Open Systems SAS. + * 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 diff --git a/virtio_loopback.c b/virtio_loopback.c index f9e5464..e95c648 100644 --- a/virtio_loopback.c +++ b/virtio_loopback.c @@ -18,7 +18,7 @@ * Peter Maydell <peter.maydell@linaro.org> * * - * Copyright 2022 Virtual Open Systems SAS. + * Copyright 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; either version 2 @@ -80,6 +80,9 @@ 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); @@ -860,9 +863,9 @@ err: void print_neg_flag(uint64_t neg_flag, bool read) { if (read) { - DBG("Read:\n"); + DBG("Read:\t"); } else { - DBG("Write:\n"); + DBG("Write:\t"); } switch (neg_flag) { @@ -1005,8 +1008,6 @@ static void virtio_queue_guest_notifier_read(EventNotifier *n) } } -int eventfd_count; - void *loopback_event_select(void *_e) { int retval; @@ -1032,14 +1033,19 @@ void *loopback_event_select(void *_e) if (retval > 0) { DBG("\n\nEvent has come from the vhost-user-device " - "(eventfd: %d) -> event_count: %d\n\n", - rfd, eventfd_count); + "(eventfd: %d) -> event_count: %d (select value: %d)\n\n", + rfd, eventfd_count, retval); - eventfd_count++; if (event_notifier_test_and_clear(e)) { - virtio_irq(vq); + if (pthread_mutex_lock(&interrupt_lock) == 0) { + eventfd_count++; + virtio_irq(vq); + pthread_mutex_unlock(&interrupt_lock); + } else { + printf("[ERROR] Locking failed\n"); + exit(1); + } } - } } } @@ -1226,7 +1232,7 @@ void virtio_loopback_update_irq(VirtIODevice *vdev) DBG("prev_level: %d\n", prev_level); if (!((level == 1) && (prev_level == 0))) { - DBG("!((level == 1) && (prev_level == 0))\n"); + DBG("No interrupt\n"); prev_level = level; return; } @@ -1236,7 +1242,6 @@ void virtio_loopback_update_irq(VirtIODevice *vdev) DBG("Interrupt counter: %d\n", int_count++); (void) ioctl(fd, IRQ, &irq_num); - } bool enable_virtio_interrupt; @@ -1280,7 +1285,6 @@ void virtio_queue_notify(VirtIODevice *vdev, int n) } if (vq->host_notifier_enabled) { - DBG("vq->host_notifier_enabled\n"); event_notifier_set(&vq->host_notifier); } else if (vq->handle_output) { DBG("vq->handle_output\n"); @@ -1397,8 +1401,6 @@ static uint64_t virtio_loopback_read(VirtIODevice *vdev, uint64_t offset, uint64_t ret; - DBG("READ\n"); - if (!vdev) { /* * If no backend is present, we treat most registers as @@ -1545,14 +1547,13 @@ static uint64_t virtio_loopback_read(VirtIODevice *vdev, uint64_t offset, return 0; } -uint64_t vring_phys_addrs[2] = {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) { - if (!vdev) { /* * If no backend is present, we just make all registers @@ -1690,7 +1691,7 @@ void virtio_loopback_write(VirtIODevice *vdev, uint64_t offset, /* TODO: To be implemented */ break; case VIRTIO_MMIO_QUEUE_NOTIFY: - DBG("\nVIRTIO_MMIO_QUEUE_NOTIFY: vq_index -> %d, notify_cnt: %d\n", + DBG("VIRTIO_MMIO_QUEUE_NOTIFY: vq_index -> %d, notify_cnt: %d\n", value, notify_cnt++); if (value < VIRTIO_QUEUE_MAX) { virtio_queue_notify(vdev, value); @@ -1824,39 +1825,6 @@ void adapter_read_write_cb(void) } -void *notify_select(void *data) -{ - int retval; - fd_set rfds; - uint64_t eftd_ctr; - int efd = *(int *)data; - int32_t vq_index; - - DBG("\nWaiting for loopback notify events\n"); - - FD_ZERO(&rfds); - FD_SET(efd, &rfds); - - while (1) { - - retval = select(efd + 1, &rfds, NULL, NULL, NULL); - - if (retval > 0) { - s = read(efd, &eftd_ctr, sizeof(uint64_t)); - if (s != sizeof(uint64_t)) { - DBG("Eventfd read error\n"); - exit(1); - } else { - DBG("\nnotify select\n"); - (void)ioctl(fd, SHARE_NOTIFIED_VQ_INDEX, &vq_index); - DBG("\nnotify_select: vq_index -> %d, notify_cnt: %d," - "eventfd_val: %lu\n\n", vq_index, notify_cnt++, eftd_ctr); - virtio_queue_notify(global_vdev, vq_index); - } - } - } -} - void *driver_event_select(void *data) { int retval; @@ -1937,6 +1905,20 @@ void virtio_dev_init(VirtIODevice *vdev, const char *name, 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; + + /* Initialize interrupt mutex */ + if (pthread_mutex_init(&interrupt_lock, NULL) != 0) { + printf("[ERROR] mutex init has failed\n"); + exit(1); + } + vdev->start_on_kick = false; vdev->started = false; vdev->device_id = device_id; @@ -2004,18 +1986,9 @@ int virtio_loopback_start(void) { efd_data_t info; pthread_t thread_id; - pthread_t thread_id_notify; int ret = -1; int flags; - /* Initialize global variables */ - prev_level = 0; - int_count = 0; - eventfd_count = 0; - enable_virtio_interrupt = false; - vring_phys_addrs_idx = 0; - notify_cnt = 0; - fd = open("/dev/loopback", O_RDWR); if (fd < 0) { perror("Open call failed"); @@ -2030,15 +2003,8 @@ int virtio_loopback_start(void) exit(EXIT_FAILURE); } - efd_notify = eventfd(0, 0); - if (efd_notify == -1) { - DBG("\nUnable to create eventfd! Exiting...\n"); - exit(EXIT_FAILURE); - } - info.pid = getpid(); info.efd[0] = efd; - info.efd[1] = efd_notify; /* * Send the appropriate information to the driver @@ -2060,13 +2026,6 @@ int virtio_loopback_start(void) exit(1); } - /* Wait the eventfd */ - ret = pthread_create(&thread_id_notify, NULL, notify_select, - (void *)&efd_notify); - if (ret != 0) { - exit(1); - } - /* Start loopback transport */ (void)ioctl(fd, START_LOOPBACK, &device_info); @@ -2075,11 +2034,6 @@ int virtio_loopback_start(void) exit(1); } - ret = pthread_join(thread_id_notify, NULL); - if (ret != 0) { - exit(1); - } - DBG("\nClosing eventfd. Exiting...\n"); close(efd); diff --git a/virtio_loopback.h b/virtio_loopback.h index 849f3a9..34bae2f 100644 --- a/virtio_loopback.h +++ b/virtio_loopback.h @@ -16,7 +16,7 @@ * * 3) vhost.h of QEMU project * - * Copyright 2022 Virtual Open Systems SAS. + * Copyright 2022-2023 Virtual Open Systems SAS. * * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. @@ -167,7 +167,6 @@ #define SHARE_VQS _IOC(_IOC_WRITE, 'k', 5, sizeof(uint32_t)) #define SHARE_BUF _IOC(_IOC_WRITE, 'k', 6, sizeof(uint64_t)) #define SHARE_COM_STRUCT _IOC(_IOC_WRITE, 'k', 7, 0) -#define SHARE_NOTIFIED_VQ_INDEX _IOC(_IOC_WRITE, 'k', 8, sizeof(int32_t)) #define VIRTIO_PCI_VRING_ALIGN 4096 @@ -261,7 +260,7 @@ typedef struct VirtIOMMIOProxy { const typeof(((type *) 0)->member) *__mptr = (ptr); \ (type *) ((char *) __mptr - offsetof(type, member));}) -extern uint64_t vring_phys_addrs[2]; +extern uint64_t vring_phys_addrs[10]; extern uint32_t vring_phys_addrs_idx; typedef struct VRing { @@ -363,6 +362,8 @@ typedef struct VHostUserRNG VHostUserRNG; typedef struct VirtioDeviceClass VirtioDeviceClass; typedef struct VHostUserBlk VHostUserBlk; typedef struct VhostUserInput VhostUserInput; +typedef struct VHostUserGPIO VHostUserGPIO; +typedef struct VHostUserSound VHostUserSound; typedef struct VirtioBus VirtioBus; typedef struct VirtIODevice { @@ -402,6 +403,8 @@ typedef struct VirtIODevice { VHostUserRNG *vhrng; VHostUserBlk *vhublk; VhostUserInput *vhuinput; + VHostUserSound *vhusnd; + VHostUserGPIO *vhugpio; } VirtIODevice; typedef struct efd_data { @@ -690,7 +693,7 @@ uint32_t get_vqs_max_size(VirtIODevice *vdev); * memory blocks from the kernel: * 0x40000000 = 1024 * 1024 * 1024 = 64 * 4096 * 4096 = 1G */ -#define OFFSET_1GB 64ULL * PAGE_SIZE * PAGE_SIZE +#define OFFSET_1GB (64ULL * PAGE_SIZE * PAGE_SIZE) /* * Define starting physical address of host memory address space diff --git a/virtio_rng.c b/virtio_rng.c index ca8f971..6a5b24b 100644 --- a/virtio_rng.c +++ b/virtio_rng.c @@ -5,7 +5,7 @@ * Copyright 2012 Red Hat, Inc. * Copyright 2012 Amit Shah <amit.shah@redhat.com> * - * Copyright 2022 Virtual Open Systems SAS. + * Copyright 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 diff --git a/virtio_rng.h b/virtio_rng.h index 8147864..cf35c29 100644 --- a/virtio_rng.h +++ b/virtio_rng.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 Virtual Open Systems SAS. + * Copyright 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 |