diff options
Diffstat (limited to 'vhost_user_gpio.c')
-rw-r--r-- | vhost_user_gpio.c | 393 |
1 files changed, 0 insertions, 393 deletions
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; -} |