153c25ceaSPaul Brook /* 253c25ceaSPaul Brook * Virtio PCI Bindings 353c25ceaSPaul Brook * 453c25ceaSPaul Brook * Copyright IBM, Corp. 2007 553c25ceaSPaul Brook * Copyright (c) 2009 CodeSourcery 653c25ceaSPaul Brook * 753c25ceaSPaul Brook * Authors: 853c25ceaSPaul Brook * Anthony Liguori <aliguori@us.ibm.com> 953c25ceaSPaul Brook * Paul Brook <paul@codesourcery.com> 1053c25ceaSPaul Brook * 1153c25ceaSPaul Brook * This work is licensed under the terms of the GNU GPL, version 2. See 1253c25ceaSPaul Brook * the COPYING file in the top-level directory. 1353c25ceaSPaul Brook * 146b620ca3SPaolo Bonzini * Contributions after 2012-01-13 are licensed under the terms of the 156b620ca3SPaolo Bonzini * GNU GPL, version 2 or (at your option) any later version. 1653c25ceaSPaul Brook */ 1753c25ceaSPaul Brook 1853c25ceaSPaul Brook #include <inttypes.h> 1953c25ceaSPaul Brook 200d09e41aSPaolo Bonzini #include "hw/virtio/virtio.h" 210d09e41aSPaolo Bonzini #include "hw/virtio/virtio-blk.h" 220d09e41aSPaolo Bonzini #include "hw/virtio/virtio-net.h" 230d09e41aSPaolo Bonzini #include "hw/virtio/virtio-serial.h" 240d09e41aSPaolo Bonzini #include "hw/virtio/virtio-scsi.h" 250d09e41aSPaolo Bonzini #include "hw/virtio/virtio-balloon.h" 2683c9f4caSPaolo Bonzini #include "hw/pci/pci.h" 271de7afc9SPaolo Bonzini #include "qemu/error-report.h" 2883c9f4caSPaolo Bonzini #include "hw/pci/msi.h" 2983c9f4caSPaolo Bonzini #include "hw/pci/msix.h" 3083c9f4caSPaolo Bonzini #include "hw/loader.h" 319c17d615SPaolo Bonzini #include "sysemu/kvm.h" 32*4be74634SMarkus Armbruster #include "sysemu/block-backend.h" 3347b43a1fSPaolo Bonzini #include "virtio-pci.h" 341de7afc9SPaolo Bonzini #include "qemu/range.h" 350d09e41aSPaolo Bonzini #include "hw/virtio/virtio-bus.h" 3624a6e7f4SKONRAD Frederic #include "qapi/visitor.h" 3753c25ceaSPaul Brook 3853c25ceaSPaul Brook /* from Linux's linux/virtio_pci.h */ 3953c25ceaSPaul Brook 4053c25ceaSPaul Brook /* A 32-bit r/o bitmask of the features supported by the host */ 4153c25ceaSPaul Brook #define VIRTIO_PCI_HOST_FEATURES 0 4253c25ceaSPaul Brook 4353c25ceaSPaul Brook /* A 32-bit r/w bitmask of features activated by the guest */ 4453c25ceaSPaul Brook #define VIRTIO_PCI_GUEST_FEATURES 4 4553c25ceaSPaul Brook 4653c25ceaSPaul Brook /* A 32-bit r/w PFN for the currently selected queue */ 4753c25ceaSPaul Brook #define VIRTIO_PCI_QUEUE_PFN 8 4853c25ceaSPaul Brook 4953c25ceaSPaul Brook /* A 16-bit r/o queue size for the currently selected queue */ 5053c25ceaSPaul Brook #define VIRTIO_PCI_QUEUE_NUM 12 5153c25ceaSPaul Brook 5253c25ceaSPaul Brook /* A 16-bit r/w queue selector */ 5353c25ceaSPaul Brook #define VIRTIO_PCI_QUEUE_SEL 14 5453c25ceaSPaul Brook 5553c25ceaSPaul Brook /* A 16-bit r/w queue notifier */ 5653c25ceaSPaul Brook #define VIRTIO_PCI_QUEUE_NOTIFY 16 5753c25ceaSPaul Brook 5853c25ceaSPaul Brook /* An 8-bit device status register. */ 5953c25ceaSPaul Brook #define VIRTIO_PCI_STATUS 18 6053c25ceaSPaul Brook 6153c25ceaSPaul Brook /* An 8-bit r/o interrupt status register. Reading the value will return the 6253c25ceaSPaul Brook * current contents of the ISR and will also clear it. This is effectively 6353c25ceaSPaul Brook * a read-and-acknowledge. */ 6453c25ceaSPaul Brook #define VIRTIO_PCI_ISR 19 6553c25ceaSPaul Brook 66aba800a3SMichael S. Tsirkin /* MSI-X registers: only enabled if MSI-X is enabled. */ 67aba800a3SMichael S. Tsirkin /* A 16-bit vector for configuration changes. */ 68aba800a3SMichael S. Tsirkin #define VIRTIO_MSI_CONFIG_VECTOR 20 69aba800a3SMichael S. Tsirkin /* A 16-bit vector for selected queue notifications. */ 70aba800a3SMichael S. Tsirkin #define VIRTIO_MSI_QUEUE_VECTOR 22 71aba800a3SMichael S. Tsirkin 72aba800a3SMichael S. Tsirkin /* Config space size */ 73aba800a3SMichael S. Tsirkin #define VIRTIO_PCI_CONFIG_NOMSI 20 74aba800a3SMichael S. Tsirkin #define VIRTIO_PCI_CONFIG_MSI 24 75aba800a3SMichael S. Tsirkin #define VIRTIO_PCI_REGION_SIZE(dev) (msix_present(dev) ? \ 76aba800a3SMichael S. Tsirkin VIRTIO_PCI_CONFIG_MSI : \ 77aba800a3SMichael S. Tsirkin VIRTIO_PCI_CONFIG_NOMSI) 78aba800a3SMichael S. Tsirkin 79aba800a3SMichael S. Tsirkin /* The remaining space is defined by each driver as the per-driver 80aba800a3SMichael S. Tsirkin * configuration space */ 81aba800a3SMichael S. Tsirkin #define VIRTIO_PCI_CONFIG(dev) (msix_enabled(dev) ? \ 82aba800a3SMichael S. Tsirkin VIRTIO_PCI_CONFIG_MSI : \ 83aba800a3SMichael S. Tsirkin VIRTIO_PCI_CONFIG_NOMSI) 8453c25ceaSPaul Brook 8553c25ceaSPaul Brook /* How many bits to shift physical queue address written to QUEUE_PFN. 8653c25ceaSPaul Brook * 12 is historical, and due to x86 page size. */ 8753c25ceaSPaul Brook #define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12 8853c25ceaSPaul Brook 8945363e46SMichael S. Tsirkin /* Flags track per-device state like workarounds for quirks in older guests. */ 9045363e46SMichael S. Tsirkin #define VIRTIO_PCI_FLAG_BUS_MASTER_BUG (1 << 0) 9145363e46SMichael S. Tsirkin 92ac7af112SAndreas Färber static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, 93ac7af112SAndreas Färber VirtIOPCIProxy *dev); 94d51fcfacSKONRAD Frederic 9553c25ceaSPaul Brook /* virtio device */ 96d2a0ccc6SMichael S. Tsirkin /* DeviceState to VirtIOPCIProxy. For use off data-path. TODO: use QOM. */ 97d2a0ccc6SMichael S. Tsirkin static inline VirtIOPCIProxy *to_virtio_pci_proxy(DeviceState *d) 9853c25ceaSPaul Brook { 99d2a0ccc6SMichael S. Tsirkin return container_of(d, VirtIOPCIProxy, pci_dev.qdev); 100d2a0ccc6SMichael S. Tsirkin } 101d2a0ccc6SMichael S. Tsirkin 102d2a0ccc6SMichael S. Tsirkin /* DeviceState to VirtIOPCIProxy. Note: used on datapath, 103d2a0ccc6SMichael S. Tsirkin * be careful and test performance if you change this. 104d2a0ccc6SMichael S. Tsirkin */ 105d2a0ccc6SMichael S. Tsirkin static inline VirtIOPCIProxy *to_virtio_pci_proxy_fast(DeviceState *d) 106d2a0ccc6SMichael S. Tsirkin { 107d2a0ccc6SMichael S. Tsirkin return container_of(d, VirtIOPCIProxy, pci_dev.qdev); 108d2a0ccc6SMichael S. Tsirkin } 109d2a0ccc6SMichael S. Tsirkin 110d2a0ccc6SMichael S. Tsirkin static void virtio_pci_notify(DeviceState *d, uint16_t vector) 111d2a0ccc6SMichael S. Tsirkin { 112d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy_fast(d); 113a3fc66d9SPaolo Bonzini 114aba800a3SMichael S. Tsirkin if (msix_enabled(&proxy->pci_dev)) 115aba800a3SMichael S. Tsirkin msix_notify(&proxy->pci_dev, vector); 116a3fc66d9SPaolo Bonzini else { 117a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 118a3fc66d9SPaolo Bonzini pci_set_irq(&proxy->pci_dev, vdev->isr & 1); 119a3fc66d9SPaolo Bonzini } 12053c25ceaSPaul Brook } 12153c25ceaSPaul Brook 122d2a0ccc6SMichael S. Tsirkin static void virtio_pci_save_config(DeviceState *d, QEMUFile *f) 123ff24bd58SMichael S. Tsirkin { 124d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 125a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 126a3fc66d9SPaolo Bonzini 127ff24bd58SMichael S. Tsirkin pci_device_save(&proxy->pci_dev, f); 128ff24bd58SMichael S. Tsirkin msix_save(&proxy->pci_dev, f); 129ff24bd58SMichael S. Tsirkin if (msix_present(&proxy->pci_dev)) 130a3fc66d9SPaolo Bonzini qemu_put_be16(f, vdev->config_vector); 131ff24bd58SMichael S. Tsirkin } 132ff24bd58SMichael S. Tsirkin 133d2a0ccc6SMichael S. Tsirkin static void virtio_pci_save_queue(DeviceState *d, int n, QEMUFile *f) 134ff24bd58SMichael S. Tsirkin { 135d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 136a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 137a3fc66d9SPaolo Bonzini 138ff24bd58SMichael S. Tsirkin if (msix_present(&proxy->pci_dev)) 139a3fc66d9SPaolo Bonzini qemu_put_be16(f, virtio_queue_vector(vdev, n)); 140ff24bd58SMichael S. Tsirkin } 141ff24bd58SMichael S. Tsirkin 142d2a0ccc6SMichael S. Tsirkin static int virtio_pci_load_config(DeviceState *d, QEMUFile *f) 143ff24bd58SMichael S. Tsirkin { 144d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 145a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 146a3fc66d9SPaolo Bonzini 147ff24bd58SMichael S. Tsirkin int ret; 148ff24bd58SMichael S. Tsirkin ret = pci_device_load(&proxy->pci_dev, f); 149e6da7680SMichael S. Tsirkin if (ret) { 150ff24bd58SMichael S. Tsirkin return ret; 151e6da7680SMichael S. Tsirkin } 1523cac001eSMichael S. Tsirkin msix_unuse_all_vectors(&proxy->pci_dev); 153ff24bd58SMichael S. Tsirkin msix_load(&proxy->pci_dev, f); 154e6da7680SMichael S. Tsirkin if (msix_present(&proxy->pci_dev)) { 155a3fc66d9SPaolo Bonzini qemu_get_be16s(f, &vdev->config_vector); 156e6da7680SMichael S. Tsirkin } else { 157a3fc66d9SPaolo Bonzini vdev->config_vector = VIRTIO_NO_VECTOR; 158e6da7680SMichael S. Tsirkin } 159a3fc66d9SPaolo Bonzini if (vdev->config_vector != VIRTIO_NO_VECTOR) { 160a3fc66d9SPaolo Bonzini return msix_vector_use(&proxy->pci_dev, vdev->config_vector); 161e6da7680SMichael S. Tsirkin } 162ff24bd58SMichael S. Tsirkin return 0; 163ff24bd58SMichael S. Tsirkin } 164ff24bd58SMichael S. Tsirkin 165d2a0ccc6SMichael S. Tsirkin static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f) 166ff24bd58SMichael S. Tsirkin { 167d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 168a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 169a3fc66d9SPaolo Bonzini 170ff24bd58SMichael S. Tsirkin uint16_t vector; 171e6da7680SMichael S. Tsirkin if (msix_present(&proxy->pci_dev)) { 172ff24bd58SMichael S. Tsirkin qemu_get_be16s(f, &vector); 173e6da7680SMichael S. Tsirkin } else { 174e6da7680SMichael S. Tsirkin vector = VIRTIO_NO_VECTOR; 175e6da7680SMichael S. Tsirkin } 176a3fc66d9SPaolo Bonzini virtio_queue_set_vector(vdev, n, vector); 177e6da7680SMichael S. Tsirkin if (vector != VIRTIO_NO_VECTOR) { 178e6da7680SMichael S. Tsirkin return msix_vector_use(&proxy->pci_dev, vector); 179e6da7680SMichael S. Tsirkin } 180ff24bd58SMichael S. Tsirkin return 0; 181ff24bd58SMichael S. Tsirkin } 182ff24bd58SMichael S. Tsirkin 18325db9ebeSStefan Hajnoczi static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy, 18426b9b5feSPaolo Bonzini int n, bool assign, bool set_handler) 18525db9ebeSStefan Hajnoczi { 186a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 187a3fc66d9SPaolo Bonzini VirtQueue *vq = virtio_get_queue(vdev, n); 18825db9ebeSStefan Hajnoczi EventNotifier *notifier = virtio_queue_get_host_notifier(vq); 189da146d0aSAvi Kivity int r = 0; 190da146d0aSAvi Kivity 19125db9ebeSStefan Hajnoczi if (assign) { 19225db9ebeSStefan Hajnoczi r = event_notifier_init(notifier, 1); 19325db9ebeSStefan Hajnoczi if (r < 0) { 194b36e3914SMichael S. Tsirkin error_report("%s: unable to init event notifier: %d", 195b36e3914SMichael S. Tsirkin __func__, r); 19625db9ebeSStefan Hajnoczi return r; 19725db9ebeSStefan Hajnoczi } 19826b9b5feSPaolo Bonzini virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler); 199da146d0aSAvi Kivity memory_region_add_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2, 200753d5e14SPaolo Bonzini true, n, notifier); 20125db9ebeSStefan Hajnoczi } else { 202da146d0aSAvi Kivity memory_region_del_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2, 203753d5e14SPaolo Bonzini true, n, notifier); 20426b9b5feSPaolo Bonzini virtio_queue_set_host_notifier_fd_handler(vq, false, false); 20525db9ebeSStefan Hajnoczi event_notifier_cleanup(notifier); 20625db9ebeSStefan Hajnoczi } 20725db9ebeSStefan Hajnoczi return r; 20825db9ebeSStefan Hajnoczi } 20925db9ebeSStefan Hajnoczi 210b36e3914SMichael S. Tsirkin static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy) 21125db9ebeSStefan Hajnoczi { 212a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 21325db9ebeSStefan Hajnoczi int n, r; 21425db9ebeSStefan Hajnoczi 21525db9ebeSStefan Hajnoczi if (!(proxy->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD) || 21625db9ebeSStefan Hajnoczi proxy->ioeventfd_disabled || 21725db9ebeSStefan Hajnoczi proxy->ioeventfd_started) { 218b36e3914SMichael S. Tsirkin return; 21925db9ebeSStefan Hajnoczi } 22025db9ebeSStefan Hajnoczi 22125db9ebeSStefan Hajnoczi for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) { 222a3fc66d9SPaolo Bonzini if (!virtio_queue_get_num(vdev, n)) { 22325db9ebeSStefan Hajnoczi continue; 22425db9ebeSStefan Hajnoczi } 22525db9ebeSStefan Hajnoczi 22626b9b5feSPaolo Bonzini r = virtio_pci_set_host_notifier_internal(proxy, n, true, true); 22725db9ebeSStefan Hajnoczi if (r < 0) { 22825db9ebeSStefan Hajnoczi goto assign_error; 22925db9ebeSStefan Hajnoczi } 23025db9ebeSStefan Hajnoczi } 23125db9ebeSStefan Hajnoczi proxy->ioeventfd_started = true; 232b36e3914SMichael S. Tsirkin return; 23325db9ebeSStefan Hajnoczi 23425db9ebeSStefan Hajnoczi assign_error: 23525db9ebeSStefan Hajnoczi while (--n >= 0) { 236a3fc66d9SPaolo Bonzini if (!virtio_queue_get_num(vdev, n)) { 23725db9ebeSStefan Hajnoczi continue; 23825db9ebeSStefan Hajnoczi } 23925db9ebeSStefan Hajnoczi 24026b9b5feSPaolo Bonzini r = virtio_pci_set_host_notifier_internal(proxy, n, false, false); 241b36e3914SMichael S. Tsirkin assert(r >= 0); 24225db9ebeSStefan Hajnoczi } 24325db9ebeSStefan Hajnoczi proxy->ioeventfd_started = false; 244b36e3914SMichael S. Tsirkin error_report("%s: failed. Fallback to a userspace (slower).", __func__); 24525db9ebeSStefan Hajnoczi } 24625db9ebeSStefan Hajnoczi 247b36e3914SMichael S. Tsirkin static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy) 24825db9ebeSStefan Hajnoczi { 249a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 250b36e3914SMichael S. Tsirkin int r; 25125db9ebeSStefan Hajnoczi int n; 25225db9ebeSStefan Hajnoczi 25325db9ebeSStefan Hajnoczi if (!proxy->ioeventfd_started) { 254b36e3914SMichael S. Tsirkin return; 25525db9ebeSStefan Hajnoczi } 25625db9ebeSStefan Hajnoczi 25725db9ebeSStefan Hajnoczi for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) { 258a3fc66d9SPaolo Bonzini if (!virtio_queue_get_num(vdev, n)) { 25925db9ebeSStefan Hajnoczi continue; 26025db9ebeSStefan Hajnoczi } 26125db9ebeSStefan Hajnoczi 26226b9b5feSPaolo Bonzini r = virtio_pci_set_host_notifier_internal(proxy, n, false, false); 263b36e3914SMichael S. Tsirkin assert(r >= 0); 26425db9ebeSStefan Hajnoczi } 26525db9ebeSStefan Hajnoczi proxy->ioeventfd_started = false; 26625db9ebeSStefan Hajnoczi } 26725db9ebeSStefan Hajnoczi 26853c25ceaSPaul Brook static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) 26953c25ceaSPaul Brook { 27053c25ceaSPaul Brook VirtIOPCIProxy *proxy = opaque; 271a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 272a8170e5eSAvi Kivity hwaddr pa; 27353c25ceaSPaul Brook 27453c25ceaSPaul Brook switch (addr) { 27553c25ceaSPaul Brook case VIRTIO_PCI_GUEST_FEATURES: 27653c25ceaSPaul Brook /* Guest does not negotiate properly? We have to assume nothing. */ 27753c25ceaSPaul Brook if (val & (1 << VIRTIO_F_BAD_FEATURE)) { 278181103cdSKONRAD Frederic val = virtio_bus_get_vdev_bad_features(&proxy->bus); 27953c25ceaSPaul Brook } 280ad0c9332SPaolo Bonzini virtio_set_features(vdev, val); 28153c25ceaSPaul Brook break; 28253c25ceaSPaul Brook case VIRTIO_PCI_QUEUE_PFN: 283a8170e5eSAvi Kivity pa = (hwaddr)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT; 2841b8e9b27SMichael S. Tsirkin if (pa == 0) { 28525db9ebeSStefan Hajnoczi virtio_pci_stop_ioeventfd(proxy); 286a3fc66d9SPaolo Bonzini virtio_reset(vdev); 2871b8e9b27SMichael S. Tsirkin msix_unuse_all_vectors(&proxy->pci_dev); 2881b8e9b27SMichael S. Tsirkin } 2897055e687SMichael S. Tsirkin else 29053c25ceaSPaul Brook virtio_queue_set_addr(vdev, vdev->queue_sel, pa); 29153c25ceaSPaul Brook break; 29253c25ceaSPaul Brook case VIRTIO_PCI_QUEUE_SEL: 29353c25ceaSPaul Brook if (val < VIRTIO_PCI_QUEUE_MAX) 29453c25ceaSPaul Brook vdev->queue_sel = val; 29553c25ceaSPaul Brook break; 29653c25ceaSPaul Brook case VIRTIO_PCI_QUEUE_NOTIFY: 2977157e2e2SStefan Hajnoczi if (val < VIRTIO_PCI_QUEUE_MAX) { 29853c25ceaSPaul Brook virtio_queue_notify(vdev, val); 2997157e2e2SStefan Hajnoczi } 30053c25ceaSPaul Brook break; 30153c25ceaSPaul Brook case VIRTIO_PCI_STATUS: 30225db9ebeSStefan Hajnoczi if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) { 30325db9ebeSStefan Hajnoczi virtio_pci_stop_ioeventfd(proxy); 30425db9ebeSStefan Hajnoczi } 30525db9ebeSStefan Hajnoczi 3063e607cb5SMichael S. Tsirkin virtio_set_status(vdev, val & 0xFF); 30725db9ebeSStefan Hajnoczi 30825db9ebeSStefan Hajnoczi if (val & VIRTIO_CONFIG_S_DRIVER_OK) { 30925db9ebeSStefan Hajnoczi virtio_pci_start_ioeventfd(proxy); 31025db9ebeSStefan Hajnoczi } 31125db9ebeSStefan Hajnoczi 3121b8e9b27SMichael S. Tsirkin if (vdev->status == 0) { 313a3fc66d9SPaolo Bonzini virtio_reset(vdev); 3141b8e9b27SMichael S. Tsirkin msix_unuse_all_vectors(&proxy->pci_dev); 3151b8e9b27SMichael S. Tsirkin } 316c81131dbSAlexander Graf 317e43c0b2eSMichael S. Tsirkin /* Linux before 2.6.34 drives the device without enabling 318e43c0b2eSMichael S. Tsirkin the PCI device bus master bit. Enable it automatically 319e43c0b2eSMichael S. Tsirkin for the guest. This is a PCI spec violation but so is 320e43c0b2eSMichael S. Tsirkin initiating DMA with bus master bit clear. */ 321e43c0b2eSMichael S. Tsirkin if (val == (VIRTIO_CONFIG_S_ACKNOWLEDGE | VIRTIO_CONFIG_S_DRIVER)) { 322e43c0b2eSMichael S. Tsirkin pci_default_write_config(&proxy->pci_dev, PCI_COMMAND, 323e43c0b2eSMichael S. Tsirkin proxy->pci_dev.config[PCI_COMMAND] | 324e43c0b2eSMichael S. Tsirkin PCI_COMMAND_MASTER, 1); 325e43c0b2eSMichael S. Tsirkin } 32645363e46SMichael S. Tsirkin 32745363e46SMichael S. Tsirkin /* Linux before 2.6.34 sets the device as OK without enabling 32845363e46SMichael S. Tsirkin the PCI device bus master bit. In this case we need to disable 32945363e46SMichael S. Tsirkin some safety checks. */ 33045363e46SMichael S. Tsirkin if ((val & VIRTIO_CONFIG_S_DRIVER_OK) && 33145363e46SMichael S. Tsirkin !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) { 33245363e46SMichael S. Tsirkin proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG; 33345363e46SMichael S. Tsirkin } 33453c25ceaSPaul Brook break; 335aba800a3SMichael S. Tsirkin case VIRTIO_MSI_CONFIG_VECTOR: 336aba800a3SMichael S. Tsirkin msix_vector_unuse(&proxy->pci_dev, vdev->config_vector); 337aba800a3SMichael S. Tsirkin /* Make it possible for guest to discover an error took place. */ 338aba800a3SMichael S. Tsirkin if (msix_vector_use(&proxy->pci_dev, val) < 0) 339aba800a3SMichael S. Tsirkin val = VIRTIO_NO_VECTOR; 340aba800a3SMichael S. Tsirkin vdev->config_vector = val; 341aba800a3SMichael S. Tsirkin break; 342aba800a3SMichael S. Tsirkin case VIRTIO_MSI_QUEUE_VECTOR: 343aba800a3SMichael S. Tsirkin msix_vector_unuse(&proxy->pci_dev, 344aba800a3SMichael S. Tsirkin virtio_queue_vector(vdev, vdev->queue_sel)); 345aba800a3SMichael S. Tsirkin /* Make it possible for guest to discover an error took place. */ 346aba800a3SMichael S. Tsirkin if (msix_vector_use(&proxy->pci_dev, val) < 0) 347aba800a3SMichael S. Tsirkin val = VIRTIO_NO_VECTOR; 348aba800a3SMichael S. Tsirkin virtio_queue_set_vector(vdev, vdev->queue_sel, val); 349aba800a3SMichael S. Tsirkin break; 350aba800a3SMichael S. Tsirkin default: 3514e02d460SStefan Hajnoczi error_report("%s: unexpected address 0x%x value 0x%x", 352aba800a3SMichael S. Tsirkin __func__, addr, val); 353aba800a3SMichael S. Tsirkin break; 35453c25ceaSPaul Brook } 35553c25ceaSPaul Brook } 35653c25ceaSPaul Brook 357aba800a3SMichael S. Tsirkin static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr) 35853c25ceaSPaul Brook { 359a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 36053c25ceaSPaul Brook uint32_t ret = 0xFFFFFFFF; 36153c25ceaSPaul Brook 36253c25ceaSPaul Brook switch (addr) { 36353c25ceaSPaul Brook case VIRTIO_PCI_HOST_FEATURES: 3648172539dSMichael S. Tsirkin ret = proxy->host_features; 36553c25ceaSPaul Brook break; 36653c25ceaSPaul Brook case VIRTIO_PCI_GUEST_FEATURES: 367704a76fcSMichael S. Tsirkin ret = vdev->guest_features; 36853c25ceaSPaul Brook break; 36953c25ceaSPaul Brook case VIRTIO_PCI_QUEUE_PFN: 37053c25ceaSPaul Brook ret = virtio_queue_get_addr(vdev, vdev->queue_sel) 37153c25ceaSPaul Brook >> VIRTIO_PCI_QUEUE_ADDR_SHIFT; 37253c25ceaSPaul Brook break; 37353c25ceaSPaul Brook case VIRTIO_PCI_QUEUE_NUM: 37453c25ceaSPaul Brook ret = virtio_queue_get_num(vdev, vdev->queue_sel); 37553c25ceaSPaul Brook break; 37653c25ceaSPaul Brook case VIRTIO_PCI_QUEUE_SEL: 37753c25ceaSPaul Brook ret = vdev->queue_sel; 37853c25ceaSPaul Brook break; 37953c25ceaSPaul Brook case VIRTIO_PCI_STATUS: 38053c25ceaSPaul Brook ret = vdev->status; 38153c25ceaSPaul Brook break; 38253c25ceaSPaul Brook case VIRTIO_PCI_ISR: 38353c25ceaSPaul Brook /* reading from the ISR also clears it. */ 38453c25ceaSPaul Brook ret = vdev->isr; 38553c25ceaSPaul Brook vdev->isr = 0; 3869e64f8a3SMarcel Apfelbaum pci_irq_deassert(&proxy->pci_dev); 38753c25ceaSPaul Brook break; 388aba800a3SMichael S. Tsirkin case VIRTIO_MSI_CONFIG_VECTOR: 389aba800a3SMichael S. Tsirkin ret = vdev->config_vector; 390aba800a3SMichael S. Tsirkin break; 391aba800a3SMichael S. Tsirkin case VIRTIO_MSI_QUEUE_VECTOR: 392aba800a3SMichael S. Tsirkin ret = virtio_queue_vector(vdev, vdev->queue_sel); 393aba800a3SMichael S. Tsirkin break; 39453c25ceaSPaul Brook default: 39553c25ceaSPaul Brook break; 39653c25ceaSPaul Brook } 39753c25ceaSPaul Brook 39853c25ceaSPaul Brook return ret; 39953c25ceaSPaul Brook } 40053c25ceaSPaul Brook 401df6db5b3SAlexander Graf static uint64_t virtio_pci_config_read(void *opaque, hwaddr addr, 402df6db5b3SAlexander Graf unsigned size) 40353c25ceaSPaul Brook { 40453c25ceaSPaul Brook VirtIOPCIProxy *proxy = opaque; 405a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 406aba800a3SMichael S. Tsirkin uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev); 407df6db5b3SAlexander Graf uint64_t val = 0; 408df6db5b3SAlexander Graf if (addr < config) { 409aba800a3SMichael S. Tsirkin return virtio_ioport_read(proxy, addr); 41053c25ceaSPaul Brook } 411aba800a3SMichael S. Tsirkin addr -= config; 412df6db5b3SAlexander Graf 413df6db5b3SAlexander Graf switch (size) { 414df6db5b3SAlexander Graf case 1: 415a3fc66d9SPaolo Bonzini val = virtio_config_readb(vdev, addr); 416df6db5b3SAlexander Graf break; 417df6db5b3SAlexander Graf case 2: 418a3fc66d9SPaolo Bonzini val = virtio_config_readw(vdev, addr); 419616a6552SGreg Kurz if (virtio_is_big_endian(vdev)) { 4208e4a424bSBlue Swirl val = bswap16(val); 4218e4a424bSBlue Swirl } 422df6db5b3SAlexander Graf break; 423df6db5b3SAlexander Graf case 4: 424a3fc66d9SPaolo Bonzini val = virtio_config_readl(vdev, addr); 425616a6552SGreg Kurz if (virtio_is_big_endian(vdev)) { 4268e4a424bSBlue Swirl val = bswap32(val); 4278e4a424bSBlue Swirl } 428df6db5b3SAlexander Graf break; 429df6db5b3SAlexander Graf } 43082afa586SBenjamin Herrenschmidt return val; 43153c25ceaSPaul Brook } 43253c25ceaSPaul Brook 433df6db5b3SAlexander Graf static void virtio_pci_config_write(void *opaque, hwaddr addr, 434df6db5b3SAlexander Graf uint64_t val, unsigned size) 43553c25ceaSPaul Brook { 43653c25ceaSPaul Brook VirtIOPCIProxy *proxy = opaque; 437aba800a3SMichael S. Tsirkin uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev); 438a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 439aba800a3SMichael S. Tsirkin if (addr < config) { 440aba800a3SMichael S. Tsirkin virtio_ioport_write(proxy, addr, val); 441aba800a3SMichael S. Tsirkin return; 442aba800a3SMichael S. Tsirkin } 443aba800a3SMichael S. Tsirkin addr -= config; 444df6db5b3SAlexander Graf /* 445df6db5b3SAlexander Graf * Virtio-PCI is odd. Ioports are LE but config space is target native 446df6db5b3SAlexander Graf * endian. 447df6db5b3SAlexander Graf */ 448df6db5b3SAlexander Graf switch (size) { 449df6db5b3SAlexander Graf case 1: 450a3fc66d9SPaolo Bonzini virtio_config_writeb(vdev, addr, val); 451df6db5b3SAlexander Graf break; 452df6db5b3SAlexander Graf case 2: 453616a6552SGreg Kurz if (virtio_is_big_endian(vdev)) { 4548e4a424bSBlue Swirl val = bswap16(val); 4558e4a424bSBlue Swirl } 456a3fc66d9SPaolo Bonzini virtio_config_writew(vdev, addr, val); 457df6db5b3SAlexander Graf break; 458df6db5b3SAlexander Graf case 4: 459616a6552SGreg Kurz if (virtio_is_big_endian(vdev)) { 4608e4a424bSBlue Swirl val = bswap32(val); 4618e4a424bSBlue Swirl } 462a3fc66d9SPaolo Bonzini virtio_config_writel(vdev, addr, val); 463df6db5b3SAlexander Graf break; 464df6db5b3SAlexander Graf } 46553c25ceaSPaul Brook } 46653c25ceaSPaul Brook 467da146d0aSAvi Kivity static const MemoryRegionOps virtio_pci_config_ops = { 468df6db5b3SAlexander Graf .read = virtio_pci_config_read, 469df6db5b3SAlexander Graf .write = virtio_pci_config_write, 470df6db5b3SAlexander Graf .impl = { 471df6db5b3SAlexander Graf .min_access_size = 1, 472df6db5b3SAlexander Graf .max_access_size = 4, 473df6db5b3SAlexander Graf }, 4748e4a424bSBlue Swirl .endianness = DEVICE_LITTLE_ENDIAN, 475da146d0aSAvi Kivity }; 476aba800a3SMichael S. Tsirkin 477aba800a3SMichael S. Tsirkin static void virtio_write_config(PCIDevice *pci_dev, uint32_t address, 478aba800a3SMichael S. Tsirkin uint32_t val, int len) 479aba800a3SMichael S. Tsirkin { 480ed757e14SYan Vugenfirer VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); 481a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 482ed757e14SYan Vugenfirer 4831129714fSMichael S. Tsirkin pci_default_write_config(pci_dev, address, val, len); 4841129714fSMichael S. Tsirkin 4851129714fSMichael S. Tsirkin if (range_covers_byte(address, len, PCI_COMMAND) && 4861129714fSMichael S. Tsirkin !(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) && 48745363e46SMichael S. Tsirkin !(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) { 48825db9ebeSStefan Hajnoczi virtio_pci_stop_ioeventfd(proxy); 48945363e46SMichael S. Tsirkin virtio_set_status(vdev, vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK); 490ed757e14SYan Vugenfirer } 49153c25ceaSPaul Brook } 49253c25ceaSPaul Brook 493d2a0ccc6SMichael S. Tsirkin static unsigned virtio_pci_get_features(DeviceState *d) 4946d74ca5aSMichael S. Tsirkin { 495d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 4968172539dSMichael S. Tsirkin return proxy->host_features; 4976d74ca5aSMichael S. Tsirkin } 4986d74ca5aSMichael S. Tsirkin 4997d37d351SJan Kiszka static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy, 5007d37d351SJan Kiszka unsigned int queue_no, 5017d37d351SJan Kiszka unsigned int vector, 5027d37d351SJan Kiszka MSIMessage msg) 5037d37d351SJan Kiszka { 5047d37d351SJan Kiszka VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; 50515b2bd18SPaolo Bonzini int ret; 5067d37d351SJan Kiszka 5077d37d351SJan Kiszka if (irqfd->users == 0) { 5087d37d351SJan Kiszka ret = kvm_irqchip_add_msi_route(kvm_state, msg); 5097d37d351SJan Kiszka if (ret < 0) { 5107d37d351SJan Kiszka return ret; 5117d37d351SJan Kiszka } 5127d37d351SJan Kiszka irqfd->virq = ret; 5137d37d351SJan Kiszka } 5147d37d351SJan Kiszka irqfd->users++; 5157d37d351SJan Kiszka return 0; 5167d37d351SJan Kiszka } 5177d37d351SJan Kiszka 5187d37d351SJan Kiszka static void kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy, 519774345f9SMichael S. Tsirkin unsigned int vector) 520774345f9SMichael S. Tsirkin { 521774345f9SMichael S. Tsirkin VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; 522774345f9SMichael S. Tsirkin if (--irqfd->users == 0) { 523774345f9SMichael S. Tsirkin kvm_irqchip_release_virq(kvm_state, irqfd->virq); 524774345f9SMichael S. Tsirkin } 525774345f9SMichael S. Tsirkin } 526774345f9SMichael S. Tsirkin 527f1d0f15aSMichael S. Tsirkin static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy, 528f1d0f15aSMichael S. Tsirkin unsigned int queue_no, 529f1d0f15aSMichael S. Tsirkin unsigned int vector) 530f1d0f15aSMichael S. Tsirkin { 531f1d0f15aSMichael S. Tsirkin VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; 532a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 533a3fc66d9SPaolo Bonzini VirtQueue *vq = virtio_get_queue(vdev, queue_no); 534f1d0f15aSMichael S. Tsirkin EventNotifier *n = virtio_queue_get_guest_notifier(vq); 535f1d0f15aSMichael S. Tsirkin int ret; 536ca916d37SVincenzo Maffione ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, NULL, irqfd->virq); 537f1d0f15aSMichael S. Tsirkin return ret; 538f1d0f15aSMichael S. Tsirkin } 539f1d0f15aSMichael S. Tsirkin 540f1d0f15aSMichael S. Tsirkin static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy, 5417d37d351SJan Kiszka unsigned int queue_no, 5427d37d351SJan Kiszka unsigned int vector) 5437d37d351SJan Kiszka { 544a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 545a3fc66d9SPaolo Bonzini VirtQueue *vq = virtio_get_queue(vdev, queue_no); 54615b2bd18SPaolo Bonzini EventNotifier *n = virtio_queue_get_guest_notifier(vq); 5477d37d351SJan Kiszka VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; 54815b2bd18SPaolo Bonzini int ret; 5497d37d351SJan Kiszka 550b131c74aSJan Kiszka ret = kvm_irqchip_remove_irqfd_notifier(kvm_state, n, irqfd->virq); 5517d37d351SJan Kiszka assert(ret == 0); 552f1d0f15aSMichael S. Tsirkin } 5537d37d351SJan Kiszka 554774345f9SMichael S. Tsirkin static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) 555774345f9SMichael S. Tsirkin { 556774345f9SMichael S. Tsirkin PCIDevice *dev = &proxy->pci_dev; 557a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 558181103cdSKONRAD Frederic VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); 559774345f9SMichael S. Tsirkin unsigned int vector; 560774345f9SMichael S. Tsirkin int ret, queue_no; 561774345f9SMichael S. Tsirkin MSIMessage msg; 562774345f9SMichael S. Tsirkin 563774345f9SMichael S. Tsirkin for (queue_no = 0; queue_no < nvqs; queue_no++) { 564774345f9SMichael S. Tsirkin if (!virtio_queue_get_num(vdev, queue_no)) { 565774345f9SMichael S. Tsirkin break; 566774345f9SMichael S. Tsirkin } 567774345f9SMichael S. Tsirkin vector = virtio_queue_vector(vdev, queue_no); 568774345f9SMichael S. Tsirkin if (vector >= msix_nr_vectors_allocated(dev)) { 569774345f9SMichael S. Tsirkin continue; 570774345f9SMichael S. Tsirkin } 571774345f9SMichael S. Tsirkin msg = msix_get_message(dev, vector); 572774345f9SMichael S. Tsirkin ret = kvm_virtio_pci_vq_vector_use(proxy, queue_no, vector, msg); 573774345f9SMichael S. Tsirkin if (ret < 0) { 574774345f9SMichael S. Tsirkin goto undo; 575774345f9SMichael S. Tsirkin } 576f1d0f15aSMichael S. Tsirkin /* If guest supports masking, set up irqfd now. 577f1d0f15aSMichael S. Tsirkin * Otherwise, delay until unmasked in the frontend. 578f1d0f15aSMichael S. Tsirkin */ 579181103cdSKONRAD Frederic if (k->guest_notifier_mask) { 580f1d0f15aSMichael S. Tsirkin ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector); 581f1d0f15aSMichael S. Tsirkin if (ret < 0) { 582f1d0f15aSMichael S. Tsirkin kvm_virtio_pci_vq_vector_release(proxy, vector); 583f1d0f15aSMichael S. Tsirkin goto undo; 584f1d0f15aSMichael S. Tsirkin } 585f1d0f15aSMichael S. Tsirkin } 586774345f9SMichael S. Tsirkin } 587774345f9SMichael S. Tsirkin return 0; 588774345f9SMichael S. Tsirkin 589774345f9SMichael S. Tsirkin undo: 590774345f9SMichael S. Tsirkin while (--queue_no >= 0) { 591774345f9SMichael S. Tsirkin vector = virtio_queue_vector(vdev, queue_no); 592774345f9SMichael S. Tsirkin if (vector >= msix_nr_vectors_allocated(dev)) { 593774345f9SMichael S. Tsirkin continue; 594774345f9SMichael S. Tsirkin } 595181103cdSKONRAD Frederic if (k->guest_notifier_mask) { 596e387f99eSMichael S. Tsirkin kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); 597f1d0f15aSMichael S. Tsirkin } 598774345f9SMichael S. Tsirkin kvm_virtio_pci_vq_vector_release(proxy, vector); 599774345f9SMichael S. Tsirkin } 600774345f9SMichael S. Tsirkin return ret; 601774345f9SMichael S. Tsirkin } 602774345f9SMichael S. Tsirkin 603774345f9SMichael S. Tsirkin static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) 604774345f9SMichael S. Tsirkin { 605774345f9SMichael S. Tsirkin PCIDevice *dev = &proxy->pci_dev; 606a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 607774345f9SMichael S. Tsirkin unsigned int vector; 608774345f9SMichael S. Tsirkin int queue_no; 609181103cdSKONRAD Frederic VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); 610774345f9SMichael S. Tsirkin 611774345f9SMichael S. Tsirkin for (queue_no = 0; queue_no < nvqs; queue_no++) { 612774345f9SMichael S. Tsirkin if (!virtio_queue_get_num(vdev, queue_no)) { 613774345f9SMichael S. Tsirkin break; 614774345f9SMichael S. Tsirkin } 615774345f9SMichael S. Tsirkin vector = virtio_queue_vector(vdev, queue_no); 616774345f9SMichael S. Tsirkin if (vector >= msix_nr_vectors_allocated(dev)) { 617774345f9SMichael S. Tsirkin continue; 618774345f9SMichael S. Tsirkin } 619f1d0f15aSMichael S. Tsirkin /* If guest supports masking, clean up irqfd now. 620f1d0f15aSMichael S. Tsirkin * Otherwise, it was cleaned when masked in the frontend. 621f1d0f15aSMichael S. Tsirkin */ 622181103cdSKONRAD Frederic if (k->guest_notifier_mask) { 623e387f99eSMichael S. Tsirkin kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); 624f1d0f15aSMichael S. Tsirkin } 625774345f9SMichael S. Tsirkin kvm_virtio_pci_vq_vector_release(proxy, vector); 6267d37d351SJan Kiszka } 6277d37d351SJan Kiszka } 6287d37d351SJan Kiszka 629a38b2c49SMichael S. Tsirkin static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy, 630774345f9SMichael S. Tsirkin unsigned int queue_no, 631774345f9SMichael S. Tsirkin unsigned int vector, 632774345f9SMichael S. Tsirkin MSIMessage msg) 633774345f9SMichael S. Tsirkin { 634a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 635a3fc66d9SPaolo Bonzini VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); 636a3fc66d9SPaolo Bonzini VirtQueue *vq = virtio_get_queue(vdev, queue_no); 637774345f9SMichael S. Tsirkin EventNotifier *n = virtio_queue_get_guest_notifier(vq); 638a38b2c49SMichael S. Tsirkin VirtIOIRQFD *irqfd; 63953510bfcSMichael Roth int ret = 0; 640774345f9SMichael S. Tsirkin 641a38b2c49SMichael S. Tsirkin if (proxy->vector_irqfd) { 642a38b2c49SMichael S. Tsirkin irqfd = &proxy->vector_irqfd[vector]; 643774345f9SMichael S. Tsirkin if (irqfd->msg.data != msg.data || irqfd->msg.address != msg.address) { 644774345f9SMichael S. Tsirkin ret = kvm_irqchip_update_msi_route(kvm_state, irqfd->virq, msg); 645774345f9SMichael S. Tsirkin if (ret < 0) { 646774345f9SMichael S. Tsirkin return ret; 647774345f9SMichael S. Tsirkin } 648774345f9SMichael S. Tsirkin } 649a38b2c49SMichael S. Tsirkin } 650774345f9SMichael S. Tsirkin 651f1d0f15aSMichael S. Tsirkin /* If guest supports masking, irqfd is already setup, unmask it. 652f1d0f15aSMichael S. Tsirkin * Otherwise, set it up now. 653f1d0f15aSMichael S. Tsirkin */ 654181103cdSKONRAD Frederic if (k->guest_notifier_mask) { 655a3fc66d9SPaolo Bonzini k->guest_notifier_mask(vdev, queue_no, false); 656f1d0f15aSMichael S. Tsirkin /* Test after unmasking to avoid losing events. */ 657181103cdSKONRAD Frederic if (k->guest_notifier_pending && 658a3fc66d9SPaolo Bonzini k->guest_notifier_pending(vdev, queue_no)) { 659f1d0f15aSMichael S. Tsirkin event_notifier_set(n); 660f1d0f15aSMichael S. Tsirkin } 661f1d0f15aSMichael S. Tsirkin } else { 662f1d0f15aSMichael S. Tsirkin ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector); 663f1d0f15aSMichael S. Tsirkin } 664774345f9SMichael S. Tsirkin return ret; 665774345f9SMichael S. Tsirkin } 666774345f9SMichael S. Tsirkin 667a38b2c49SMichael S. Tsirkin static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy, 6687d37d351SJan Kiszka unsigned int queue_no, 6697d37d351SJan Kiszka unsigned int vector) 6707d37d351SJan Kiszka { 671a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 672a3fc66d9SPaolo Bonzini VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); 673181103cdSKONRAD Frederic 674f1d0f15aSMichael S. Tsirkin /* If guest supports masking, keep irqfd but mask it. 675f1d0f15aSMichael S. Tsirkin * Otherwise, clean it up now. 676f1d0f15aSMichael S. Tsirkin */ 677181103cdSKONRAD Frederic if (k->guest_notifier_mask) { 678a3fc66d9SPaolo Bonzini k->guest_notifier_mask(vdev, queue_no, true); 679f1d0f15aSMichael S. Tsirkin } else { 680e387f99eSMichael S. Tsirkin kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); 681f1d0f15aSMichael S. Tsirkin } 6827d37d351SJan Kiszka } 6837d37d351SJan Kiszka 684a38b2c49SMichael S. Tsirkin static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, 6857d37d351SJan Kiszka MSIMessage msg) 6867d37d351SJan Kiszka { 6877d37d351SJan Kiszka VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); 688a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 6897d37d351SJan Kiszka int ret, queue_no; 6907d37d351SJan Kiszka 6912d620f59SMichael S. Tsirkin for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) { 6927d37d351SJan Kiszka if (!virtio_queue_get_num(vdev, queue_no)) { 6937d37d351SJan Kiszka break; 6947d37d351SJan Kiszka } 6957d37d351SJan Kiszka if (virtio_queue_vector(vdev, queue_no) != vector) { 6967d37d351SJan Kiszka continue; 6977d37d351SJan Kiszka } 698a38b2c49SMichael S. Tsirkin ret = virtio_pci_vq_vector_unmask(proxy, queue_no, vector, msg); 6997d37d351SJan Kiszka if (ret < 0) { 7007d37d351SJan Kiszka goto undo; 7017d37d351SJan Kiszka } 7027d37d351SJan Kiszka } 7037d37d351SJan Kiszka return 0; 7047d37d351SJan Kiszka 7057d37d351SJan Kiszka undo: 7067d37d351SJan Kiszka while (--queue_no >= 0) { 7077d37d351SJan Kiszka if (virtio_queue_vector(vdev, queue_no) != vector) { 7087d37d351SJan Kiszka continue; 7097d37d351SJan Kiszka } 710a38b2c49SMichael S. Tsirkin virtio_pci_vq_vector_mask(proxy, queue_no, vector); 7117d37d351SJan Kiszka } 7127d37d351SJan Kiszka return ret; 7137d37d351SJan Kiszka } 7147d37d351SJan Kiszka 715a38b2c49SMichael S. Tsirkin static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector) 7167d37d351SJan Kiszka { 7177d37d351SJan Kiszka VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); 718a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 7197d37d351SJan Kiszka int queue_no; 7207d37d351SJan Kiszka 7212d620f59SMichael S. Tsirkin for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) { 7227d37d351SJan Kiszka if (!virtio_queue_get_num(vdev, queue_no)) { 7237d37d351SJan Kiszka break; 7247d37d351SJan Kiszka } 7257d37d351SJan Kiszka if (virtio_queue_vector(vdev, queue_no) != vector) { 7267d37d351SJan Kiszka continue; 7277d37d351SJan Kiszka } 728a38b2c49SMichael S. Tsirkin virtio_pci_vq_vector_mask(proxy, queue_no, vector); 7297d37d351SJan Kiszka } 7307d37d351SJan Kiszka } 7317d37d351SJan Kiszka 732a38b2c49SMichael S. Tsirkin static void virtio_pci_vector_poll(PCIDevice *dev, 73389d62be9SMichael S. Tsirkin unsigned int vector_start, 73489d62be9SMichael S. Tsirkin unsigned int vector_end) 73589d62be9SMichael S. Tsirkin { 73689d62be9SMichael S. Tsirkin VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); 737a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 738181103cdSKONRAD Frederic VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); 73989d62be9SMichael S. Tsirkin int queue_no; 74089d62be9SMichael S. Tsirkin unsigned int vector; 74189d62be9SMichael S. Tsirkin EventNotifier *notifier; 74289d62be9SMichael S. Tsirkin VirtQueue *vq; 74389d62be9SMichael S. Tsirkin 7442d620f59SMichael S. Tsirkin for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) { 74589d62be9SMichael S. Tsirkin if (!virtio_queue_get_num(vdev, queue_no)) { 74689d62be9SMichael S. Tsirkin break; 74789d62be9SMichael S. Tsirkin } 74889d62be9SMichael S. Tsirkin vector = virtio_queue_vector(vdev, queue_no); 74989d62be9SMichael S. Tsirkin if (vector < vector_start || vector >= vector_end || 75089d62be9SMichael S. Tsirkin !msix_is_masked(dev, vector)) { 75189d62be9SMichael S. Tsirkin continue; 75289d62be9SMichael S. Tsirkin } 75389d62be9SMichael S. Tsirkin vq = virtio_get_queue(vdev, queue_no); 75489d62be9SMichael S. Tsirkin notifier = virtio_queue_get_guest_notifier(vq); 755181103cdSKONRAD Frederic if (k->guest_notifier_pending) { 756181103cdSKONRAD Frederic if (k->guest_notifier_pending(vdev, queue_no)) { 757f1d0f15aSMichael S. Tsirkin msix_set_pending(dev, vector); 758f1d0f15aSMichael S. Tsirkin } 759f1d0f15aSMichael S. Tsirkin } else if (event_notifier_test_and_clear(notifier)) { 76089d62be9SMichael S. Tsirkin msix_set_pending(dev, vector); 76189d62be9SMichael S. Tsirkin } 76289d62be9SMichael S. Tsirkin } 76389d62be9SMichael S. Tsirkin } 76489d62be9SMichael S. Tsirkin 76589d62be9SMichael S. Tsirkin static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign, 76689d62be9SMichael S. Tsirkin bool with_irqfd) 767ade80dc8SMichael S. Tsirkin { 768d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 769a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 770a3fc66d9SPaolo Bonzini VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); 771a3fc66d9SPaolo Bonzini VirtQueue *vq = virtio_get_queue(vdev, n); 772ade80dc8SMichael S. Tsirkin EventNotifier *notifier = virtio_queue_get_guest_notifier(vq); 773ade80dc8SMichael S. Tsirkin 774ade80dc8SMichael S. Tsirkin if (assign) { 775ade80dc8SMichael S. Tsirkin int r = event_notifier_init(notifier, 0); 776ade80dc8SMichael S. Tsirkin if (r < 0) { 777ade80dc8SMichael S. Tsirkin return r; 778ade80dc8SMichael S. Tsirkin } 77989d62be9SMichael S. Tsirkin virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd); 780ade80dc8SMichael S. Tsirkin } else { 78189d62be9SMichael S. Tsirkin virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd); 782ade80dc8SMichael S. Tsirkin event_notifier_cleanup(notifier); 783ade80dc8SMichael S. Tsirkin } 784ade80dc8SMichael S. Tsirkin 78562c96360SMichael S. Tsirkin if (!msix_enabled(&proxy->pci_dev) && vdc->guest_notifier_mask) { 786a3fc66d9SPaolo Bonzini vdc->guest_notifier_mask(vdev, n, !assign); 78762c96360SMichael S. Tsirkin } 78862c96360SMichael S. Tsirkin 789ade80dc8SMichael S. Tsirkin return 0; 790ade80dc8SMichael S. Tsirkin } 791ade80dc8SMichael S. Tsirkin 792d2a0ccc6SMichael S. Tsirkin static bool virtio_pci_query_guest_notifiers(DeviceState *d) 7935430a28fSmst@redhat.com { 794d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 7955430a28fSmst@redhat.com return msix_enabled(&proxy->pci_dev); 7965430a28fSmst@redhat.com } 7975430a28fSmst@redhat.com 7982d620f59SMichael S. Tsirkin static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) 79954dd9321SMichael S. Tsirkin { 800d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 801a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 802181103cdSKONRAD Frederic VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); 80354dd9321SMichael S. Tsirkin int r, n; 80489d62be9SMichael S. Tsirkin bool with_irqfd = msix_enabled(&proxy->pci_dev) && 80589d62be9SMichael S. Tsirkin kvm_msi_via_irqfd_enabled(); 80654dd9321SMichael S. Tsirkin 8072d620f59SMichael S. Tsirkin nvqs = MIN(nvqs, VIRTIO_PCI_QUEUE_MAX); 8082d620f59SMichael S. Tsirkin 8092d620f59SMichael S. Tsirkin /* When deassigning, pass a consistent nvqs value 8102d620f59SMichael S. Tsirkin * to avoid leaking notifiers. 8112d620f59SMichael S. Tsirkin */ 8122d620f59SMichael S. Tsirkin assert(assign || nvqs == proxy->nvqs_with_notifiers); 8132d620f59SMichael S. Tsirkin 8142d620f59SMichael S. Tsirkin proxy->nvqs_with_notifiers = nvqs; 8152d620f59SMichael S. Tsirkin 8167d37d351SJan Kiszka /* Must unset vector notifier while guest notifier is still assigned */ 817181103cdSKONRAD Frederic if ((proxy->vector_irqfd || k->guest_notifier_mask) && !assign) { 8187d37d351SJan Kiszka msix_unset_vector_notifiers(&proxy->pci_dev); 819a38b2c49SMichael S. Tsirkin if (proxy->vector_irqfd) { 820774345f9SMichael S. Tsirkin kvm_virtio_pci_vector_release(proxy, nvqs); 8217d37d351SJan Kiszka g_free(proxy->vector_irqfd); 8227d37d351SJan Kiszka proxy->vector_irqfd = NULL; 8237d37d351SJan Kiszka } 824a38b2c49SMichael S. Tsirkin } 8257d37d351SJan Kiszka 8262d620f59SMichael S. Tsirkin for (n = 0; n < nvqs; n++) { 82754dd9321SMichael S. Tsirkin if (!virtio_queue_get_num(vdev, n)) { 82854dd9321SMichael S. Tsirkin break; 82954dd9321SMichael S. Tsirkin } 83054dd9321SMichael S. Tsirkin 83123fe2b3fSMichael S. Tsirkin r = virtio_pci_set_guest_notifier(d, n, assign, with_irqfd); 83254dd9321SMichael S. Tsirkin if (r < 0) { 83354dd9321SMichael S. Tsirkin goto assign_error; 83454dd9321SMichael S. Tsirkin } 83554dd9321SMichael S. Tsirkin } 83654dd9321SMichael S. Tsirkin 8377d37d351SJan Kiszka /* Must set vector notifier after guest notifier has been assigned */ 838181103cdSKONRAD Frederic if ((with_irqfd || k->guest_notifier_mask) && assign) { 839a38b2c49SMichael S. Tsirkin if (with_irqfd) { 8407d37d351SJan Kiszka proxy->vector_irqfd = 8417d37d351SJan Kiszka g_malloc0(sizeof(*proxy->vector_irqfd) * 8427d37d351SJan Kiszka msix_nr_vectors_allocated(&proxy->pci_dev)); 843774345f9SMichael S. Tsirkin r = kvm_virtio_pci_vector_use(proxy, nvqs); 8447d37d351SJan Kiszka if (r < 0) { 8457d37d351SJan Kiszka goto assign_error; 8467d37d351SJan Kiszka } 847a38b2c49SMichael S. Tsirkin } 848774345f9SMichael S. Tsirkin r = msix_set_vector_notifiers(&proxy->pci_dev, 849a38b2c49SMichael S. Tsirkin virtio_pci_vector_unmask, 850a38b2c49SMichael S. Tsirkin virtio_pci_vector_mask, 851a38b2c49SMichael S. Tsirkin virtio_pci_vector_poll); 852774345f9SMichael S. Tsirkin if (r < 0) { 853774345f9SMichael S. Tsirkin goto notifiers_error; 854774345f9SMichael S. Tsirkin } 8557d37d351SJan Kiszka } 8567d37d351SJan Kiszka 85754dd9321SMichael S. Tsirkin return 0; 85854dd9321SMichael S. Tsirkin 859774345f9SMichael S. Tsirkin notifiers_error: 860a38b2c49SMichael S. Tsirkin if (with_irqfd) { 861774345f9SMichael S. Tsirkin assert(assign); 862774345f9SMichael S. Tsirkin kvm_virtio_pci_vector_release(proxy, nvqs); 863a38b2c49SMichael S. Tsirkin } 864774345f9SMichael S. Tsirkin 86554dd9321SMichael S. Tsirkin assign_error: 86654dd9321SMichael S. Tsirkin /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */ 8677d37d351SJan Kiszka assert(assign); 86854dd9321SMichael S. Tsirkin while (--n >= 0) { 86989d62be9SMichael S. Tsirkin virtio_pci_set_guest_notifier(d, n, !assign, with_irqfd); 87054dd9321SMichael S. Tsirkin } 87154dd9321SMichael S. Tsirkin return r; 87254dd9321SMichael S. Tsirkin } 87354dd9321SMichael S. Tsirkin 874d2a0ccc6SMichael S. Tsirkin static int virtio_pci_set_host_notifier(DeviceState *d, int n, bool assign) 875ade80dc8SMichael S. Tsirkin { 876d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 87725db9ebeSStefan Hajnoczi 87825db9ebeSStefan Hajnoczi /* Stop using ioeventfd for virtqueue kick if the device starts using host 87925db9ebeSStefan Hajnoczi * notifiers. This makes it easy to avoid stepping on each others' toes. 88025db9ebeSStefan Hajnoczi */ 88125db9ebeSStefan Hajnoczi proxy->ioeventfd_disabled = assign; 882ade80dc8SMichael S. Tsirkin if (assign) { 88325db9ebeSStefan Hajnoczi virtio_pci_stop_ioeventfd(proxy); 884ade80dc8SMichael S. Tsirkin } 88525db9ebeSStefan Hajnoczi /* We don't need to start here: it's not needed because backend 88625db9ebeSStefan Hajnoczi * currently only stops on status change away from ok, 88725db9ebeSStefan Hajnoczi * reset, vmstop and such. If we do add code to start here, 88825db9ebeSStefan Hajnoczi * need to check vmstate, device state etc. */ 88926b9b5feSPaolo Bonzini return virtio_pci_set_host_notifier_internal(proxy, n, assign, false); 890ade80dc8SMichael S. Tsirkin } 89125db9ebeSStefan Hajnoczi 892d2a0ccc6SMichael S. Tsirkin static void virtio_pci_vmstate_change(DeviceState *d, bool running) 89325db9ebeSStefan Hajnoczi { 894d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 895a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 89625db9ebeSStefan Hajnoczi 89725db9ebeSStefan Hajnoczi if (running) { 89845363e46SMichael S. Tsirkin /* Try to find out if the guest has bus master disabled, but is 89945363e46SMichael S. Tsirkin in ready state. Then we have a buggy guest OS. */ 90045363e46SMichael S. Tsirkin if ((vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) && 90145363e46SMichael S. Tsirkin !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) { 90245363e46SMichael S. Tsirkin proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG; 90389c473fdSMichael S. Tsirkin } 90425db9ebeSStefan Hajnoczi virtio_pci_start_ioeventfd(proxy); 905ade80dc8SMichael S. Tsirkin } else { 90625db9ebeSStefan Hajnoczi virtio_pci_stop_ioeventfd(proxy); 907ade80dc8SMichael S. Tsirkin } 908ade80dc8SMichael S. Tsirkin } 909ade80dc8SMichael S. Tsirkin 91060653b28SPaolo Bonzini #ifdef CONFIG_VIRTFS 911234a336fSKONRAD Frederic static int virtio_9p_init_pci(VirtIOPCIProxy *vpci_dev) 91260653b28SPaolo Bonzini { 913234a336fSKONRAD Frederic V9fsPCIState *dev = VIRTIO_9P_PCI(vpci_dev); 914234a336fSKONRAD Frederic DeviceState *vdev = DEVICE(&dev->vdev); 91560653b28SPaolo Bonzini 916234a336fSKONRAD Frederic qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); 917234a336fSKONRAD Frederic if (qdev_init(vdev) < 0) { 918234a336fSKONRAD Frederic return -1; 919234a336fSKONRAD Frederic } 92060653b28SPaolo Bonzini return 0; 92160653b28SPaolo Bonzini } 92260653b28SPaolo Bonzini 923234a336fSKONRAD Frederic static Property virtio_9p_pci_properties[] = { 924234a336fSKONRAD Frederic DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, 925234a336fSKONRAD Frederic VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), 92660653b28SPaolo Bonzini DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), 92760653b28SPaolo Bonzini DEFINE_PROP_END_OF_LIST(), 92860653b28SPaolo Bonzini }; 92960653b28SPaolo Bonzini 930234a336fSKONRAD Frederic static void virtio_9p_pci_class_init(ObjectClass *klass, void *data) 93160653b28SPaolo Bonzini { 93260653b28SPaolo Bonzini DeviceClass *dc = DEVICE_CLASS(klass); 933234a336fSKONRAD Frederic PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); 934234a336fSKONRAD Frederic VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); 93560653b28SPaolo Bonzini 93660653b28SPaolo Bonzini k->init = virtio_9p_init_pci; 937234a336fSKONRAD Frederic pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 938234a336fSKONRAD Frederic pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_9P; 939234a336fSKONRAD Frederic pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; 940234a336fSKONRAD Frederic pcidev_k->class_id = 0x2; 941125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 942234a336fSKONRAD Frederic dc->props = virtio_9p_pci_properties; 94360653b28SPaolo Bonzini } 94460653b28SPaolo Bonzini 945234a336fSKONRAD Frederic static void virtio_9p_pci_instance_init(Object *obj) 946234a336fSKONRAD Frederic { 947234a336fSKONRAD Frederic V9fsPCIState *dev = VIRTIO_9P_PCI(obj); 948c8075cafSGonglei 949c8075cafSGonglei virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), 950c8075cafSGonglei TYPE_VIRTIO_9P); 951234a336fSKONRAD Frederic } 952234a336fSKONRAD Frederic 953234a336fSKONRAD Frederic static const TypeInfo virtio_9p_pci_info = { 954234a336fSKONRAD Frederic .name = TYPE_VIRTIO_9P_PCI, 955234a336fSKONRAD Frederic .parent = TYPE_VIRTIO_PCI, 956234a336fSKONRAD Frederic .instance_size = sizeof(V9fsPCIState), 957234a336fSKONRAD Frederic .instance_init = virtio_9p_pci_instance_init, 958234a336fSKONRAD Frederic .class_init = virtio_9p_pci_class_init, 95960653b28SPaolo Bonzini }; 960234a336fSKONRAD Frederic #endif /* CONFIG_VIRTFS */ 96160653b28SPaolo Bonzini 962085bccb7SKONRAD Frederic /* 963085bccb7SKONRAD Frederic * virtio-pci: This is the PCIDevice which has a virtio-pci-bus. 964085bccb7SKONRAD Frederic */ 965085bccb7SKONRAD Frederic 966085bccb7SKONRAD Frederic /* This is called by virtio-bus just after the device is plugged. */ 967085bccb7SKONRAD Frederic static void virtio_pci_device_plugged(DeviceState *d) 968085bccb7SKONRAD Frederic { 969085bccb7SKONRAD Frederic VirtIOPCIProxy *proxy = VIRTIO_PCI(d); 970085bccb7SKONRAD Frederic VirtioBusState *bus = &proxy->bus; 971085bccb7SKONRAD Frederic uint8_t *config; 972085bccb7SKONRAD Frederic uint32_t size; 973085bccb7SKONRAD Frederic 974085bccb7SKONRAD Frederic config = proxy->pci_dev.config; 975085bccb7SKONRAD Frederic if (proxy->class_code) { 976085bccb7SKONRAD Frederic pci_config_set_class(config, proxy->class_code); 977085bccb7SKONRAD Frederic } 978085bccb7SKONRAD Frederic pci_set_word(config + PCI_SUBSYSTEM_VENDOR_ID, 979085bccb7SKONRAD Frederic pci_get_word(config + PCI_VENDOR_ID)); 980085bccb7SKONRAD Frederic pci_set_word(config + PCI_SUBSYSTEM_ID, virtio_bus_get_vdev_id(bus)); 981085bccb7SKONRAD Frederic config[PCI_INTERRUPT_PIN] = 1; 982085bccb7SKONRAD Frederic 983085bccb7SKONRAD Frederic if (proxy->nvectors && 984085bccb7SKONRAD Frederic msix_init_exclusive_bar(&proxy->pci_dev, proxy->nvectors, 1)) { 985c7ff5482SFam Zheng error_report("unable to init msix vectors to %" PRIu32, 986c7ff5482SFam Zheng proxy->nvectors); 987085bccb7SKONRAD Frederic proxy->nvectors = 0; 988085bccb7SKONRAD Frederic } 989085bccb7SKONRAD Frederic 990085bccb7SKONRAD Frederic proxy->pci_dev.config_write = virtio_write_config; 991085bccb7SKONRAD Frederic 992085bccb7SKONRAD Frederic size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) 993085bccb7SKONRAD Frederic + virtio_bus_get_vdev_config_len(bus); 994085bccb7SKONRAD Frederic if (size & (size - 1)) { 995085bccb7SKONRAD Frederic size = 1 << qemu_fls(size); 996085bccb7SKONRAD Frederic } 997085bccb7SKONRAD Frederic 99822fc860bSPaolo Bonzini memory_region_init_io(&proxy->bar, OBJECT(proxy), &virtio_pci_config_ops, 99922fc860bSPaolo Bonzini proxy, "virtio-pci", size); 1000085bccb7SKONRAD Frederic pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, 1001085bccb7SKONRAD Frederic &proxy->bar); 1002085bccb7SKONRAD Frederic 1003085bccb7SKONRAD Frederic if (!kvm_has_many_ioeventfds()) { 1004085bccb7SKONRAD Frederic proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD; 1005085bccb7SKONRAD Frederic } 1006085bccb7SKONRAD Frederic 1007085bccb7SKONRAD Frederic proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY; 1008085bccb7SKONRAD Frederic proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE; 1009085bccb7SKONRAD Frederic proxy->host_features = virtio_bus_get_vdev_features(bus, 1010085bccb7SKONRAD Frederic proxy->host_features); 1011085bccb7SKONRAD Frederic } 1012085bccb7SKONRAD Frederic 101306a13073SPaolo Bonzini static void virtio_pci_device_unplugged(DeviceState *d) 101406a13073SPaolo Bonzini { 101506a13073SPaolo Bonzini VirtIOPCIProxy *proxy = VIRTIO_PCI(d); 101606a13073SPaolo Bonzini 101706a13073SPaolo Bonzini virtio_pci_stop_ioeventfd(proxy); 101806a13073SPaolo Bonzini } 101906a13073SPaolo Bonzini 1020085bccb7SKONRAD Frederic static int virtio_pci_init(PCIDevice *pci_dev) 1021085bccb7SKONRAD Frederic { 1022085bccb7SKONRAD Frederic VirtIOPCIProxy *dev = VIRTIO_PCI(pci_dev); 1023085bccb7SKONRAD Frederic VirtioPCIClass *k = VIRTIO_PCI_GET_CLASS(pci_dev); 1024ac7af112SAndreas Färber virtio_pci_bus_new(&dev->bus, sizeof(dev->bus), dev); 1025085bccb7SKONRAD Frederic if (k->init != NULL) { 1026085bccb7SKONRAD Frederic return k->init(dev); 1027085bccb7SKONRAD Frederic } 1028085bccb7SKONRAD Frederic return 0; 1029085bccb7SKONRAD Frederic } 1030085bccb7SKONRAD Frederic 1031085bccb7SKONRAD Frederic static void virtio_pci_exit(PCIDevice *pci_dev) 1032085bccb7SKONRAD Frederic { 10338b81bb3bSPaolo Bonzini msix_uninit_exclusive_bar(pci_dev); 1034085bccb7SKONRAD Frederic } 1035085bccb7SKONRAD Frederic 103659ccd20aSKONRAD Frederic static void virtio_pci_reset(DeviceState *qdev) 1037085bccb7SKONRAD Frederic { 1038085bccb7SKONRAD Frederic VirtIOPCIProxy *proxy = VIRTIO_PCI(qdev); 1039085bccb7SKONRAD Frederic VirtioBusState *bus = VIRTIO_BUS(&proxy->bus); 1040085bccb7SKONRAD Frederic virtio_pci_stop_ioeventfd(proxy); 1041085bccb7SKONRAD Frederic virtio_bus_reset(bus); 1042085bccb7SKONRAD Frederic msix_unuse_all_vectors(&proxy->pci_dev); 104345363e46SMichael S. Tsirkin proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG; 1044085bccb7SKONRAD Frederic } 1045085bccb7SKONRAD Frederic 104685d1277eSMing Lei static Property virtio_pci_properties[] = { 104785d1277eSMing Lei DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features), 104885d1277eSMing Lei DEFINE_PROP_END_OF_LIST(), 104985d1277eSMing Lei }; 105085d1277eSMing Lei 1051085bccb7SKONRAD Frederic static void virtio_pci_class_init(ObjectClass *klass, void *data) 1052085bccb7SKONRAD Frederic { 1053085bccb7SKONRAD Frederic DeviceClass *dc = DEVICE_CLASS(klass); 1054085bccb7SKONRAD Frederic PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 1055085bccb7SKONRAD Frederic 105685d1277eSMing Lei dc->props = virtio_pci_properties; 1057085bccb7SKONRAD Frederic k->init = virtio_pci_init; 1058085bccb7SKONRAD Frederic k->exit = virtio_pci_exit; 1059085bccb7SKONRAD Frederic k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 1060085bccb7SKONRAD Frederic k->revision = VIRTIO_PCI_ABI_VERSION; 1061085bccb7SKONRAD Frederic k->class_id = PCI_CLASS_OTHERS; 106259ccd20aSKONRAD Frederic dc->reset = virtio_pci_reset; 1063085bccb7SKONRAD Frederic } 1064085bccb7SKONRAD Frederic 1065085bccb7SKONRAD Frederic static const TypeInfo virtio_pci_info = { 1066085bccb7SKONRAD Frederic .name = TYPE_VIRTIO_PCI, 1067085bccb7SKONRAD Frederic .parent = TYPE_PCI_DEVICE, 1068085bccb7SKONRAD Frederic .instance_size = sizeof(VirtIOPCIProxy), 1069085bccb7SKONRAD Frederic .class_init = virtio_pci_class_init, 1070085bccb7SKONRAD Frederic .class_size = sizeof(VirtioPCIClass), 1071085bccb7SKONRAD Frederic .abstract = true, 1072085bccb7SKONRAD Frederic }; 1073085bccb7SKONRAD Frederic 1074653ced07SKONRAD Frederic /* virtio-blk-pci */ 1075653ced07SKONRAD Frederic 1076653ced07SKONRAD Frederic static Property virtio_blk_pci_properties[] = { 1077c7bcc85dSPaolo Bonzini DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), 1078653ced07SKONRAD Frederic DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, 1079653ced07SKONRAD Frederic VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), 1080653ced07SKONRAD Frederic DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), 1081653ced07SKONRAD Frederic DEFINE_PROP_END_OF_LIST(), 1082653ced07SKONRAD Frederic }; 1083653ced07SKONRAD Frederic 1084653ced07SKONRAD Frederic static int virtio_blk_pci_init(VirtIOPCIProxy *vpci_dev) 1085653ced07SKONRAD Frederic { 1086653ced07SKONRAD Frederic VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(vpci_dev); 1087653ced07SKONRAD Frederic DeviceState *vdev = DEVICE(&dev->vdev); 1088653ced07SKONRAD Frederic qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); 1089653ced07SKONRAD Frederic if (qdev_init(vdev) < 0) { 1090653ced07SKONRAD Frederic return -1; 1091653ced07SKONRAD Frederic } 1092653ced07SKONRAD Frederic return 0; 1093653ced07SKONRAD Frederic } 1094653ced07SKONRAD Frederic 1095653ced07SKONRAD Frederic static void virtio_blk_pci_class_init(ObjectClass *klass, void *data) 1096653ced07SKONRAD Frederic { 1097653ced07SKONRAD Frederic DeviceClass *dc = DEVICE_CLASS(klass); 1098653ced07SKONRAD Frederic VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); 1099653ced07SKONRAD Frederic PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); 1100653ced07SKONRAD Frederic 1101125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 1102653ced07SKONRAD Frederic dc->props = virtio_blk_pci_properties; 1103653ced07SKONRAD Frederic k->init = virtio_blk_pci_init; 1104653ced07SKONRAD Frederic pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 1105653ced07SKONRAD Frederic pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BLOCK; 1106653ced07SKONRAD Frederic pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; 1107653ced07SKONRAD Frederic pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI; 1108653ced07SKONRAD Frederic } 1109653ced07SKONRAD Frederic 1110653ced07SKONRAD Frederic static void virtio_blk_pci_instance_init(Object *obj) 1111653ced07SKONRAD Frederic { 1112653ced07SKONRAD Frederic VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(obj); 1113c8075cafSGonglei 1114c8075cafSGonglei virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), 1115c8075cafSGonglei TYPE_VIRTIO_BLK); 1116467b3f33SStefan Hajnoczi object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev),"iothread", 1117467b3f33SStefan Hajnoczi &error_abort); 1118aeb98ddcSGonglei object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), 1119aeb98ddcSGonglei "bootindex", &error_abort); 1120653ced07SKONRAD Frederic } 1121653ced07SKONRAD Frederic 1122653ced07SKONRAD Frederic static const TypeInfo virtio_blk_pci_info = { 1123653ced07SKONRAD Frederic .name = TYPE_VIRTIO_BLK_PCI, 1124653ced07SKONRAD Frederic .parent = TYPE_VIRTIO_PCI, 1125653ced07SKONRAD Frederic .instance_size = sizeof(VirtIOBlkPCI), 1126653ced07SKONRAD Frederic .instance_init = virtio_blk_pci_instance_init, 1127653ced07SKONRAD Frederic .class_init = virtio_blk_pci_class_init, 1128653ced07SKONRAD Frederic }; 1129653ced07SKONRAD Frederic 1130bc7b90a0SKONRAD Frederic /* virtio-scsi-pci */ 1131bc7b90a0SKONRAD Frederic 1132bc7b90a0SKONRAD Frederic static Property virtio_scsi_pci_properties[] = { 1133bc7b90a0SKONRAD Frederic DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, 1134bc7b90a0SKONRAD Frederic VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), 1135bc7b90a0SKONRAD Frederic DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 1136bc7b90a0SKONRAD Frederic DEV_NVECTORS_UNSPECIFIED), 1137bc7b90a0SKONRAD Frederic DEFINE_VIRTIO_SCSI_FEATURES(VirtIOPCIProxy, host_features), 1138bc7b90a0SKONRAD Frederic DEFINE_PROP_END_OF_LIST(), 1139bc7b90a0SKONRAD Frederic }; 1140bc7b90a0SKONRAD Frederic 1141bc7b90a0SKONRAD Frederic static int virtio_scsi_pci_init_pci(VirtIOPCIProxy *vpci_dev) 1142bc7b90a0SKONRAD Frederic { 1143bc7b90a0SKONRAD Frederic VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(vpci_dev); 1144bc7b90a0SKONRAD Frederic DeviceState *vdev = DEVICE(&dev->vdev); 1145292c8e50SPaolo Bonzini VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev); 11466f32a6b4SKONRAD Frederic DeviceState *proxy = DEVICE(vpci_dev); 11476f32a6b4SKONRAD Frederic char *bus_name; 1148bc7b90a0SKONRAD Frederic 1149bc7b90a0SKONRAD Frederic if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { 1150292c8e50SPaolo Bonzini vpci_dev->nvectors = vs->conf.num_queues + 3; 1151bc7b90a0SKONRAD Frederic } 1152bc7b90a0SKONRAD Frederic 11536f32a6b4SKONRAD Frederic /* 11546f32a6b4SKONRAD Frederic * For command line compatibility, this sets the virtio-scsi-device bus 11556f32a6b4SKONRAD Frederic * name as before. 11566f32a6b4SKONRAD Frederic */ 11576f32a6b4SKONRAD Frederic if (proxy->id) { 11586f32a6b4SKONRAD Frederic bus_name = g_strdup_printf("%s.0", proxy->id); 11596f32a6b4SKONRAD Frederic virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name); 11606f32a6b4SKONRAD Frederic g_free(bus_name); 11616f32a6b4SKONRAD Frederic } 11626f32a6b4SKONRAD Frederic 1163bc7b90a0SKONRAD Frederic qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); 1164bc7b90a0SKONRAD Frederic if (qdev_init(vdev) < 0) { 1165bc7b90a0SKONRAD Frederic return -1; 1166bc7b90a0SKONRAD Frederic } 1167bc7b90a0SKONRAD Frederic return 0; 1168bc7b90a0SKONRAD Frederic } 1169bc7b90a0SKONRAD Frederic 1170bc7b90a0SKONRAD Frederic static void virtio_scsi_pci_class_init(ObjectClass *klass, void *data) 1171bc7b90a0SKONRAD Frederic { 1172bc7b90a0SKONRAD Frederic DeviceClass *dc = DEVICE_CLASS(klass); 1173bc7b90a0SKONRAD Frederic VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); 1174bc7b90a0SKONRAD Frederic PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); 1175bc7b90a0SKONRAD Frederic k->init = virtio_scsi_pci_init_pci; 1176125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 1177bc7b90a0SKONRAD Frederic dc->props = virtio_scsi_pci_properties; 1178bc7b90a0SKONRAD Frederic pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 1179bc7b90a0SKONRAD Frederic pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI; 1180bc7b90a0SKONRAD Frederic pcidev_k->revision = 0x00; 1181bc7b90a0SKONRAD Frederic pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI; 1182bc7b90a0SKONRAD Frederic } 1183bc7b90a0SKONRAD Frederic 1184bc7b90a0SKONRAD Frederic static void virtio_scsi_pci_instance_init(Object *obj) 1185bc7b90a0SKONRAD Frederic { 1186bc7b90a0SKONRAD Frederic VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(obj); 1187c8075cafSGonglei 1188c8075cafSGonglei virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), 1189c8075cafSGonglei TYPE_VIRTIO_SCSI); 119019d339f1SFam Zheng object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev), "iothread", 119119d339f1SFam Zheng &error_abort); 1192bc7b90a0SKONRAD Frederic } 1193bc7b90a0SKONRAD Frederic 1194bc7b90a0SKONRAD Frederic static const TypeInfo virtio_scsi_pci_info = { 1195bc7b90a0SKONRAD Frederic .name = TYPE_VIRTIO_SCSI_PCI, 1196bc7b90a0SKONRAD Frederic .parent = TYPE_VIRTIO_PCI, 1197bc7b90a0SKONRAD Frederic .instance_size = sizeof(VirtIOSCSIPCI), 1198bc7b90a0SKONRAD Frederic .instance_init = virtio_scsi_pci_instance_init, 1199bc7b90a0SKONRAD Frederic .class_init = virtio_scsi_pci_class_init, 1200bc7b90a0SKONRAD Frederic }; 1201bc7b90a0SKONRAD Frederic 120250787628SNicholas Bellinger /* vhost-scsi-pci */ 120350787628SNicholas Bellinger 120450787628SNicholas Bellinger #ifdef CONFIG_VHOST_SCSI 120550787628SNicholas Bellinger static Property vhost_scsi_pci_properties[] = { 120650787628SNicholas Bellinger DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 120750787628SNicholas Bellinger DEV_NVECTORS_UNSPECIFIED), 120850787628SNicholas Bellinger DEFINE_PROP_END_OF_LIST(), 120950787628SNicholas Bellinger }; 121050787628SNicholas Bellinger 121150787628SNicholas Bellinger static int vhost_scsi_pci_init_pci(VirtIOPCIProxy *vpci_dev) 121250787628SNicholas Bellinger { 121350787628SNicholas Bellinger VHostSCSIPCI *dev = VHOST_SCSI_PCI(vpci_dev); 121450787628SNicholas Bellinger DeviceState *vdev = DEVICE(&dev->vdev); 121550787628SNicholas Bellinger VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev); 121650787628SNicholas Bellinger 121750787628SNicholas Bellinger if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { 121850787628SNicholas Bellinger vpci_dev->nvectors = vs->conf.num_queues + 3; 121950787628SNicholas Bellinger } 122050787628SNicholas Bellinger 122150787628SNicholas Bellinger qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); 122250787628SNicholas Bellinger if (qdev_init(vdev) < 0) { 122350787628SNicholas Bellinger return -1; 122450787628SNicholas Bellinger } 122550787628SNicholas Bellinger return 0; 122650787628SNicholas Bellinger } 122750787628SNicholas Bellinger 122850787628SNicholas Bellinger static void vhost_scsi_pci_class_init(ObjectClass *klass, void *data) 122950787628SNicholas Bellinger { 123050787628SNicholas Bellinger DeviceClass *dc = DEVICE_CLASS(klass); 123150787628SNicholas Bellinger VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); 123250787628SNicholas Bellinger PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); 123350787628SNicholas Bellinger k->init = vhost_scsi_pci_init_pci; 1234125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 123550787628SNicholas Bellinger dc->props = vhost_scsi_pci_properties; 123650787628SNicholas Bellinger pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 123750787628SNicholas Bellinger pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI; 123850787628SNicholas Bellinger pcidev_k->revision = 0x00; 123950787628SNicholas Bellinger pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI; 124050787628SNicholas Bellinger } 124150787628SNicholas Bellinger 124250787628SNicholas Bellinger static void vhost_scsi_pci_instance_init(Object *obj) 124350787628SNicholas Bellinger { 124450787628SNicholas Bellinger VHostSCSIPCI *dev = VHOST_SCSI_PCI(obj); 1245c8075cafSGonglei 1246c8075cafSGonglei virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), 1247c8075cafSGonglei TYPE_VHOST_SCSI); 124850787628SNicholas Bellinger } 124950787628SNicholas Bellinger 125050787628SNicholas Bellinger static const TypeInfo vhost_scsi_pci_info = { 125150787628SNicholas Bellinger .name = TYPE_VHOST_SCSI_PCI, 125250787628SNicholas Bellinger .parent = TYPE_VIRTIO_PCI, 125350787628SNicholas Bellinger .instance_size = sizeof(VHostSCSIPCI), 125450787628SNicholas Bellinger .instance_init = vhost_scsi_pci_instance_init, 125550787628SNicholas Bellinger .class_init = vhost_scsi_pci_class_init, 125650787628SNicholas Bellinger }; 125750787628SNicholas Bellinger #endif 125850787628SNicholas Bellinger 1259e378e88dSKONRAD Frederic /* virtio-balloon-pci */ 1260e378e88dSKONRAD Frederic 126124a6e7f4SKONRAD Frederic static void balloon_pci_stats_get_all(Object *obj, struct Visitor *v, 126224a6e7f4SKONRAD Frederic void *opaque, const char *name, 126324a6e7f4SKONRAD Frederic Error **errp) 126424a6e7f4SKONRAD Frederic { 126524a6e7f4SKONRAD Frederic VirtIOBalloonPCI *dev = opaque; 126624a6e7f4SKONRAD Frederic object_property_get(OBJECT(&dev->vdev), v, "guest-stats", errp); 126724a6e7f4SKONRAD Frederic } 126824a6e7f4SKONRAD Frederic 126924a6e7f4SKONRAD Frederic static void balloon_pci_stats_get_poll_interval(Object *obj, struct Visitor *v, 127024a6e7f4SKONRAD Frederic void *opaque, const char *name, 127124a6e7f4SKONRAD Frederic Error **errp) 127224a6e7f4SKONRAD Frederic { 127324a6e7f4SKONRAD Frederic VirtIOBalloonPCI *dev = opaque; 127424a6e7f4SKONRAD Frederic object_property_get(OBJECT(&dev->vdev), v, "guest-stats-polling-interval", 127524a6e7f4SKONRAD Frederic errp); 127624a6e7f4SKONRAD Frederic } 127724a6e7f4SKONRAD Frederic 127824a6e7f4SKONRAD Frederic static void balloon_pci_stats_set_poll_interval(Object *obj, struct Visitor *v, 127924a6e7f4SKONRAD Frederic void *opaque, const char *name, 128024a6e7f4SKONRAD Frederic Error **errp) 128124a6e7f4SKONRAD Frederic { 128224a6e7f4SKONRAD Frederic VirtIOBalloonPCI *dev = opaque; 128324a6e7f4SKONRAD Frederic object_property_set(OBJECT(&dev->vdev), v, "guest-stats-polling-interval", 128424a6e7f4SKONRAD Frederic errp); 128524a6e7f4SKONRAD Frederic } 128624a6e7f4SKONRAD Frederic 1287e378e88dSKONRAD Frederic static Property virtio_balloon_pci_properties[] = { 1288c7bcc85dSPaolo Bonzini DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), 1289e378e88dSKONRAD Frederic DEFINE_PROP_END_OF_LIST(), 1290e378e88dSKONRAD Frederic }; 1291e378e88dSKONRAD Frederic 1292e378e88dSKONRAD Frederic static int virtio_balloon_pci_init(VirtIOPCIProxy *vpci_dev) 1293e378e88dSKONRAD Frederic { 1294e378e88dSKONRAD Frederic VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(vpci_dev); 1295e378e88dSKONRAD Frederic DeviceState *vdev = DEVICE(&dev->vdev); 1296e378e88dSKONRAD Frederic 1297e378e88dSKONRAD Frederic if (vpci_dev->class_code != PCI_CLASS_OTHERS && 1298e378e88dSKONRAD Frederic vpci_dev->class_code != PCI_CLASS_MEMORY_RAM) { /* qemu < 1.1 */ 1299e378e88dSKONRAD Frederic vpci_dev->class_code = PCI_CLASS_OTHERS; 1300e378e88dSKONRAD Frederic } 1301e378e88dSKONRAD Frederic 1302e378e88dSKONRAD Frederic qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); 1303e378e88dSKONRAD Frederic if (qdev_init(vdev) < 0) { 1304e378e88dSKONRAD Frederic return -1; 1305e378e88dSKONRAD Frederic } 1306e378e88dSKONRAD Frederic return 0; 1307e378e88dSKONRAD Frederic } 1308e378e88dSKONRAD Frederic 1309e378e88dSKONRAD Frederic static void virtio_balloon_pci_class_init(ObjectClass *klass, void *data) 1310e378e88dSKONRAD Frederic { 1311e378e88dSKONRAD Frederic DeviceClass *dc = DEVICE_CLASS(klass); 1312e378e88dSKONRAD Frederic VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); 1313e378e88dSKONRAD Frederic PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); 1314e378e88dSKONRAD Frederic k->init = virtio_balloon_pci_init; 1315125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_MISC, dc->categories); 1316e378e88dSKONRAD Frederic dc->props = virtio_balloon_pci_properties; 1317e378e88dSKONRAD Frederic pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 1318e378e88dSKONRAD Frederic pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON; 1319e378e88dSKONRAD Frederic pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; 1320e378e88dSKONRAD Frederic pcidev_k->class_id = PCI_CLASS_OTHERS; 1321e378e88dSKONRAD Frederic } 1322e378e88dSKONRAD Frederic 1323e378e88dSKONRAD Frederic static void virtio_balloon_pci_instance_init(Object *obj) 1324e378e88dSKONRAD Frederic { 1325e378e88dSKONRAD Frederic VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(obj); 1326213f0c4fSAndreas Färber object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BALLOON); 1327e378e88dSKONRAD Frederic object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); 132891ba2120SGonglei object_unref(OBJECT(&dev->vdev)); 132924a6e7f4SKONRAD Frederic object_property_add(obj, "guest-stats", "guest statistics", 133024a6e7f4SKONRAD Frederic balloon_pci_stats_get_all, NULL, NULL, dev, 133124a6e7f4SKONRAD Frederic NULL); 133224a6e7f4SKONRAD Frederic 133324a6e7f4SKONRAD Frederic object_property_add(obj, "guest-stats-polling-interval", "int", 133424a6e7f4SKONRAD Frederic balloon_pci_stats_get_poll_interval, 133524a6e7f4SKONRAD Frederic balloon_pci_stats_set_poll_interval, 133624a6e7f4SKONRAD Frederic NULL, dev, NULL); 1337e378e88dSKONRAD Frederic } 1338e378e88dSKONRAD Frederic 1339e378e88dSKONRAD Frederic static const TypeInfo virtio_balloon_pci_info = { 1340e378e88dSKONRAD Frederic .name = TYPE_VIRTIO_BALLOON_PCI, 1341e378e88dSKONRAD Frederic .parent = TYPE_VIRTIO_PCI, 1342e378e88dSKONRAD Frederic .instance_size = sizeof(VirtIOBalloonPCI), 1343e378e88dSKONRAD Frederic .instance_init = virtio_balloon_pci_instance_init, 1344e378e88dSKONRAD Frederic .class_init = virtio_balloon_pci_class_init, 1345e378e88dSKONRAD Frederic }; 1346e378e88dSKONRAD Frederic 1347f7f7464aSKONRAD Frederic /* virtio-serial-pci */ 1348f7f7464aSKONRAD Frederic 1349f7f7464aSKONRAD Frederic static int virtio_serial_pci_init(VirtIOPCIProxy *vpci_dev) 1350f7f7464aSKONRAD Frederic { 1351f7f7464aSKONRAD Frederic VirtIOSerialPCI *dev = VIRTIO_SERIAL_PCI(vpci_dev); 1352f7f7464aSKONRAD Frederic DeviceState *vdev = DEVICE(&dev->vdev); 135380270a19SKONRAD Frederic DeviceState *proxy = DEVICE(vpci_dev); 135480270a19SKONRAD Frederic char *bus_name; 1355f7f7464aSKONRAD Frederic 1356f7f7464aSKONRAD Frederic if (vpci_dev->class_code != PCI_CLASS_COMMUNICATION_OTHER && 1357f7f7464aSKONRAD Frederic vpci_dev->class_code != PCI_CLASS_DISPLAY_OTHER && /* qemu 0.10 */ 1358f7f7464aSKONRAD Frederic vpci_dev->class_code != PCI_CLASS_OTHERS) { /* qemu-kvm */ 1359f7f7464aSKONRAD Frederic vpci_dev->class_code = PCI_CLASS_COMMUNICATION_OTHER; 1360f7f7464aSKONRAD Frederic } 1361f7f7464aSKONRAD Frederic 1362f7f7464aSKONRAD Frederic /* backwards-compatibility with machines that were created with 1363f7f7464aSKONRAD Frederic DEV_NVECTORS_UNSPECIFIED */ 1364f7f7464aSKONRAD Frederic if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { 1365f7f7464aSKONRAD Frederic vpci_dev->nvectors = dev->vdev.serial.max_virtserial_ports + 1; 1366f7f7464aSKONRAD Frederic } 1367f7f7464aSKONRAD Frederic 136880270a19SKONRAD Frederic /* 136980270a19SKONRAD Frederic * For command line compatibility, this sets the virtio-serial-device bus 137080270a19SKONRAD Frederic * name as before. 137180270a19SKONRAD Frederic */ 137280270a19SKONRAD Frederic if (proxy->id) { 137380270a19SKONRAD Frederic bus_name = g_strdup_printf("%s.0", proxy->id); 137480270a19SKONRAD Frederic virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name); 137580270a19SKONRAD Frederic g_free(bus_name); 137680270a19SKONRAD Frederic } 137780270a19SKONRAD Frederic 1378f7f7464aSKONRAD Frederic qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); 1379f7f7464aSKONRAD Frederic if (qdev_init(vdev) < 0) { 1380f7f7464aSKONRAD Frederic return -1; 1381f7f7464aSKONRAD Frederic } 1382f7f7464aSKONRAD Frederic return 0; 1383f7f7464aSKONRAD Frederic } 1384f7f7464aSKONRAD Frederic 1385f7f7464aSKONRAD Frederic static Property virtio_serial_pci_properties[] = { 1386f7f7464aSKONRAD Frederic DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, 1387f7f7464aSKONRAD Frederic VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), 1388f7f7464aSKONRAD Frederic DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), 1389c7bcc85dSPaolo Bonzini DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), 1390f7f7464aSKONRAD Frederic DEFINE_PROP_END_OF_LIST(), 1391f7f7464aSKONRAD Frederic }; 1392f7f7464aSKONRAD Frederic 1393f7f7464aSKONRAD Frederic static void virtio_serial_pci_class_init(ObjectClass *klass, void *data) 1394f7f7464aSKONRAD Frederic { 1395f7f7464aSKONRAD Frederic DeviceClass *dc = DEVICE_CLASS(klass); 1396f7f7464aSKONRAD Frederic VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); 1397f7f7464aSKONRAD Frederic PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); 1398f7f7464aSKONRAD Frederic k->init = virtio_serial_pci_init; 1399125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_INPUT, dc->categories); 1400f7f7464aSKONRAD Frederic dc->props = virtio_serial_pci_properties; 1401f7f7464aSKONRAD Frederic pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 1402f7f7464aSKONRAD Frederic pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE; 1403f7f7464aSKONRAD Frederic pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; 1404f7f7464aSKONRAD Frederic pcidev_k->class_id = PCI_CLASS_COMMUNICATION_OTHER; 1405f7f7464aSKONRAD Frederic } 1406f7f7464aSKONRAD Frederic 1407f7f7464aSKONRAD Frederic static void virtio_serial_pci_instance_init(Object *obj) 1408f7f7464aSKONRAD Frederic { 1409f7f7464aSKONRAD Frederic VirtIOSerialPCI *dev = VIRTIO_SERIAL_PCI(obj); 1410c8075cafSGonglei 1411c8075cafSGonglei virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), 1412c8075cafSGonglei TYPE_VIRTIO_SERIAL); 1413f7f7464aSKONRAD Frederic } 1414f7f7464aSKONRAD Frederic 1415f7f7464aSKONRAD Frederic static const TypeInfo virtio_serial_pci_info = { 1416f7f7464aSKONRAD Frederic .name = TYPE_VIRTIO_SERIAL_PCI, 1417f7f7464aSKONRAD Frederic .parent = TYPE_VIRTIO_PCI, 1418f7f7464aSKONRAD Frederic .instance_size = sizeof(VirtIOSerialPCI), 1419f7f7464aSKONRAD Frederic .instance_init = virtio_serial_pci_instance_init, 1420f7f7464aSKONRAD Frederic .class_init = virtio_serial_pci_class_init, 1421f7f7464aSKONRAD Frederic }; 1422f7f7464aSKONRAD Frederic 1423e37da394SKONRAD Frederic /* virtio-net-pci */ 1424e37da394SKONRAD Frederic 1425e37da394SKONRAD Frederic static Property virtio_net_properties[] = { 1426e37da394SKONRAD Frederic DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, 1427e37da394SKONRAD Frederic VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false), 1428e37da394SKONRAD Frederic DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3), 1429e37da394SKONRAD Frederic DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features), 1430e37da394SKONRAD Frederic DEFINE_PROP_END_OF_LIST(), 1431e37da394SKONRAD Frederic }; 1432e37da394SKONRAD Frederic 1433e37da394SKONRAD Frederic static int virtio_net_pci_init(VirtIOPCIProxy *vpci_dev) 1434e37da394SKONRAD Frederic { 1435800ced8cSKONRAD Frederic DeviceState *qdev = DEVICE(vpci_dev); 1436e37da394SKONRAD Frederic VirtIONetPCI *dev = VIRTIO_NET_PCI(vpci_dev); 1437e37da394SKONRAD Frederic DeviceState *vdev = DEVICE(&dev->vdev); 1438e37da394SKONRAD Frederic 1439e37da394SKONRAD Frederic virtio_net_set_config_size(&dev->vdev, vpci_dev->host_features); 1440800ced8cSKONRAD Frederic virtio_net_set_netclient_name(&dev->vdev, qdev->id, 1441800ced8cSKONRAD Frederic object_get_typename(OBJECT(qdev))); 1442e37da394SKONRAD Frederic qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); 1443e37da394SKONRAD Frederic if (qdev_init(vdev) < 0) { 1444e37da394SKONRAD Frederic return -1; 1445e37da394SKONRAD Frederic } 1446e37da394SKONRAD Frederic return 0; 1447e37da394SKONRAD Frederic } 1448e37da394SKONRAD Frederic 1449e37da394SKONRAD Frederic static void virtio_net_pci_class_init(ObjectClass *klass, void *data) 1450e37da394SKONRAD Frederic { 1451e37da394SKONRAD Frederic DeviceClass *dc = DEVICE_CLASS(klass); 1452e37da394SKONRAD Frederic PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 1453e37da394SKONRAD Frederic VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass); 1454e37da394SKONRAD Frederic 1455e37da394SKONRAD Frederic k->romfile = "efi-virtio.rom"; 1456e37da394SKONRAD Frederic k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 1457e37da394SKONRAD Frederic k->device_id = PCI_DEVICE_ID_VIRTIO_NET; 1458e37da394SKONRAD Frederic k->revision = VIRTIO_PCI_ABI_VERSION; 1459e37da394SKONRAD Frederic k->class_id = PCI_CLASS_NETWORK_ETHERNET; 1460125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); 1461e37da394SKONRAD Frederic dc->props = virtio_net_properties; 1462e37da394SKONRAD Frederic vpciklass->init = virtio_net_pci_init; 1463e37da394SKONRAD Frederic } 1464e37da394SKONRAD Frederic 1465e37da394SKONRAD Frederic static void virtio_net_pci_instance_init(Object *obj) 1466e37da394SKONRAD Frederic { 1467e37da394SKONRAD Frederic VirtIONetPCI *dev = VIRTIO_NET_PCI(obj); 1468c8075cafSGonglei 1469c8075cafSGonglei virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), 1470c8075cafSGonglei TYPE_VIRTIO_NET); 14710cf63c3eSGonglei object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), 14720cf63c3eSGonglei "bootindex", &error_abort); 1473e37da394SKONRAD Frederic } 1474e37da394SKONRAD Frederic 1475e37da394SKONRAD Frederic static const TypeInfo virtio_net_pci_info = { 1476e37da394SKONRAD Frederic .name = TYPE_VIRTIO_NET_PCI, 1477e37da394SKONRAD Frederic .parent = TYPE_VIRTIO_PCI, 1478e37da394SKONRAD Frederic .instance_size = sizeof(VirtIONetPCI), 1479e37da394SKONRAD Frederic .instance_init = virtio_net_pci_instance_init, 1480e37da394SKONRAD Frederic .class_init = virtio_net_pci_class_init, 1481e37da394SKONRAD Frederic }; 1482e37da394SKONRAD Frederic 148359ccd20aSKONRAD Frederic /* virtio-rng-pci */ 148459ccd20aSKONRAD Frederic 148559ccd20aSKONRAD Frederic static Property virtio_rng_pci_properties[] = { 148659ccd20aSKONRAD Frederic DEFINE_PROP_END_OF_LIST(), 148759ccd20aSKONRAD Frederic }; 148859ccd20aSKONRAD Frederic 148959ccd20aSKONRAD Frederic static int virtio_rng_pci_init(VirtIOPCIProxy *vpci_dev) 149059ccd20aSKONRAD Frederic { 149159ccd20aSKONRAD Frederic VirtIORngPCI *vrng = VIRTIO_RNG_PCI(vpci_dev); 149259ccd20aSKONRAD Frederic DeviceState *vdev = DEVICE(&vrng->vdev); 149359ccd20aSKONRAD Frederic 149459ccd20aSKONRAD Frederic qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); 149559ccd20aSKONRAD Frederic if (qdev_init(vdev) < 0) { 149659ccd20aSKONRAD Frederic return -1; 149759ccd20aSKONRAD Frederic } 149859ccd20aSKONRAD Frederic 149959ccd20aSKONRAD Frederic object_property_set_link(OBJECT(vrng), 15005b456438SCole Robinson OBJECT(vrng->vdev.conf.rng), "rng", 150159ccd20aSKONRAD Frederic NULL); 150259ccd20aSKONRAD Frederic 150359ccd20aSKONRAD Frederic return 0; 150459ccd20aSKONRAD Frederic } 150559ccd20aSKONRAD Frederic 150659ccd20aSKONRAD Frederic static void virtio_rng_pci_class_init(ObjectClass *klass, void *data) 150759ccd20aSKONRAD Frederic { 150859ccd20aSKONRAD Frederic DeviceClass *dc = DEVICE_CLASS(klass); 150959ccd20aSKONRAD Frederic VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); 151059ccd20aSKONRAD Frederic PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); 151159ccd20aSKONRAD Frederic 151259ccd20aSKONRAD Frederic k->init = virtio_rng_pci_init; 1513125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_MISC, dc->categories); 151459ccd20aSKONRAD Frederic dc->props = virtio_rng_pci_properties; 151559ccd20aSKONRAD Frederic 151659ccd20aSKONRAD Frederic pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 151759ccd20aSKONRAD Frederic pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_RNG; 151859ccd20aSKONRAD Frederic pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; 151959ccd20aSKONRAD Frederic pcidev_k->class_id = PCI_CLASS_OTHERS; 152059ccd20aSKONRAD Frederic } 152159ccd20aSKONRAD Frederic 152259ccd20aSKONRAD Frederic static void virtio_rng_initfn(Object *obj) 152359ccd20aSKONRAD Frederic { 152459ccd20aSKONRAD Frederic VirtIORngPCI *dev = VIRTIO_RNG_PCI(obj); 1525c8075cafSGonglei 1526c8075cafSGonglei virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), 1527c8075cafSGonglei TYPE_VIRTIO_RNG); 152859ccd20aSKONRAD Frederic object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, 15299561fda8SStefan Hajnoczi (Object **)&dev->vdev.conf.rng, 153039f72ef9SStefan Hajnoczi qdev_prop_allow_set_link_before_realize, 15319561fda8SStefan Hajnoczi OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL); 153259ccd20aSKONRAD Frederic 153359ccd20aSKONRAD Frederic } 153459ccd20aSKONRAD Frederic 153559ccd20aSKONRAD Frederic static const TypeInfo virtio_rng_pci_info = { 153659ccd20aSKONRAD Frederic .name = TYPE_VIRTIO_RNG_PCI, 153759ccd20aSKONRAD Frederic .parent = TYPE_VIRTIO_PCI, 153859ccd20aSKONRAD Frederic .instance_size = sizeof(VirtIORngPCI), 153959ccd20aSKONRAD Frederic .instance_init = virtio_rng_initfn, 154059ccd20aSKONRAD Frederic .class_init = virtio_rng_pci_class_init, 154159ccd20aSKONRAD Frederic }; 154259ccd20aSKONRAD Frederic 15430a2acf5eSKONRAD Frederic /* virtio-pci-bus */ 15440a2acf5eSKONRAD Frederic 1545ac7af112SAndreas Färber static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, 1546ac7af112SAndreas Färber VirtIOPCIProxy *dev) 15470a2acf5eSKONRAD Frederic { 15480a2acf5eSKONRAD Frederic DeviceState *qdev = DEVICE(dev); 1549f4dd69aaSKONRAD Frederic char virtio_bus_name[] = "virtio-bus"; 1550f4dd69aaSKONRAD Frederic 1551fb17dfe0SAndreas Färber qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_PCI_BUS, qdev, 1552f4dd69aaSKONRAD Frederic virtio_bus_name); 15530a2acf5eSKONRAD Frederic } 15540a2acf5eSKONRAD Frederic 15550a2acf5eSKONRAD Frederic static void virtio_pci_bus_class_init(ObjectClass *klass, void *data) 15560a2acf5eSKONRAD Frederic { 15570a2acf5eSKONRAD Frederic BusClass *bus_class = BUS_CLASS(klass); 15580a2acf5eSKONRAD Frederic VirtioBusClass *k = VIRTIO_BUS_CLASS(klass); 15590a2acf5eSKONRAD Frederic bus_class->max_dev = 1; 15600a2acf5eSKONRAD Frederic k->notify = virtio_pci_notify; 15610a2acf5eSKONRAD Frederic k->save_config = virtio_pci_save_config; 15620a2acf5eSKONRAD Frederic k->load_config = virtio_pci_load_config; 15630a2acf5eSKONRAD Frederic k->save_queue = virtio_pci_save_queue; 15640a2acf5eSKONRAD Frederic k->load_queue = virtio_pci_load_queue; 15650a2acf5eSKONRAD Frederic k->get_features = virtio_pci_get_features; 15660a2acf5eSKONRAD Frederic k->query_guest_notifiers = virtio_pci_query_guest_notifiers; 15670a2acf5eSKONRAD Frederic k->set_host_notifier = virtio_pci_set_host_notifier; 15680a2acf5eSKONRAD Frederic k->set_guest_notifiers = virtio_pci_set_guest_notifiers; 15690a2acf5eSKONRAD Frederic k->vmstate_change = virtio_pci_vmstate_change; 1570085bccb7SKONRAD Frederic k->device_plugged = virtio_pci_device_plugged; 157106a13073SPaolo Bonzini k->device_unplugged = virtio_pci_device_unplugged; 15720a2acf5eSKONRAD Frederic } 15730a2acf5eSKONRAD Frederic 15740a2acf5eSKONRAD Frederic static const TypeInfo virtio_pci_bus_info = { 15750a2acf5eSKONRAD Frederic .name = TYPE_VIRTIO_PCI_BUS, 15760a2acf5eSKONRAD Frederic .parent = TYPE_VIRTIO_BUS, 15770a2acf5eSKONRAD Frederic .instance_size = sizeof(VirtioPCIBusState), 15780a2acf5eSKONRAD Frederic .class_init = virtio_pci_bus_class_init, 15790a2acf5eSKONRAD Frederic }; 15800a2acf5eSKONRAD Frederic 158183f7d43aSAndreas Färber static void virtio_pci_register_types(void) 158253c25ceaSPaul Brook { 158359ccd20aSKONRAD Frederic type_register_static(&virtio_rng_pci_info); 15840a2acf5eSKONRAD Frederic type_register_static(&virtio_pci_bus_info); 1585085bccb7SKONRAD Frederic type_register_static(&virtio_pci_info); 158660653b28SPaolo Bonzini #ifdef CONFIG_VIRTFS 1587234a336fSKONRAD Frederic type_register_static(&virtio_9p_pci_info); 158860653b28SPaolo Bonzini #endif 1589653ced07SKONRAD Frederic type_register_static(&virtio_blk_pci_info); 1590bc7b90a0SKONRAD Frederic type_register_static(&virtio_scsi_pci_info); 1591e378e88dSKONRAD Frederic type_register_static(&virtio_balloon_pci_info); 1592f7f7464aSKONRAD Frederic type_register_static(&virtio_serial_pci_info); 1593e37da394SKONRAD Frederic type_register_static(&virtio_net_pci_info); 159450787628SNicholas Bellinger #ifdef CONFIG_VHOST_SCSI 159550787628SNicholas Bellinger type_register_static(&vhost_scsi_pci_info); 159650787628SNicholas Bellinger #endif 159753c25ceaSPaul Brook } 159853c25ceaSPaul Brook 159983f7d43aSAndreas Färber type_init(virtio_pci_register_types) 1600