Browse Source
virtio introspection new serial number opton for cxl vhost user blk dynamic config size virtio-gpio vhost user backend Tests fixes cleanups all over the place Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- iQFDBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAmNEVeoPHG1zdEByZWRo YXQuY29tAAoJECgfDbjSjVRph8YH+gMWpb5IglE0Q+H2JiQPBwB/Ghy1ohRKnOvZ lChB7+oy18o2xXRFTOXwG9Ijqsbdn0QMbU/r3NWxBuMzxDow012xiMDniJlJmcXw /4POOCSTKrIfzVBhsEErVSA9NwSE5cQKr1oiRBGIa9UdZfZ//v7s6SoP4vtyj8RZ UJVYVnMDtq/0PaN92IMs06lhqo/LkegE7gTGHMBf8Nvw4SgQoZgfPyp1eR+dKOhz lXNqqvTds9yt8yS65UWbuSrZ9d7GpCQf8nuyLaLaENHd6FQUVfmTTT37l2EKziwp PK0EwWMHeGkj7LHrylztradhE9xBlIW23ROP8wPdGZHmgLNHbC0= =20Zb -----END PGP SIGNATURE----- Merge tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu into staging pc,virtio: features, tests, fixes, cleanups virtio introspection new serial number opton for cxl vhost user blk dynamic config size virtio-gpio vhost user backend Tests fixes cleanups all over the place Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # -----BEGIN PGP SIGNATURE----- # # iQFDBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAmNEVeoPHG1zdEByZWRo # YXQuY29tAAoJECgfDbjSjVRph8YH+gMWpb5IglE0Q+H2JiQPBwB/Ghy1ohRKnOvZ # lChB7+oy18o2xXRFTOXwG9Ijqsbdn0QMbU/r3NWxBuMzxDow012xiMDniJlJmcXw # /4POOCSTKrIfzVBhsEErVSA9NwSE5cQKr1oiRBGIa9UdZfZ//v7s6SoP4vtyj8RZ # UJVYVnMDtq/0PaN92IMs06lhqo/LkegE7gTGHMBf8Nvw4SgQoZgfPyp1eR+dKOhz # lXNqqvTds9yt8yS65UWbuSrZ9d7GpCQf8nuyLaLaENHd6FQUVfmTTT37l2EKziwp # PK0EwWMHeGkj7LHrylztradhE9xBlIW23ROP8wPdGZHmgLNHbC0= # =20Zb # -----END PGP SIGNATURE----- # gpg: Signature made Mon 10 Oct 2022 13:27:06 EDT # gpg: using RSA key 5D09FD0871C8F85B94CA8A0D281F0DB8D28D5469 # gpg: issuer "mst@redhat.com" # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full] # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" [full] # Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67 # Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469 * tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu: (55 commits) x86: pci: acpi: consolidate PCI slots creation tests: acpi: update expected blobs x86: pci: acpi: reorder Device's _DSM method tests: acpi: whitelist pc/q35 DSDT before moving _ADR field tests: acpi: update expected blobs x86: pci: acpi: reorder Device's _ADR and _SUN fields tests: acpi: whitelist pc/q35 DSDT before moving _ADR field tests: acpi: update expected blobs x86: acpi: cleanup PCI device _DSM duplication tests: acpi: whitelist pc/q35 DSDT before switching _DSM to use ASUN tests: acpi: update expected blobs x86: acpi: _DSM: use Package to pass parameters acpi: x86: refactor PDSM method to reduce nesting tests: acpi: whitelist pc/q35 DSDT due to HPET AML move tests: acpi: update expected blobs after HPET move acpi: x86: deduplicate HPET AML building tests: acpi: whitelist pc/q35 DSDT due to HPET AML move hw/smbios: support for type 8 (port connector) pci: Sanity check mask argument to pci_set_*_by_mask() pci: Remove unused pci_get_*_by_mask() functions ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>pull/223/head
87 changed files with 3796 additions and 289 deletions
@ -0,0 +1,39 @@ |
|||
/*
|
|||
* Virtio Block Device common helpers |
|||
* |
|||
* 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. |
|||
*/ |
|||
|
|||
#include "qemu/osdep.h" |
|||
|
|||
#include "standard-headers/linux/virtio_blk.h" |
|||
#include "hw/virtio/virtio.h" |
|||
#include "hw/virtio/virtio-blk-common.h" |
|||
|
|||
/* Config size before the discard support (hide associated config fields) */ |
|||
#define VIRTIO_BLK_CFG_SIZE offsetof(struct virtio_blk_config, \ |
|||
max_discard_sectors) |
|||
|
|||
/*
|
|||
* Starting from the discard feature, we can use this array to properly |
|||
* set the config size depending on the features enabled. |
|||
*/ |
|||
static const VirtIOFeature feature_sizes[] = { |
|||
{.flags = 1ULL << VIRTIO_BLK_F_DISCARD, |
|||
.end = endof(struct virtio_blk_config, discard_sector_alignment)}, |
|||
{.flags = 1ULL << VIRTIO_BLK_F_WRITE_ZEROES, |
|||
.end = endof(struct virtio_blk_config, write_zeroes_may_unmap)}, |
|||
{} |
|||
}; |
|||
|
|||
const VirtIOConfigSizeParams virtio_blk_cfg_size_params = { |
|||
.min_size = VIRTIO_BLK_CFG_SIZE, |
|||
.max_size = sizeof(struct virtio_blk_config), |
|||
.feature_sizes = feature_sizes |
|||
}; |
|||
@ -0,0 +1,69 @@ |
|||
/*
|
|||
* Vhost-user gpio virtio device PCI glue |
|||
* |
|||
* Copyright (c) 2022 Viresh Kumar <viresh.kumar@linaro.org> |
|||
* |
|||
* SPDX-License-Identifier: GPL-2.0-or-later |
|||
*/ |
|||
|
|||
#include "qemu/osdep.h" |
|||
#include "hw/qdev-properties.h" |
|||
#include "hw/virtio/vhost-user-gpio.h" |
|||
#include "hw/virtio/virtio-pci.h" |
|||
|
|||
struct VHostUserGPIOPCI { |
|||
VirtIOPCIProxy parent_obj; |
|||
VHostUserGPIO vdev; |
|||
}; |
|||
|
|||
typedef struct VHostUserGPIOPCI VHostUserGPIOPCI; |
|||
|
|||
#define TYPE_VHOST_USER_GPIO_PCI "vhost-user-gpio-pci-base" |
|||
|
|||
DECLARE_INSTANCE_CHECKER(VHostUserGPIOPCI, VHOST_USER_GPIO_PCI, |
|||
TYPE_VHOST_USER_GPIO_PCI) |
|||
|
|||
static void vhost_user_gpio_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) |
|||
{ |
|||
VHostUserGPIOPCI *dev = VHOST_USER_GPIO_PCI(vpci_dev); |
|||
DeviceState *vdev = DEVICE(&dev->vdev); |
|||
|
|||
vpci_dev->nvectors = 1; |
|||
qdev_realize(vdev, BUS(&vpci_dev->bus), errp); |
|||
} |
|||
|
|||
static void vhost_user_gpio_pci_class_init(ObjectClass *klass, void *data) |
|||
{ |
|||
DeviceClass *dc = DEVICE_CLASS(klass); |
|||
VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); |
|||
PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); |
|||
k->realize = vhost_user_gpio_pci_realize; |
|||
set_bit(DEVICE_CATEGORY_INPUT, dc->categories); |
|||
pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; |
|||
pcidev_k->device_id = 0; /* Set by virtio-pci based on virtio id */ |
|||
pcidev_k->revision = 0x00; |
|||
pcidev_k->class_id = PCI_CLASS_COMMUNICATION_OTHER; |
|||
} |
|||
|
|||
static void vhost_user_gpio_pci_instance_init(Object *obj) |
|||
{ |
|||
VHostUserGPIOPCI *dev = VHOST_USER_GPIO_PCI(obj); |
|||
|
|||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), |
|||
TYPE_VHOST_USER_GPIO); |
|||
} |
|||
|
|||
static const VirtioPCIDeviceTypeInfo vhost_user_gpio_pci_info = { |
|||
.base_name = TYPE_VHOST_USER_GPIO_PCI, |
|||
.non_transitional_name = "vhost-user-gpio-pci", |
|||
.instance_size = sizeof(VHostUserGPIOPCI), |
|||
.instance_init = vhost_user_gpio_pci_instance_init, |
|||
.class_init = vhost_user_gpio_pci_class_init, |
|||
}; |
|||
|
|||
static void vhost_user_gpio_pci_register(void) |
|||
{ |
|||
virtio_pci_types_register(&vhost_user_gpio_pci_info); |
|||
} |
|||
|
|||
type_init(vhost_user_gpio_pci_register); |
|||
@ -0,0 +1,411 @@ |
|||
/*
|
|||
* Vhost-user GPIO virtio device |
|||
* |
|||
* Copyright (c) 2022 Viresh Kumar <viresh.kumar@linaro.org> |
|||
* |
|||
* SPDX-License-Identifier: GPL-2.0-or-later |
|||
*/ |
|||
|
|||
#include "qemu/osdep.h" |
|||
#include "qapi/error.h" |
|||
#include "hw/qdev-properties.h" |
|||
#include "hw/virtio/virtio-bus.h" |
|||
#include "hw/virtio/vhost-user-gpio.h" |
|||
#include "qemu/error-report.h" |
|||
#include "standard-headers/linux/virtio_ids.h" |
|||
#include "trace.h" |
|||
|
|||
#define REALIZE_CONNECTION_RETRIES 3 |
|||
|
|||
/* Features required from VirtIO */ |
|||
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, |
|||
VHOST_INVALID_FEATURE_BIT |
|||
}; |
|||
|
|||
static void vu_gpio_get_config(VirtIODevice *vdev, uint8_t *config) |
|||
{ |
|||
VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); |
|||
|
|||
memcpy(config, &gpio->config, sizeof(gpio->config)); |
|||
} |
|||
|
|||
static int vu_gpio_config_notifier(struct vhost_dev *dev) |
|||
{ |
|||
VHostUserGPIO *gpio = VHOST_USER_GPIO(dev->vdev); |
|||
|
|||
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) |
|||
{ |
|||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); |
|||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); |
|||
VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); |
|||
struct vhost_dev *vhost_dev = &gpio->vhost_dev; |
|||
int ret, i; |
|||
|
|||
if (!k->set_guest_notifiers) { |
|||
error_report("binding does not support guest notifiers"); |
|||
return -ENOSYS; |
|||
} |
|||
|
|||
ret = vhost_dev_enable_notifiers(vhost_dev, vdev); |
|||
if (ret < 0) { |
|||
error_report("Error enabling host notifiers: %d", ret); |
|||
return ret; |
|||
} |
|||
|
|||
ret = k->set_guest_notifiers(qbus->parent, vhost_dev->nvqs, true); |
|||
if (ret < 0) { |
|||
error_report("Error binding guest notifier: %d", ret); |
|||
goto err_host_notifiers; |
|||
} |
|||
|
|||
/*
|
|||
* Before we start up we need to ensure we have the final feature |
|||
* set needed for the vhost configuration. The backend may also |
|||
* apply backend_features when the feature set is sent. |
|||
*/ |
|||
vhost_ack_features(&gpio->vhost_dev, feature_bits, vdev->guest_features); |
|||
|
|||
ret = vhost_dev_start(&gpio->vhost_dev, vdev); |
|||
if (ret < 0) { |
|||
error_report("Error starting vhost-user-gpio: %d", 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 < gpio->vhost_dev.nvqs; i++) { |
|||
vhost_virtqueue_mask(&gpio->vhost_dev, vdev, i, false); |
|||
} |
|||
|
|||
/*
|
|||
* As we must have VHOST_USER_F_PROTOCOL_FEATURES (because |
|||
* VHOST_USER_GET_CONFIG requires it) we need to explicitly enable |
|||
* the vrings. |
|||
*/ |
|||
g_assert(vhost_dev->vhost_ops && |
|||
vhost_dev->vhost_ops->vhost_set_vring_enable); |
|||
ret = vhost_dev->vhost_ops->vhost_set_vring_enable(vhost_dev, true); |
|||
if (ret == 0) { |
|||
return 0; |
|||
} |
|||
|
|||
error_report("Failed to start vrings for vhost-user-gpio: %d", ret); |
|||
|
|||
err_guest_notifiers: |
|||
k->set_guest_notifiers(qbus->parent, gpio->vhost_dev.nvqs, false); |
|||
err_host_notifiers: |
|||
vhost_dev_disable_notifiers(&gpio->vhost_dev, vdev); |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
static void vu_gpio_stop(VirtIODevice *vdev) |
|||
{ |
|||
VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); |
|||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); |
|||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); |
|||
struct vhost_dev *vhost_dev = &gpio->vhost_dev; |
|||
int ret; |
|||
|
|||
if (!k->set_guest_notifiers) { |
|||
return; |
|||
} |
|||
|
|||
/*
|
|||
* We can call vu_gpio_stop multiple times, for example from |
|||
* vm_state_notify and the final object finalisation. Check we |
|||
* aren't already stopped before doing so. |
|||
*/ |
|||
if (!vhost_dev_is_started(vhost_dev)) { |
|||
return; |
|||
} |
|||
|
|||
vhost_dev_stop(vhost_dev, vdev); |
|||
|
|||
ret = k->set_guest_notifiers(qbus->parent, vhost_dev->nvqs, false); |
|||
if (ret < 0) { |
|||
error_report("vhost guest notifier cleanup failed: %d", ret); |
|||
return; |
|||
} |
|||
|
|||
vhost_dev_disable_notifiers(vhost_dev, vdev); |
|||
} |
|||
|
|||
static void vu_gpio_set_status(VirtIODevice *vdev, uint8_t status) |
|||
{ |
|||
VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); |
|||
bool should_start = virtio_device_started(vdev, status); |
|||
|
|||
trace_virtio_gpio_set_status(status); |
|||
|
|||
if (!gpio->connected) { |
|||
return; |
|||
} |
|||
|
|||
if (vhost_dev_is_started(&gpio->vhost_dev) == should_start) { |
|||
return; |
|||
} |
|||
|
|||
if (should_start) { |
|||
if (vu_gpio_start(vdev)) { |
|||
qemu_chr_fe_disconnect(&gpio->chardev); |
|||
} |
|||
} else { |
|||
vu_gpio_stop(vdev); |
|||
} |
|||
} |
|||
|
|||
static uint64_t vu_gpio_get_features(VirtIODevice *vdev, uint64_t features, |
|||
Error **errp) |
|||
{ |
|||
VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); |
|||
|
|||
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. |
|||
*/ |
|||
} |
|||
|
|||
static void vu_gpio_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask) |
|||
{ |
|||
VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); |
|||
|
|||
vhost_virtqueue_mask(&gpio->vhost_dev, vdev, idx, mask); |
|||
} |
|||
|
|||
static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserGPIO *gpio) |
|||
{ |
|||
virtio_delete_queue(gpio->command_vq); |
|||
virtio_delete_queue(gpio->interrupt_vq); |
|||
g_free(gpio->vhost_dev.vqs); |
|||
gpio->vhost_dev.vqs = NULL; |
|||
virtio_cleanup(vdev); |
|||
vhost_user_cleanup(&gpio->vhost_user); |
|||
} |
|||
|
|||
static int vu_gpio_connect(DeviceState *dev, Error **errp) |
|||
{ |
|||
VirtIODevice *vdev = VIRTIO_DEVICE(dev); |
|||
VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); |
|||
struct vhost_dev *vhost_dev = &gpio->vhost_dev; |
|||
int ret; |
|||
|
|||
if (gpio->connected) { |
|||
return 0; |
|||
} |
|||
gpio->connected = true; |
|||
|
|||
vhost_dev_set_config_notifier(vhost_dev, &gpio_ops); |
|||
gpio->vhost_user.supports_config = true; |
|||
|
|||
ret = vhost_dev_init(vhost_dev, &gpio->vhost_user, |
|||
VHOST_BACKEND_TYPE_USER, 0, errp); |
|||
if (ret < 0) { |
|||
return ret; |
|||
} |
|||
|
|||
/* restore vhost state */ |
|||
if (virtio_device_started(vdev, vdev->status)) { |
|||
vu_gpio_start(vdev); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
static void vu_gpio_disconnect(DeviceState *dev) |
|||
{ |
|||
VirtIODevice *vdev = VIRTIO_DEVICE(dev); |
|||
VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); |
|||
|
|||
if (!gpio->connected) { |
|||
return; |
|||
} |
|||
gpio->connected = false; |
|||
|
|||
vu_gpio_stop(vdev); |
|||
vhost_dev_cleanup(&gpio->vhost_dev); |
|||
} |
|||
|
|||
static void vu_gpio_event(void *opaque, QEMUChrEvent event) |
|||
{ |
|||
DeviceState *dev = opaque; |
|||
VirtIODevice *vdev = VIRTIO_DEVICE(dev); |
|||
VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); |
|||
Error *local_err = NULL; |
|||
|
|||
switch (event) { |
|||
case CHR_EVENT_OPENED: |
|||
if (vu_gpio_connect(dev, &local_err) < 0) { |
|||
qemu_chr_fe_disconnect(&gpio->chardev); |
|||
return; |
|||
} |
|||
break; |
|||
case CHR_EVENT_CLOSED: |
|||
vu_gpio_disconnect(dev); |
|||
break; |
|||
case CHR_EVENT_BREAK: |
|||
case CHR_EVENT_MUX_IN: |
|||
case CHR_EVENT_MUX_OUT: |
|||
/* Ignore */ |
|||
break; |
|||
} |
|||
} |
|||
|
|||
static int vu_gpio_realize_connect(VHostUserGPIO *gpio, Error **errp) |
|||
{ |
|||
VirtIODevice *vdev = &gpio->parent_obj; |
|||
DeviceState *dev = &vdev->parent_obj; |
|||
struct vhost_dev *vhost_dev = &gpio->vhost_dev; |
|||
int ret; |
|||
|
|||
ret = qemu_chr_fe_wait_connected(&gpio->chardev, errp); |
|||
if (ret < 0) { |
|||
return ret; |
|||
} |
|||
|
|||
/*
|
|||
* vu_gpio_connect() may have already connected (via the event |
|||
* callback) in which case it will just report success. |
|||
*/ |
|||
ret = vu_gpio_connect(dev, errp); |
|||
if (ret < 0) { |
|||
qemu_chr_fe_disconnect(&gpio->chardev); |
|||
return ret; |
|||
} |
|||
g_assert(gpio->connected); |
|||
|
|||
ret = vhost_dev_get_config(vhost_dev, (uint8_t *)&gpio->config, |
|||
sizeof(gpio->config), errp); |
|||
|
|||
if (ret < 0) { |
|||
error_report("vhost-user-gpio: get config failed"); |
|||
|
|||
qemu_chr_fe_disconnect(&gpio->chardev); |
|||
vhost_dev_cleanup(vhost_dev); |
|||
return ret; |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
static void vu_gpio_device_realize(DeviceState *dev, Error **errp) |
|||
{ |
|||
ERRP_GUARD(); |
|||
|
|||
VirtIODevice *vdev = VIRTIO_DEVICE(dev); |
|||
VHostUserGPIO *gpio = VHOST_USER_GPIO(dev); |
|||
int retries, ret; |
|||
|
|||
if (!gpio->chardev.chr) { |
|||
error_setg(errp, "vhost-user-gpio: chardev is mandatory"); |
|||
return; |
|||
} |
|||
|
|||
if (!vhost_user_init(&gpio->vhost_user, &gpio->chardev, errp)) { |
|||
return; |
|||
} |
|||
|
|||
virtio_init(vdev, VIRTIO_ID_GPIO, sizeof(gpio->config)); |
|||
|
|||
gpio->vhost_dev.nvqs = 2; |
|||
gpio->command_vq = virtio_add_queue(vdev, 256, vu_gpio_handle_output); |
|||
gpio->interrupt_vq = virtio_add_queue(vdev, 256, vu_gpio_handle_output); |
|||
gpio->vhost_dev.vqs = g_new0(struct vhost_virtqueue, gpio->vhost_dev.nvqs); |
|||
|
|||
gpio->connected = false; |
|||
|
|||
qemu_chr_fe_set_handlers(&gpio->chardev, NULL, NULL, vu_gpio_event, NULL, |
|||
dev, NULL, true); |
|||
|
|||
retries = REALIZE_CONNECTION_RETRIES; |
|||
g_assert(!*errp); |
|||
do { |
|||
if (*errp) { |
|||
error_prepend(errp, "Reconnecting after error: "); |
|||
error_report_err(*errp); |
|||
*errp = NULL; |
|||
} |
|||
ret = vu_gpio_realize_connect(gpio, errp); |
|||
} while (ret < 0 && retries--); |
|||
|
|||
if (ret < 0) { |
|||
do_vhost_user_cleanup(vdev, gpio); |
|||
} |
|||
|
|||
return; |
|||
} |
|||
|
|||
static void vu_gpio_device_unrealize(DeviceState *dev) |
|||
{ |
|||
VirtIODevice *vdev = VIRTIO_DEVICE(dev); |
|||
VHostUserGPIO *gpio = VHOST_USER_GPIO(dev); |
|||
|
|||
vu_gpio_set_status(vdev, 0); |
|||
qemu_chr_fe_set_handlers(&gpio->chardev, NULL, NULL, NULL, NULL, NULL, NULL, |
|||
false); |
|||
vhost_dev_cleanup(&gpio->vhost_dev); |
|||
do_vhost_user_cleanup(vdev, gpio); |
|||
} |
|||
|
|||
static const VMStateDescription vu_gpio_vmstate = { |
|||
.name = "vhost-user-gpio", |
|||
.unmigratable = 1, |
|||
}; |
|||
|
|||
static Property vu_gpio_properties[] = { |
|||
DEFINE_PROP_CHR("chardev", VHostUserGPIO, chardev), |
|||
DEFINE_PROP_END_OF_LIST(), |
|||
}; |
|||
|
|||
static void vu_gpio_class_init(ObjectClass *klass, void *data) |
|||
{ |
|||
DeviceClass *dc = DEVICE_CLASS(klass); |
|||
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); |
|||
|
|||
device_class_set_props(dc, vu_gpio_properties); |
|||
dc->vmsd = &vu_gpio_vmstate; |
|||
set_bit(DEVICE_CATEGORY_INPUT, dc->categories); |
|||
vdc->realize = vu_gpio_device_realize; |
|||
vdc->unrealize = vu_gpio_device_unrealize; |
|||
vdc->get_features = vu_gpio_get_features; |
|||
vdc->get_config = vu_gpio_get_config; |
|||
vdc->set_status = vu_gpio_set_status; |
|||
vdc->guest_notifier_mask = vu_gpio_guest_notifier_mask; |
|||
} |
|||
|
|||
static const TypeInfo vu_gpio_info = { |
|||
.name = TYPE_VHOST_USER_GPIO, |
|||
.parent = TYPE_VIRTIO_DEVICE, |
|||
.instance_size = sizeof(VHostUserGPIO), |
|||
.class_init = vu_gpio_class_init, |
|||
}; |
|||
|
|||
static void vu_gpio_register_types(void) |
|||
{ |
|||
type_register_static(&vu_gpio_info); |
|||
} |
|||
|
|||
type_init(vu_gpio_register_types) |
|||
@ -0,0 +1,42 @@ |
|||
#include "qemu/osdep.h" |
|||
#include "qapi/error.h" |
|||
#include "qapi/qapi-commands-virtio.h" |
|||
|
|||
static void *qmp_virtio_unsupported(Error **errp) |
|||
{ |
|||
error_setg(errp, "Virtio is disabled"); |
|||
return NULL; |
|||
} |
|||
|
|||
VirtioInfoList *qmp_x_query_virtio(Error **errp) |
|||
{ |
|||
return qmp_virtio_unsupported(errp); |
|||
} |
|||
|
|||
VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp) |
|||
{ |
|||
return qmp_virtio_unsupported(errp); |
|||
} |
|||
|
|||
VirtVhostQueueStatus *qmp_x_query_virtio_vhost_queue_status(const char *path, |
|||
uint16_t queue, |
|||
Error **errp) |
|||
{ |
|||
return qmp_virtio_unsupported(errp); |
|||
} |
|||
|
|||
VirtQueueStatus *qmp_x_query_virtio_queue_status(const char *path, |
|||
uint16_t queue, |
|||
Error **errp) |
|||
{ |
|||
return qmp_virtio_unsupported(errp); |
|||
} |
|||
|
|||
VirtioQueueElement *qmp_x_query_virtio_queue_element(const char *path, |
|||
uint16_t queue, |
|||
bool has_index, |
|||
uint16_t index, |
|||
Error **errp) |
|||
{ |
|||
return qmp_virtio_unsupported(errp); |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,35 @@ |
|||
/*
|
|||
* Vhost-user GPIO virtio device |
|||
* |
|||
* Copyright (c) 2021 Viresh Kumar <viresh.kumar@linaro.org> |
|||
* |
|||
* SPDX-License-Identifier: GPL-2.0-or-later |
|||
*/ |
|||
|
|||
#ifndef _QEMU_VHOST_USER_GPIO_H |
|||
#define _QEMU_VHOST_USER_GPIO_H |
|||
|
|||
#include "hw/virtio/virtio.h" |
|||
#include "hw/virtio/vhost.h" |
|||
#include "hw/virtio/vhost-user.h" |
|||
#include "standard-headers/linux/virtio_gpio.h" |
|||
#include "chardev/char-fe.h" |
|||
|
|||
#define TYPE_VHOST_USER_GPIO "vhost-user-gpio-device" |
|||
OBJECT_DECLARE_SIMPLE_TYPE(VHostUserGPIO, VHOST_USER_GPIO); |
|||
|
|||
struct VHostUserGPIO { |
|||
/*< private >*/ |
|||
VirtIODevice parent_obj; |
|||
CharBackend chardev; |
|||
struct virtio_gpio_config config; |
|||
struct vhost_virtqueue *vhost_vq; |
|||
struct vhost_dev vhost_dev; |
|||
VhostUserState vhost_user; |
|||
VirtQueue *command_vq; |
|||
VirtQueue *interrupt_vq; |
|||
bool connected; |
|||
/*< public >*/ |
|||
}; |
|||
|
|||
#endif /* _QEMU_VHOST_USER_GPIO_H */ |
|||
@ -0,0 +1,20 @@ |
|||
/*
|
|||
* Virtio Block Device common helpers |
|||
* |
|||
* 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 VIRTIO_BLK_COMMON_H |
|||
#define VIRTIO_BLK_COMMON_H |
|||
|
|||
#include "hw/virtio/virtio.h" |
|||
|
|||
extern const VirtIOConfigSizeParams virtio_blk_cfg_size_params; |
|||
|
|||
#endif |
|||
@ -0,0 +1,954 @@ |
|||
# -*- Mode: Python -*- |
|||
# vim: filetype=python |
|||
# |
|||
|
|||
## |
|||
# = Virtio devices |
|||
## |
|||
|
|||
## |
|||
# @VirtioInfo: |
|||
# |
|||
# Basic information about a given VirtIODevice |
|||
# |
|||
# @path: The VirtIODevice's canonical QOM path |
|||
# |
|||
# @name: Name of the VirtIODevice |
|||
# |
|||
# Since: 7.1 |
|||
# |
|||
## |
|||
{ 'struct': 'VirtioInfo', |
|||
'data': { 'path': 'str', |
|||
'name': 'str' } } |
|||
|
|||
## |
|||
# @x-query-virtio: |
|||
# |
|||
# Returns a list of all realized VirtIODevices |
|||
# |
|||
# Features: |
|||
# @unstable: This command is meant for debugging. |
|||
# |
|||
# Returns: List of gathered VirtIODevices |
|||
# |
|||
# Since: 7.1 |
|||
# |
|||
# Example: |
|||
# |
|||
# -> { "execute": "x-query-virtio" } |
|||
# <- { "return": [ |
|||
# { |
|||
# "name": "virtio-input", |
|||
# "path": "/machine/peripheral-anon/device[4]/virtio-backend" |
|||
# }, |
|||
# { |
|||
# "name": "virtio-crypto", |
|||
# "path": "/machine/peripheral/crypto0/virtio-backend" |
|||
# }, |
|||
# { |
|||
# "name": "virtio-scsi", |
|||
# "path": "/machine/peripheral-anon/device[2]/virtio-backend" |
|||
# }, |
|||
# { |
|||
# "name": "virtio-net", |
|||
# "path": "/machine/peripheral-anon/device[1]/virtio-backend" |
|||
# }, |
|||
# { |
|||
# "name": "virtio-serial", |
|||
# "path": "/machine/peripheral-anon/device[0]/virtio-backend" |
|||
# } |
|||
# ] |
|||
# } |
|||
# |
|||
## |
|||
|
|||
{ 'command': 'x-query-virtio', |
|||
'returns': [ 'VirtioInfo' ], |
|||
'features': [ 'unstable' ] } |
|||
|
|||
## |
|||
# @VhostStatus: |
|||
# |
|||
# Information about a vhost device. This information will only be |
|||
# displayed if the vhost device is active. |
|||
# |
|||
# @n-mem-sections: vhost_dev n_mem_sections |
|||
# |
|||
# @n-tmp-sections: vhost_dev n_tmp_sections |
|||
# |
|||
# @nvqs: vhost_dev nvqs (number of virtqueues being used) |
|||
# |
|||
# @vq-index: vhost_dev vq_index |
|||
# |
|||
# @features: vhost_dev features |
|||
# |
|||
# @acked-features: vhost_dev acked_features |
|||
# |
|||
# @backend-features: vhost_dev backend_features |
|||
# |
|||
# @protocol-features: vhost_dev protocol_features |
|||
# |
|||
# @max-queues: vhost_dev max_queues |
|||
# |
|||
# @backend-cap: vhost_dev backend_cap |
|||
# |
|||
# @log-enabled: vhost_dev log_enabled flag |
|||
# |
|||
# @log-size: vhost_dev log_size |
|||
# |
|||
# Since: 7.1 |
|||
# |
|||
## |
|||
|
|||
{ 'struct': 'VhostStatus', |
|||
'data': { 'n-mem-sections': 'int', |
|||
'n-tmp-sections': 'int', |
|||
'nvqs': 'uint32', |
|||
'vq-index': 'int', |
|||
'features': 'VirtioDeviceFeatures', |
|||
'acked-features': 'VirtioDeviceFeatures', |
|||
'backend-features': 'VirtioDeviceFeatures', |
|||
'protocol-features': 'VhostDeviceProtocols', |
|||
'max-queues': 'uint64', |
|||
'backend-cap': 'uint64', |
|||
'log-enabled': 'bool', |
|||
'log-size': 'uint64' } } |
|||
|
|||
## |
|||
# @VirtioStatus: |
|||
# |
|||
# Full status of the virtio device with most VirtIODevice members. |
|||
# Also includes the full status of the corresponding vhost device |
|||
# if the vhost device is active. |
|||
# |
|||
# @name: VirtIODevice name |
|||
# |
|||
# @device-id: VirtIODevice ID |
|||
# |
|||
# @vhost-started: VirtIODevice vhost_started flag |
|||
# |
|||
# @guest-features: VirtIODevice guest_features |
|||
# |
|||
# @host-features: VirtIODevice host_features |
|||
# |
|||
# @backend-features: VirtIODevice backend_features |
|||
# |
|||
# @device-endian: VirtIODevice device_endian |
|||
# |
|||
# @num-vqs: VirtIODevice virtqueue count. This is the number of active |
|||
# virtqueues being used by the VirtIODevice. |
|||
# |
|||
# @status: VirtIODevice configuration status (VirtioDeviceStatus) |
|||
# |
|||
# @isr: VirtIODevice ISR |
|||
# |
|||
# @queue-sel: VirtIODevice queue_sel |
|||
# |
|||
# @vm-running: VirtIODevice vm_running flag |
|||
# |
|||
# @broken: VirtIODevice broken flag |
|||
# |
|||
# @disabled: VirtIODevice disabled flag |
|||
# |
|||
# @use-started: VirtIODevice use_started flag |
|||
# |
|||
# @started: VirtIODevice started flag |
|||
# |
|||
# @start-on-kick: VirtIODevice start_on_kick flag |
|||
# |
|||
# @disable-legacy-check: VirtIODevice disabled_legacy_check flag |
|||
# |
|||
# @bus-name: VirtIODevice bus_name |
|||
# |
|||
# @use-guest-notifier-mask: VirtIODevice use_guest_notifier_mask flag |
|||
# |
|||
# @vhost-dev: Corresponding vhost device info for a given VirtIODevice. |
|||
# Present if the given VirtIODevice has an active vhost |
|||
# device. |
|||
# |
|||
# Since: 7.1 |
|||
# |
|||
## |
|||
|
|||
{ 'struct': 'VirtioStatus', |
|||
'data': { 'name': 'str', |
|||
'device-id': 'uint16', |
|||
'vhost-started': 'bool', |
|||
'device-endian': 'str', |
|||
'guest-features': 'VirtioDeviceFeatures', |
|||
'host-features': 'VirtioDeviceFeatures', |
|||
'backend-features': 'VirtioDeviceFeatures', |
|||
'num-vqs': 'int', |
|||
'status': 'VirtioDeviceStatus', |
|||
'isr': 'uint8', |
|||
'queue-sel': 'uint16', |
|||
'vm-running': 'bool', |
|||
'broken': 'bool', |
|||
'disabled': 'bool', |
|||
'use-started': 'bool', |
|||
'started': 'bool', |
|||
'start-on-kick': 'bool', |
|||
'disable-legacy-check': 'bool', |
|||
'bus-name': 'str', |
|||
'use-guest-notifier-mask': 'bool', |
|||
'*vhost-dev': 'VhostStatus' } } |
|||
|
|||
## |
|||
# @x-query-virtio-status: |
|||
# |
|||
# Poll for a comprehensive status of a given virtio device |
|||
# |
|||
# @path: Canonical QOM path of the VirtIODevice |
|||
# |
|||
# Features: |
|||
# @unstable: This command is meant for debugging. |
|||
# |
|||
# Returns: VirtioStatus of the virtio device |
|||
# |
|||
# Since: 7.1 |
|||
# |
|||
# Examples: |
|||
# |
|||
# 1. Poll for the status of virtio-crypto (no vhost-crypto active) |
|||
# |
|||
# -> { "execute": "x-query-virtio-status", |
|||
# "arguments": { "path": "/machine/peripheral/crypto0/virtio-backend" } |
|||
# } |
|||
# <- { "return": { |
|||
# "device-endian": "little", |
|||
# "bus-name": "", |
|||
# "disable-legacy-check": false, |
|||
# "name": "virtio-crypto", |
|||
# "started": true, |
|||
# "device-id": 20, |
|||
# "backend-features": { |
|||
# "transports": [], |
|||
# "dev-features": [] |
|||
# }, |
|||
# "start-on-kick": false, |
|||
# "isr": 1, |
|||
# "broken": false, |
|||
# "status": { |
|||
# "statuses": [ |
|||
# "VIRTIO_CONFIG_S_ACKNOWLEDGE: Valid virtio device found", |
|||
# "VIRTIO_CONFIG_S_DRIVER: Guest OS compatible with device", |
|||
# "VIRTIO_CONFIG_S_FEATURES_OK: Feature negotiation complete", |
|||
# "VIRTIO_CONFIG_S_DRIVER_OK: Driver setup and ready" |
|||
# ] |
|||
# }, |
|||
# "num-vqs": 2, |
|||
# "guest-features": { |
|||
# "dev-features": [], |
|||
# "transports": [ |
|||
# "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled", |
|||
# "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported", |
|||
# "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)" |
|||
# ] |
|||
# }, |
|||
# "host-features": { |
|||
# "unknown-dev-features": 1073741824, |
|||
# "dev-features": [], |
|||
# "transports": [ |
|||
# "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled", |
|||
# "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported", |
|||
# "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)", |
|||
# "VIRTIO_F_ANY_LAYOUT: Device accepts arbitrary desc. layouts", |
|||
# "VIRTIO_F_NOTIFY_ON_EMPTY: Notify when device runs out of avail. descs. on VQ" |
|||
# ] |
|||
# }, |
|||
# "use-guest-notifier-mask": true, |
|||
# "vm-running": true, |
|||
# "queue-sel": 1, |
|||
# "disabled": false, |
|||
# "vhost-started": false, |
|||
# "use-started": true |
|||
# } |
|||
# } |
|||
# |
|||
# 2. Poll for the status of virtio-net (vhost-net is active) |
|||
# |
|||
# -> { "execute": "x-query-virtio-status", |
|||
# "arguments": { "path": "/machine/peripheral-anon/device[1]/virtio-backend" } |
|||
# } |
|||
# <- { "return": { |
|||
# "device-endian": "little", |
|||
# "bus-name": "", |
|||
# "disabled-legacy-check": false, |
|||
# "name": "virtio-net", |
|||
# "started": true, |
|||
# "device-id": 1, |
|||
# "vhost-dev": { |
|||
# "n-tmp-sections": 4, |
|||
# "n-mem-sections": 4, |
|||
# "max-queues": 1, |
|||
# "backend-cap": 2, |
|||
# "log-size": 0, |
|||
# "backend-features": { |
|||
# "dev-features": [], |
|||
# "transports": [] |
|||
# }, |
|||
# "nvqs": 2, |
|||
# "protocol-features": { |
|||
# "protocols": [] |
|||
# }, |
|||
# "vq-index": 0, |
|||
# "log-enabled": false, |
|||
# "acked-features": { |
|||
# "dev-features": [ |
|||
# "VIRTIO_NET_F_MRG_RXBUF: Driver can merge receive buffers" |
|||
# ], |
|||
# "transports": [ |
|||
# "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled", |
|||
# "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported", |
|||
# "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)" |
|||
# ] |
|||
# }, |
|||
# "features": { |
|||
# "dev-features": [ |
|||
# "VHOST_F_LOG_ALL: Logging write descriptors supported", |
|||
# "VIRTIO_NET_F_MRG_RXBUF: Driver can merge receive buffers" |
|||
# ], |
|||
# "transports": [ |
|||
# "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled", |
|||
# "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported", |
|||
# "VIRTIO_F_IOMMU_PLATFORM: Device can be used on IOMMU platform", |
|||
# "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)", |
|||
# "VIRTIO_F_ANY_LAYOUT: Device accepts arbitrary desc. layouts", |
|||
# "VIRTIO_F_NOTIFY_ON_EMPTY: Notify when device runs out of avail. descs. on VQ" |
|||
# ] |
|||
# } |
|||
# }, |
|||
# "backend-features": { |
|||
# "dev-features": [ |
|||
# "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features negotation supported", |
|||
# "VIRTIO_NET_F_GSO: Handling GSO-type packets supported", |
|||
# "VIRTIO_NET_F_CTRL_MAC_ADDR: MAC address set through control channel", |
|||
# "VIRTIO_NET_F_GUEST_ANNOUNCE: Driver sending gratuitous packets supported", |
|||
# "VIRTIO_NET_F_CTRL_RX_EXTRA: Extra RX mode control supported", |
|||
# "VIRTIO_NET_F_CTRL_VLAN: Control channel VLAN filtering supported", |
|||
# "VIRTIO_NET_F_CTRL_RX: Control channel RX mode supported", |
|||
# "VIRTIO_NET_F_CTRL_VQ: Control channel available", |
|||
# "VIRTIO_NET_F_STATUS: Configuration status field available", |
|||
# "VIRTIO_NET_F_MRG_RXBUF: Driver can merge receive buffers", |
|||
# "VIRTIO_NET_F_HOST_UFO: Device can receive UFO", |
|||
# "VIRTIO_NET_F_HOST_ECN: Device can receive TSO with ECN", |
|||
# "VIRTIO_NET_F_HOST_TSO6: Device can receive TSOv6", |
|||
# "VIRTIO_NET_F_HOST_TSO4: Device can receive TSOv4", |
|||
# "VIRTIO_NET_F_GUEST_UFO: Driver can receive UFO", |
|||
# "VIRTIO_NET_F_GUEST_ECN: Driver can receive TSO with ECN", |
|||
# "VIRTIO_NET_F_GUEST_TSO6: Driver can receive TSOv6", |
|||
# "VIRTIO_NET_F_GUEST_TSO4: Driver can receive TSOv4", |
|||
# "VIRTIO_NET_F_MAC: Device has given MAC address", |
|||
# "VIRTIO_NET_F_CTRL_GUEST_OFFLOADS: Control channel offloading reconfig. supported", |
|||
# "VIRTIO_NET_F_GUEST_CSUM: Driver handling packets with partial checksum supported", |
|||
# "VIRTIO_NET_F_CSUM: Device handling packets with partial checksum supported" |
|||
# ], |
|||
# "transports": [ |
|||
# "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled", |
|||
# "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported", |
|||
# "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)", |
|||
# "VIRTIO_F_ANY_LAYOUT: Device accepts arbitrary desc. layouts", |
|||
# "VIRTIO_F_NOTIFY_ON_EMPTY: Notify when device runs out of avail. descs. on VQ" |
|||
# ] |
|||
# }, |
|||
# "start-on-kick": false, |
|||
# "isr": 1, |
|||
# "broken": false, |
|||
# "status": { |
|||
# "statuses": [ |
|||
# "VIRTIO_CONFIG_S_ACKNOWLEDGE: Valid virtio device found", |
|||
# "VIRTIO_CONFIG_S_DRIVER: Guest OS compatible with device", |
|||
# "VIRTIO_CONFIG_S_FEATURES_OK: Feature negotiation complete", |
|||
# "VIRTIO_CONFIG_S_DRIVER_OK: Driver setup and ready" |
|||
# ] |
|||
# }, |
|||
# "num-vqs": 3, |
|||
# "guest-features": { |
|||
# "dev-features": [ |
|||
# "VIRTIO_NET_F_CTRL_MAC_ADDR: MAC address set through control channel", |
|||
# "VIRTIO_NET_F_GUEST_ANNOUNCE: Driver sending gratuitous packets supported", |
|||
# "VIRTIO_NET_F_CTRL_VLAN: Control channel VLAN filtering supported", |
|||
# "VIRTIO_NET_F_CTRL_RX: Control channel RX mode supported", |
|||
# "VIRTIO_NET_F_CTRL_VQ: Control channel available", |
|||
# "VIRTIO_NET_F_STATUS: Configuration status field available", |
|||
# "VIRTIO_NET_F_MRG_RXBUF: Driver can merge receive buffers", |
|||
# "VIRTIO_NET_F_HOST_UFO: Device can receive UFO", |
|||
# "VIRTIO_NET_F_HOST_ECN: Device can receive TSO with ECN", |
|||
# "VIRTIO_NET_F_HOST_TSO6: Device can receive TSOv6", |
|||
# "VIRTIO_NET_F_HOST_TSO4: Device can receive TSOv4", |
|||
# "VIRTIO_NET_F_GUEST_UFO: Driver can receive UFO", |
|||
# "VIRTIO_NET_F_GUEST_ECN: Driver can receive TSO with ECN", |
|||
# "VIRTIO_NET_F_GUEST_TSO6: Driver can receive TSOv6", |
|||
# "VIRTIO_NET_F_GUEST_TSO4: Driver can receive TSOv4", |
|||
# "VIRTIO_NET_F_MAC: Device has given MAC address", |
|||
# "VIRTIO_NET_F_CTRL_GUEST_OFFLOADS: Control channel offloading reconfig. supported", |
|||
# "VIRTIO_NET_F_GUEST_CSUM: Driver handling packets with partial checksum supported", |
|||
# "VIRTIO_NET_F_CSUM: Device handling packets with partial checksum supported" |
|||
# ], |
|||
# "transports": [ |
|||
# "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled", |
|||
# "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported", |
|||
# "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)" |
|||
# ] |
|||
# }, |
|||
# "host-features": { |
|||
# "dev-features": [ |
|||
# "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features negotation supported", |
|||
# "VIRTIO_NET_F_GSO: Handling GSO-type packets supported", |
|||
# "VIRTIO_NET_F_CTRL_MAC_ADDR: MAC address set through control channel", |
|||
# "VIRTIO_NET_F_GUEST_ANNOUNCE: Driver sending gratuitous packets supported", |
|||
# "VIRTIO_NET_F_CTRL_RX_EXTRA: Extra RX mode control supported", |
|||
# "VIRTIO_NET_F_CTRL_VLAN: Control channel VLAN filtering supported", |
|||
# "VIRTIO_NET_F_CTRL_RX: Control channel RX mode supported", |
|||
# "VIRTIO_NET_F_CTRL_VQ: Control channel available", |
|||
# "VIRTIO_NET_F_STATUS: Configuration status field available", |
|||
# "VIRTIO_NET_F_MRG_RXBUF: Driver can merge receive buffers", |
|||
# "VIRTIO_NET_F_HOST_UFO: Device can receive UFO", |
|||
# "VIRTIO_NET_F_HOST_ECN: Device can receive TSO with ECN", |
|||
# "VIRTIO_NET_F_HOST_TSO6: Device can receive TSOv6", |
|||
# "VIRTIO_NET_F_HOST_TSO4: Device can receive TSOv4", |
|||
# "VIRTIO_NET_F_GUEST_UFO: Driver can receive UFO", |
|||
# "VIRTIO_NET_F_GUEST_ECN: Driver can receive TSO with ECN", |
|||
# "VIRTIO_NET_F_GUEST_TSO6: Driver can receive TSOv6", |
|||
# "VIRTIO_NET_F_GUEST_TSO4: Driver can receive TSOv4", |
|||
# "VIRTIO_NET_F_MAC: Device has given MAC address", |
|||
# "VIRTIO_NET_F_CTRL_GUEST_OFFLOADS: Control channel offloading reconfig. supported", |
|||
# "VIRTIO_NET_F_GUEST_CSUM: Driver handling packets with partial checksum supported", |
|||
# "VIRTIO_NET_F_CSUM: Device handling packets with partial checksum supported" |
|||
# ], |
|||
# "transports": [ |
|||
# "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled", |
|||
# "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported", |
|||
# "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)", |
|||
# "VIRTIO_F_ANY_LAYOUT: Device accepts arbitrary desc. layouts", |
|||
# "VIRTIO_F_NOTIFY_ON_EMPTY: Notify when device runs out of avail. descs. on VQ" |
|||
# ] |
|||
# }, |
|||
# "use-guest-notifier-mask": true, |
|||
# "vm-running": true, |
|||
# "queue-sel": 2, |
|||
# "disabled": false, |
|||
# "vhost-started": true, |
|||
# "use-started": true |
|||
# } |
|||
# } |
|||
# |
|||
## |
|||
|
|||
{ 'command': 'x-query-virtio-status', |
|||
'data': { 'path': 'str' }, |
|||
'returns': 'VirtioStatus', |
|||
'features': [ 'unstable' ] } |
|||
|
|||
## |
|||
# @VirtioDeviceStatus: |
|||
# |
|||
# A structure defined to list the configuration statuses of a virtio |
|||
# device |
|||
# |
|||
# @statuses: List of decoded configuration statuses of the virtio |
|||
# device |
|||
# |
|||
# @unknown-statuses: Virtio device statuses bitmap that have not been decoded |
|||
# |
|||
# Since: 7.1 |
|||
## |
|||
|
|||
{ 'struct': 'VirtioDeviceStatus', |
|||
'data': { 'statuses': [ 'str' ], |
|||
'*unknown-statuses': 'uint8' } } |
|||
|
|||
## |
|||
# @VhostDeviceProtocols: |
|||
# |
|||
# A structure defined to list the vhost user protocol features of a |
|||
# Vhost User device |
|||
# |
|||
# @protocols: List of decoded vhost user protocol features of a vhost |
|||
# user device |
|||
# |
|||
# @unknown-protocols: Vhost user device protocol features bitmap that |
|||
# have not been decoded |
|||
# |
|||
# Since: 7.1 |
|||
## |
|||
|
|||
{ 'struct': 'VhostDeviceProtocols', |
|||
'data': { 'protocols': [ 'str' ], |
|||
'*unknown-protocols': 'uint64' } } |
|||
|
|||
## |
|||
# @VirtioDeviceFeatures: |
|||
# |
|||
# The common fields that apply to most Virtio devices. Some devices |
|||
# may not have their own device-specific features (e.g. virtio-rng). |
|||
# |
|||
# @transports: List of transport features of the virtio device |
|||
# |
|||
# @dev-features: List of device-specific features (if the device has |
|||
# unique features) |
|||
# |
|||
# @unknown-dev-features: Virtio device features bitmap that have not |
|||
# been decoded |
|||
# |
|||
# Since: 7.1 |
|||
## |
|||
|
|||
{ 'struct': 'VirtioDeviceFeatures', |
|||
'data': { 'transports': [ 'str' ], |
|||
'*dev-features': [ 'str' ], |
|||
'*unknown-dev-features': 'uint64' } } |
|||
|
|||
## |
|||
# @VirtQueueStatus: |
|||
# |
|||
# Information of a VirtIODevice VirtQueue, including most members of |
|||
# the VirtQueue data structure. |
|||
# |
|||
# @name: Name of the VirtIODevice that uses this VirtQueue |
|||
# |
|||
# @queue-index: VirtQueue queue_index |
|||
# |
|||
# @inuse: VirtQueue inuse |
|||
# |
|||
# @vring-num: VirtQueue vring.num |
|||
# |
|||
# @vring-num-default: VirtQueue vring.num_default |
|||
# |
|||
# @vring-align: VirtQueue vring.align |
|||
# |
|||
# @vring-desc: VirtQueue vring.desc (descriptor area) |
|||
# |
|||
# @vring-avail: VirtQueue vring.avail (driver area) |
|||
# |
|||
# @vring-used: VirtQueue vring.used (device area) |
|||
# |
|||
# @last-avail-idx: VirtQueue last_avail_idx or return of vhost_dev |
|||
# vhost_get_vring_base (if vhost active) |
|||
# |
|||
# @shadow-avail-idx: VirtQueue shadow_avail_idx |
|||
# |
|||
# @used-idx: VirtQueue used_idx |
|||
# |
|||
# @signalled-used: VirtQueue signalled_used |
|||
# |
|||
# @signalled-used-valid: VirtQueue signalled_used_valid flag |
|||
# |
|||
# Since: 7.1 |
|||
# |
|||
## |
|||
|
|||
{ 'struct': 'VirtQueueStatus', |
|||
'data': { 'name': 'str', |
|||
'queue-index': 'uint16', |
|||
'inuse': 'uint32', |
|||
'vring-num': 'uint32', |
|||
'vring-num-default': 'uint32', |
|||
'vring-align': 'uint32', |
|||
'vring-desc': 'uint64', |
|||
'vring-avail': 'uint64', |
|||
'vring-used': 'uint64', |
|||
'*last-avail-idx': 'uint16', |
|||
'*shadow-avail-idx': 'uint16', |
|||
'used-idx': 'uint16', |
|||
'signalled-used': 'uint16', |
|||
'signalled-used-valid': 'bool' } } |
|||
|
|||
## |
|||
# @x-query-virtio-queue-status: |
|||
# |
|||
# Return the status of a given VirtIODevice's VirtQueue |
|||
# |
|||
# @path: VirtIODevice canonical QOM path |
|||
# |
|||
# @queue: VirtQueue index to examine |
|||
# |
|||
# Features: |
|||
# @unstable: This command is meant for debugging. |
|||
# |
|||
# Returns: VirtQueueStatus of the VirtQueue |
|||
# |
|||
# Notes: last_avail_idx will not be displayed in the case where |
|||
# the selected VirtIODevice has a running vhost device and |
|||
# the VirtIODevice VirtQueue index (queue) does not exist for |
|||
# the corresponding vhost device vhost_virtqueue. Also, |
|||
# shadow_avail_idx will not be displayed in the case where |
|||
# the selected VirtIODevice has a running vhost device. |
|||
# |
|||
# Since: 7.1 |
|||
# |
|||
# Examples: |
|||
# |
|||
# 1. Get VirtQueueStatus for virtio-vsock (vhost-vsock running) |
|||
# |
|||
# -> { "execute": "x-query-virtio-queue-status", |
|||
# "arguments": { "path": "/machine/peripheral/vsock0/virtio-backend", |
|||
# "queue": 1 } |
|||
# } |
|||
# <- { "return": { |
|||
# "signalled-used": 0, |
|||
# "inuse": 0, |
|||
# "name": "vhost-vsock", |
|||
# "vring-align": 4096, |
|||
# "vring-desc": 5217370112, |
|||
# "signalled-used-valid": false, |
|||
# "vring-num-default": 128, |
|||
# "vring-avail": 5217372160, |
|||
# "queue-index": 1, |
|||
# "last-avail-idx": 0, |
|||
# "vring-used": 5217372480, |
|||
# "used-idx": 0, |
|||
# "vring-num": 128 |
|||
# } |
|||
# } |
|||
# |
|||
# 2. Get VirtQueueStatus for virtio-serial (no vhost) |
|||
# |
|||
# -> { "execute": "x-query-virtio-queue-status", |
|||
# "arguments": { "path": "/machine/peripheral-anon/device[0]/virtio-backend", |
|||
# "queue": 20 } |
|||
# } |
|||
# <- { "return": { |
|||
# "signalled-used": 0, |
|||
# "inuse": 0, |
|||
# "name": "virtio-serial", |
|||
# "vring-align": 4096, |
|||
# "vring-desc": 5182074880, |
|||
# "signalled-used-valid": false, |
|||
# "vring-num-default": 128, |
|||
# "vring-avail": 5182076928, |
|||
# "queue-index": 20, |
|||
# "last-avail-idx": 0, |
|||
# "vring-used": 5182077248, |
|||
# "used-idx": 0, |
|||
# "shadow-avail-idx": 0, |
|||
# "vring-num": 128 |
|||
# } |
|||
# } |
|||
# |
|||
## |
|||
|
|||
{ 'command': 'x-query-virtio-queue-status', |
|||
'data': { 'path': 'str', 'queue': 'uint16' }, |
|||
'returns': 'VirtQueueStatus', |
|||
'features': [ 'unstable' ] } |
|||
|
|||
## |
|||
# @VirtVhostQueueStatus: |
|||
# |
|||
# Information of a vhost device's vhost_virtqueue, including most |
|||
# members of the vhost_dev vhost_virtqueue data structure. |
|||
# |
|||
# @name: Name of the VirtIODevice that uses this vhost_virtqueue |
|||
# |
|||
# @kick: vhost_virtqueue kick |
|||
# |
|||
# @call: vhost_virtqueue call |
|||
# |
|||
# @desc: vhost_virtqueue desc |
|||
# |
|||
# @avail: vhost_virtqueue avail |
|||
# |
|||
# @used: vhost_virtqueue used |
|||
# |
|||
# @num: vhost_virtqueue num |
|||
# |
|||
# @desc-phys: vhost_virtqueue desc_phys (descriptor area phys. addr.) |
|||
# |
|||
# @desc-size: vhost_virtqueue desc_size |
|||
# |
|||
# @avail-phys: vhost_virtqueue avail_phys (driver area phys. addr.) |
|||
# |
|||
# @avail-size: vhost_virtqueue avail_size |
|||
# |
|||
# @used-phys: vhost_virtqueue used_phys (device area phys. addr.) |
|||
# |
|||
# @used-size: vhost_virtqueue used_size |
|||
# |
|||
# Since: 7.1 |
|||
# |
|||
## |
|||
|
|||
{ 'struct': 'VirtVhostQueueStatus', |
|||
'data': { 'name': 'str', |
|||
'kick': 'int', |
|||
'call': 'int', |
|||
'desc': 'uint64', |
|||
'avail': 'uint64', |
|||
'used': 'uint64', |
|||
'num': 'int', |
|||
'desc-phys': 'uint64', |
|||
'desc-size': 'uint32', |
|||
'avail-phys': 'uint64', |
|||
'avail-size': 'uint32', |
|||
'used-phys': 'uint64', |
|||
'used-size': 'uint32' } } |
|||
|
|||
## |
|||
# @x-query-virtio-vhost-queue-status: |
|||
# |
|||
# Return information of a given vhost device's vhost_virtqueue |
|||
# |
|||
# @path: VirtIODevice canonical QOM path |
|||
# |
|||
# @queue: vhost_virtqueue index to examine |
|||
# |
|||
# Features: |
|||
# @unstable: This command is meant for debugging. |
|||
# |
|||
# Returns: VirtVhostQueueStatus of the vhost_virtqueue |
|||
# |
|||
# Since: 7.1 |
|||
# |
|||
# Examples: |
|||
# |
|||
# 1. Get vhost_virtqueue status for vhost-crypto |
|||
# |
|||
# -> { "execute": "x-query-virtio-vhost-queue-status", |
|||
# "arguments": { "path": "/machine/peripheral/crypto0/virtio-backend", |
|||
# "queue": 0 } |
|||
# } |
|||
# <- { "return": { |
|||
# "avail-phys": 5216124928, |
|||
# "name": "virtio-crypto", |
|||
# "used-phys": 5216127040, |
|||
# "avail-size": 2054, |
|||
# "desc-size": 16384, |
|||
# "used-size": 8198, |
|||
# "desc": 140141447430144, |
|||
# "num": 1024, |
|||
# "call": 0, |
|||
# "avail": 140141447446528, |
|||
# "desc-phys": 5216108544, |
|||
# "used": 140141447448640, |
|||
# "kick": 0 |
|||
# } |
|||
# } |
|||
# |
|||
# 2. Get vhost_virtqueue status for vhost-vsock |
|||
# |
|||
# -> { "execute": "x-query-virtio-vhost-queue-status", |
|||
# "arguments": { "path": "/machine/peripheral/vsock0/virtio-backend", |
|||
# "queue": 0 } |
|||
# } |
|||
# <- { "return": { |
|||
# "avail-phys": 5182261248, |
|||
# "name": "vhost-vsock", |
|||
# "used-phys": 5182261568, |
|||
# "avail-size": 262, |
|||
# "desc-size": 2048, |
|||
# "used-size": 1030, |
|||
# "desc": 140141413580800, |
|||
# "num": 128, |
|||
# "call": 0, |
|||
# "avail": 140141413582848, |
|||
# "desc-phys": 5182259200, |
|||
# "used": 140141413583168, |
|||
# "kick": 0 |
|||
# } |
|||
# } |
|||
# |
|||
## |
|||
|
|||
{ 'command': 'x-query-virtio-vhost-queue-status', |
|||
'data': { 'path': 'str', 'queue': 'uint16' }, |
|||
'returns': 'VirtVhostQueueStatus', |
|||
'features': [ 'unstable' ] } |
|||
|
|||
## |
|||
# @VirtioRingDesc: |
|||
# |
|||
# Information regarding the vring descriptor area |
|||
# |
|||
# @addr: Guest physical address of the descriptor area |
|||
# |
|||
# @len: Length of the descriptor area |
|||
# |
|||
# @flags: List of descriptor flags |
|||
# |
|||
# Since: 7.1 |
|||
# |
|||
## |
|||
|
|||
{ 'struct': 'VirtioRingDesc', |
|||
'data': { 'addr': 'uint64', |
|||
'len': 'uint32', |
|||
'flags': [ 'str' ] } } |
|||
|
|||
## |
|||
# @VirtioRingAvail: |
|||
# |
|||
# Information regarding the avail vring (a.k.a. driver area) |
|||
# |
|||
# @flags: VRingAvail flags |
|||
# |
|||
# @idx: VRingAvail index |
|||
# |
|||
# @ring: VRingAvail ring[] entry at provided index |
|||
# |
|||
# Since: 7.1 |
|||
# |
|||
## |
|||
|
|||
{ 'struct': 'VirtioRingAvail', |
|||
'data': { 'flags': 'uint16', |
|||
'idx': 'uint16', |
|||
'ring': 'uint16' } } |
|||
|
|||
## |
|||
# @VirtioRingUsed: |
|||
# |
|||
# Information regarding the used vring (a.k.a. device area) |
|||
# |
|||
# @flags: VRingUsed flags |
|||
# |
|||
# @idx: VRingUsed index |
|||
# |
|||
# Since: 7.1 |
|||
# |
|||
## |
|||
|
|||
{ 'struct': 'VirtioRingUsed', |
|||
'data': { 'flags': 'uint16', |
|||
'idx': 'uint16' } } |
|||
|
|||
## |
|||
# @VirtioQueueElement: |
|||
# |
|||
# Information regarding a VirtQueue's VirtQueueElement including |
|||
# descriptor, driver, and device areas |
|||
# |
|||
# @name: Name of the VirtIODevice that uses this VirtQueue |
|||
# |
|||
# @index: Index of the element in the queue |
|||
# |
|||
# @descs: List of descriptors (VirtioRingDesc) |
|||
# |
|||
# @avail: VRingAvail info |
|||
# |
|||
# @used: VRingUsed info |
|||
# |
|||
# Since: 7.1 |
|||
# |
|||
## |
|||
|
|||
{ 'struct': 'VirtioQueueElement', |
|||
'data': { 'name': 'str', |
|||
'index': 'uint32', |
|||
'descs': [ 'VirtioRingDesc' ], |
|||
'avail': 'VirtioRingAvail', |
|||
'used': 'VirtioRingUsed' } } |
|||
|
|||
## |
|||
# @x-query-virtio-queue-element: |
|||
# |
|||
# Return the information about a VirtQueue's VirtQueueElement |
|||
# |
|||
# @path: VirtIODevice canonical QOM path |
|||
# |
|||
# @queue: VirtQueue index to examine |
|||
# |
|||
# @index: Index of the element in the queue |
|||
# (default: head of the queue) |
|||
# |
|||
# Features: |
|||
# @unstable: This command is meant for debugging. |
|||
# |
|||
# Returns: VirtioQueueElement information |
|||
# |
|||
# Since: 7.1 |
|||
# |
|||
# Examples: |
|||
# |
|||
# 1. Introspect on virtio-net's VirtQueue 0 at index 5 |
|||
# |
|||
# -> { "execute": "x-query-virtio-queue-element", |
|||
# "arguments": { "path": "/machine/peripheral-anon/device[1]/virtio-backend", |
|||
# "queue": 0, |
|||
# "index": 5 } |
|||
# } |
|||
# <- { "return": { |
|||
# "index": 5, |
|||
# "name": "virtio-net", |
|||
# "descs": [ |
|||
# { |
|||
# "flags": ["write"], |
|||
# "len": 1536, |
|||
# "addr": 5257305600 |
|||
# } |
|||
# ], |
|||
# "avail": { |
|||
# "idx": 256, |
|||
# "flags": 0, |
|||
# "ring": 5 |
|||
# }, |
|||
# "used": { |
|||
# "idx": 13, |
|||
# "flags": 0 |
|||
# } |
|||
# } |
|||
# } |
|||
# |
|||
# 2. Introspect on virtio-crypto's VirtQueue 1 at head |
|||
# |
|||
# -> { "execute": "x-query-virtio-queue-element", |
|||
# "arguments": { "path": "/machine/peripheral/crypto0/virtio-backend", |
|||
# "queue": 1 } |
|||
# } |
|||
# <- { "return": { |
|||
# "index": 0, |
|||
# "name": "virtio-crypto", |
|||
# "descs": [ |
|||
# { |
|||
# "flags": [], |
|||
# "len": 0, |
|||
# "addr": 8080268923184214134 |
|||
# } |
|||
# ], |
|||
# "avail": { |
|||
# "idx": 280, |
|||
# "flags": 0, |
|||
# "ring": 0 |
|||
# }, |
|||
# "used": { |
|||
# "idx": 280, |
|||
# "flags": 0 |
|||
# } |
|||
# } |
|||
# } |
|||
# |
|||
# 3. Introspect on virtio-scsi's VirtQueue 2 at head |
|||
# |
|||
# -> { "execute": "x-query-virtio-queue-element", |
|||
# "arguments": { "path": "/machine/peripheral-anon/device[2]/virtio-backend", |
|||
# "queue": 2 } |
|||
# } |
|||
# <- { "return": { |
|||
# "index": 19, |
|||
# "name": "virtio-scsi", |
|||
# "descs": [ |
|||
# { |
|||
# "flags": ["used", "indirect", "write"], |
|||
# "len": 4099327944, |
|||
# "addr": 12055409292258155293 |
|||
# } |
|||
# ], |
|||
# "avail": { |
|||
# "idx": 1147, |
|||
# "flags": 0, |
|||
# "ring": 19 |
|||
# }, |
|||
# "used": { |
|||
# "idx": 280, |
|||
# "flags": 0 |
|||
# } |
|||
# } |
|||
# } |
|||
# |
|||
## |
|||
|
|||
{ 'command': 'x-query-virtio-queue-element', |
|||
'data': { 'path': 'str', 'queue': 'uint16', '*index': 'uint16' }, |
|||
'returns': 'VirtioQueueElement', |
|||
'features': [ 'unstable' ] } |
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,171 @@ |
|||
/*
|
|||
* virtio-gpio nodes for testing |
|||
* |
|||
* Copyright (c) 2022 Linaro Ltd |
|||
* |
|||
* SPDX-License-Identifier: GPL-2.0-or-later |
|||
*/ |
|||
|
|||
#include "qemu/osdep.h" |
|||
#include "standard-headers/linux/virtio_config.h" |
|||
#include "../libqtest.h" |
|||
#include "qemu/module.h" |
|||
#include "qgraph.h" |
|||
#include "virtio-gpio.h" |
|||
|
|||
static QGuestAllocator *alloc; |
|||
|
|||
static void virtio_gpio_cleanup(QVhostUserGPIO *gpio) |
|||
{ |
|||
QVirtioDevice *vdev = gpio->vdev; |
|||
int i; |
|||
|
|||
for (i = 0; i < 2; i++) { |
|||
qvirtqueue_cleanup(vdev->bus, gpio->queues[i], alloc); |
|||
} |
|||
g_free(gpio->queues); |
|||
} |
|||
|
|||
/*
|
|||
* This handles the VirtIO setup from the point of view of the driver |
|||
* frontend and therefor doesn't present any vhost specific features |
|||
* and in fact masks of the re-used bit. |
|||
*/ |
|||
static void virtio_gpio_setup(QVhostUserGPIO *gpio) |
|||
{ |
|||
QVirtioDevice *vdev = gpio->vdev; |
|||
uint64_t features; |
|||
int i; |
|||
|
|||
features = qvirtio_get_features(vdev); |
|||
features &= ~QVIRTIO_F_BAD_FEATURE; |
|||
qvirtio_set_features(vdev, features); |
|||
|
|||
gpio->queues = g_new(QVirtQueue *, 2); |
|||
for (i = 0; i < 2; i++) { |
|||
gpio->queues[i] = qvirtqueue_setup(vdev, alloc, i); |
|||
} |
|||
qvirtio_set_driver_ok(vdev); |
|||
} |
|||
|
|||
static void *qvirtio_gpio_get_driver(QVhostUserGPIO *v_gpio, |
|||
const char *interface) |
|||
{ |
|||
if (!g_strcmp0(interface, "vhost-user-gpio")) { |
|||
return v_gpio; |
|||
} |
|||
if (!g_strcmp0(interface, "virtio")) { |
|||
return v_gpio->vdev; |
|||
} |
|||
|
|||
g_assert_not_reached(); |
|||
} |
|||
|
|||
static void *qvirtio_gpio_device_get_driver(void *object, |
|||
const char *interface) |
|||
{ |
|||
QVhostUserGPIODevice *v_gpio = object; |
|||
return qvirtio_gpio_get_driver(&v_gpio->gpio, interface); |
|||
} |
|||
|
|||
/* virtio-gpio (mmio) */ |
|||
static void qvirtio_gpio_device_destructor(QOSGraphObject *obj) |
|||
{ |
|||
QVhostUserGPIODevice *gpio_dev = (QVhostUserGPIODevice *) obj; |
|||
virtio_gpio_cleanup(&gpio_dev->gpio); |
|||
} |
|||
|
|||
static void qvirtio_gpio_device_start_hw(QOSGraphObject *obj) |
|||
{ |
|||
QVhostUserGPIODevice *gpio_dev = (QVhostUserGPIODevice *) obj; |
|||
virtio_gpio_setup(&gpio_dev->gpio); |
|||
} |
|||
|
|||
static void *virtio_gpio_device_create(void *virtio_dev, |
|||
QGuestAllocator *t_alloc, |
|||
void *addr) |
|||
{ |
|||
QVhostUserGPIODevice *virtio_device = g_new0(QVhostUserGPIODevice, 1); |
|||
QVhostUserGPIO *interface = &virtio_device->gpio; |
|||
|
|||
interface->vdev = virtio_dev; |
|||
alloc = t_alloc; |
|||
|
|||
virtio_device->obj.get_driver = qvirtio_gpio_device_get_driver; |
|||
virtio_device->obj.start_hw = qvirtio_gpio_device_start_hw; |
|||
virtio_device->obj.destructor = qvirtio_gpio_device_destructor; |
|||
|
|||
return &virtio_device->obj; |
|||
} |
|||
|
|||
/* virtio-gpio-pci */ |
|||
static void qvirtio_gpio_pci_destructor(QOSGraphObject *obj) |
|||
{ |
|||
QVhostUserGPIOPCI *gpio_pci = (QVhostUserGPIOPCI *) obj; |
|||
QOSGraphObject *pci_vobj = &gpio_pci->pci_vdev.obj; |
|||
|
|||
virtio_gpio_cleanup(&gpio_pci->gpio); |
|||
qvirtio_pci_destructor(pci_vobj); |
|||
} |
|||
|
|||
static void qvirtio_gpio_pci_start_hw(QOSGraphObject *obj) |
|||
{ |
|||
QVhostUserGPIOPCI *gpio_pci = (QVhostUserGPIOPCI *) obj; |
|||
QOSGraphObject *pci_vobj = &gpio_pci->pci_vdev.obj; |
|||
|
|||
qvirtio_pci_start_hw(pci_vobj); |
|||
virtio_gpio_setup(&gpio_pci->gpio); |
|||
} |
|||
|
|||
static void *qvirtio_gpio_pci_get_driver(void *object, const char *interface) |
|||
{ |
|||
QVhostUserGPIOPCI *v_gpio = object; |
|||
|
|||
if (!g_strcmp0(interface, "pci-device")) { |
|||
return v_gpio->pci_vdev.pdev; |
|||
} |
|||
return qvirtio_gpio_get_driver(&v_gpio->gpio, interface); |
|||
} |
|||
|
|||
static void *virtio_gpio_pci_create(void *pci_bus, QGuestAllocator *t_alloc, |
|||
void *addr) |
|||
{ |
|||
QVhostUserGPIOPCI *virtio_spci = g_new0(QVhostUserGPIOPCI, 1); |
|||
QVhostUserGPIO *interface = &virtio_spci->gpio; |
|||
QOSGraphObject *obj = &virtio_spci->pci_vdev.obj; |
|||
|
|||
virtio_pci_init(&virtio_spci->pci_vdev, pci_bus, addr); |
|||
interface->vdev = &virtio_spci->pci_vdev.vdev; |
|||
alloc = t_alloc; |
|||
|
|||
obj->get_driver = qvirtio_gpio_pci_get_driver; |
|||
obj->start_hw = qvirtio_gpio_pci_start_hw; |
|||
obj->destructor = qvirtio_gpio_pci_destructor; |
|||
|
|||
return obj; |
|||
} |
|||
|
|||
static void virtio_gpio_register_nodes(void) |
|||
{ |
|||
QPCIAddress addr = { |
|||
.devfn = QPCI_DEVFN(4, 0), |
|||
}; |
|||
|
|||
QOSGraphEdgeOptions edge_opts = { }; |
|||
|
|||
/* vhost-user-gpio-device */ |
|||
edge_opts.extra_device_opts = "id=gpio0,chardev=chr-vhost-user-test"; |
|||
qos_node_create_driver("vhost-user-gpio-device", |
|||
virtio_gpio_device_create); |
|||
qos_node_consumes("vhost-user-gpio-device", "virtio-bus", &edge_opts); |
|||
qos_node_produces("vhost-user-gpio-device", "vhost-user-gpio"); |
|||
|
|||
/* virtio-gpio-pci */ |
|||
edge_opts.extra_device_opts = "id=gpio0,addr=04.0,chardev=chr-vhost-user-test"; |
|||
add_qpci_address(&edge_opts, &addr); |
|||
qos_node_create_driver("vhost-user-gpio-pci", virtio_gpio_pci_create); |
|||
qos_node_consumes("vhost-user-gpio-pci", "pci-bus", &edge_opts); |
|||
qos_node_produces("vhost-user-gpio-pci", "vhost-user-gpio"); |
|||
} |
|||
|
|||
libqos_init(virtio_gpio_register_nodes); |
|||
@ -0,0 +1,35 @@ |
|||
/*
|
|||
* virtio-gpio structures |
|||
* |
|||
* Copyright (c) 2022 Linaro Ltd |
|||
* |
|||
* SPDX-License-Identifier: GPL-2.0-or-later |
|||
*/ |
|||
|
|||
#ifndef TESTS_LIBQOS_VIRTIO_GPIO_H |
|||
#define TESTS_LIBQOS_VIRTIO_GPIO_H |
|||
|
|||
#include "qgraph.h" |
|||
#include "virtio.h" |
|||
#include "virtio-pci.h" |
|||
|
|||
typedef struct QVhostUserGPIO QVhostUserGPIO; |
|||
typedef struct QVhostUserGPIOPCI QVhostUserGPIOPCI; |
|||
typedef struct QVhostUserGPIODevice QVhostUserGPIODevice; |
|||
|
|||
struct QVhostUserGPIO { |
|||
QVirtioDevice *vdev; |
|||
QVirtQueue **queues; |
|||
}; |
|||
|
|||
struct QVhostUserGPIOPCI { |
|||
QVirtioPCIDevice pci_vdev; |
|||
QVhostUserGPIO gpio; |
|||
}; |
|||
|
|||
struct QVhostUserGPIODevice { |
|||
QOSGraphObject obj; |
|||
QVhostUserGPIO gpio; |
|||
}; |
|||
|
|||
#endif |
|||
Loading…
Reference in new issue