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" 329c17d615SPaolo Bonzini #include "sysemu/blockdev.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 89ac7af112SAndreas Färber static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, 90ac7af112SAndreas Färber VirtIOPCIProxy *dev); 91d51fcfacSKONRAD Frederic 9253c25ceaSPaul Brook /* virtio device */ 93d2a0ccc6SMichael S. Tsirkin /* DeviceState to VirtIOPCIProxy. For use off data-path. TODO: use QOM. */ 94d2a0ccc6SMichael S. Tsirkin static inline VirtIOPCIProxy *to_virtio_pci_proxy(DeviceState *d) 9553c25ceaSPaul Brook { 96d2a0ccc6SMichael S. Tsirkin return container_of(d, VirtIOPCIProxy, pci_dev.qdev); 97d2a0ccc6SMichael S. Tsirkin } 98d2a0ccc6SMichael S. Tsirkin 99d2a0ccc6SMichael S. Tsirkin /* DeviceState to VirtIOPCIProxy. Note: used on datapath, 100d2a0ccc6SMichael S. Tsirkin * be careful and test performance if you change this. 101d2a0ccc6SMichael S. Tsirkin */ 102d2a0ccc6SMichael S. Tsirkin static inline VirtIOPCIProxy *to_virtio_pci_proxy_fast(DeviceState *d) 103d2a0ccc6SMichael S. Tsirkin { 104d2a0ccc6SMichael S. Tsirkin return container_of(d, VirtIOPCIProxy, pci_dev.qdev); 105d2a0ccc6SMichael S. Tsirkin } 106d2a0ccc6SMichael S. Tsirkin 107d2a0ccc6SMichael S. Tsirkin static void virtio_pci_notify(DeviceState *d, uint16_t vector) 108d2a0ccc6SMichael S. Tsirkin { 109d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy_fast(d); 110a3fc66d9SPaolo Bonzini 111aba800a3SMichael S. Tsirkin if (msix_enabled(&proxy->pci_dev)) 112aba800a3SMichael S. Tsirkin msix_notify(&proxy->pci_dev, vector); 113a3fc66d9SPaolo Bonzini else { 114a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 115a3fc66d9SPaolo Bonzini pci_set_irq(&proxy->pci_dev, vdev->isr & 1); 116a3fc66d9SPaolo Bonzini } 11753c25ceaSPaul Brook } 11853c25ceaSPaul Brook 119d2a0ccc6SMichael S. Tsirkin static void virtio_pci_save_config(DeviceState *d, QEMUFile *f) 120ff24bd58SMichael S. Tsirkin { 121d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 122a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 123a3fc66d9SPaolo Bonzini 124ff24bd58SMichael S. Tsirkin pci_device_save(&proxy->pci_dev, f); 125ff24bd58SMichael S. Tsirkin msix_save(&proxy->pci_dev, f); 126ff24bd58SMichael S. Tsirkin if (msix_present(&proxy->pci_dev)) 127a3fc66d9SPaolo Bonzini qemu_put_be16(f, vdev->config_vector); 128ff24bd58SMichael S. Tsirkin } 129ff24bd58SMichael S. Tsirkin 130d2a0ccc6SMichael S. Tsirkin static void virtio_pci_save_queue(DeviceState *d, int n, QEMUFile *f) 131ff24bd58SMichael S. Tsirkin { 132d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 133a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 134a3fc66d9SPaolo Bonzini 135ff24bd58SMichael S. Tsirkin if (msix_present(&proxy->pci_dev)) 136a3fc66d9SPaolo Bonzini qemu_put_be16(f, virtio_queue_vector(vdev, n)); 137ff24bd58SMichael S. Tsirkin } 138ff24bd58SMichael S. Tsirkin 139d2a0ccc6SMichael S. Tsirkin static int virtio_pci_load_config(DeviceState *d, QEMUFile *f) 140ff24bd58SMichael S. Tsirkin { 141d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 142a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 143a3fc66d9SPaolo Bonzini 144ff24bd58SMichael S. Tsirkin int ret; 145ff24bd58SMichael S. Tsirkin ret = pci_device_load(&proxy->pci_dev, f); 146e6da7680SMichael S. Tsirkin if (ret) { 147ff24bd58SMichael S. Tsirkin return ret; 148e6da7680SMichael S. Tsirkin } 1493cac001eSMichael S. Tsirkin msix_unuse_all_vectors(&proxy->pci_dev); 150ff24bd58SMichael S. Tsirkin msix_load(&proxy->pci_dev, f); 151e6da7680SMichael S. Tsirkin if (msix_present(&proxy->pci_dev)) { 152a3fc66d9SPaolo Bonzini qemu_get_be16s(f, &vdev->config_vector); 153e6da7680SMichael S. Tsirkin } else { 154a3fc66d9SPaolo Bonzini vdev->config_vector = VIRTIO_NO_VECTOR; 155e6da7680SMichael S. Tsirkin } 156a3fc66d9SPaolo Bonzini if (vdev->config_vector != VIRTIO_NO_VECTOR) { 157a3fc66d9SPaolo Bonzini return msix_vector_use(&proxy->pci_dev, vdev->config_vector); 158e6da7680SMichael S. Tsirkin } 159ff24bd58SMichael S. Tsirkin return 0; 160ff24bd58SMichael S. Tsirkin } 161ff24bd58SMichael S. Tsirkin 162d2a0ccc6SMichael S. Tsirkin static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f) 163ff24bd58SMichael S. Tsirkin { 164d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 165a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 166a3fc66d9SPaolo Bonzini 167ff24bd58SMichael S. Tsirkin uint16_t vector; 168e6da7680SMichael S. Tsirkin if (msix_present(&proxy->pci_dev)) { 169ff24bd58SMichael S. Tsirkin qemu_get_be16s(f, &vector); 170e6da7680SMichael S. Tsirkin } else { 171e6da7680SMichael S. Tsirkin vector = VIRTIO_NO_VECTOR; 172e6da7680SMichael S. Tsirkin } 173a3fc66d9SPaolo Bonzini virtio_queue_set_vector(vdev, n, vector); 174e6da7680SMichael S. Tsirkin if (vector != VIRTIO_NO_VECTOR) { 175e6da7680SMichael S. Tsirkin return msix_vector_use(&proxy->pci_dev, vector); 176e6da7680SMichael S. Tsirkin } 177ff24bd58SMichael S. Tsirkin return 0; 178ff24bd58SMichael S. Tsirkin } 179ff24bd58SMichael S. Tsirkin 18025db9ebeSStefan Hajnoczi static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy, 18126b9b5feSPaolo Bonzini int n, bool assign, bool set_handler) 18225db9ebeSStefan Hajnoczi { 183a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 184a3fc66d9SPaolo Bonzini VirtQueue *vq = virtio_get_queue(vdev, n); 18525db9ebeSStefan Hajnoczi EventNotifier *notifier = virtio_queue_get_host_notifier(vq); 186da146d0aSAvi Kivity int r = 0; 187da146d0aSAvi Kivity 18825db9ebeSStefan Hajnoczi if (assign) { 18925db9ebeSStefan Hajnoczi r = event_notifier_init(notifier, 1); 19025db9ebeSStefan Hajnoczi if (r < 0) { 191b36e3914SMichael S. Tsirkin error_report("%s: unable to init event notifier: %d", 192b36e3914SMichael S. Tsirkin __func__, r); 19325db9ebeSStefan Hajnoczi return r; 19425db9ebeSStefan Hajnoczi } 19526b9b5feSPaolo Bonzini virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler); 196da146d0aSAvi Kivity memory_region_add_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2, 197753d5e14SPaolo Bonzini true, n, notifier); 19825db9ebeSStefan Hajnoczi } else { 199da146d0aSAvi Kivity memory_region_del_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2, 200753d5e14SPaolo Bonzini true, n, notifier); 20126b9b5feSPaolo Bonzini virtio_queue_set_host_notifier_fd_handler(vq, false, false); 20225db9ebeSStefan Hajnoczi event_notifier_cleanup(notifier); 20325db9ebeSStefan Hajnoczi } 20425db9ebeSStefan Hajnoczi return r; 20525db9ebeSStefan Hajnoczi } 20625db9ebeSStefan Hajnoczi 207b36e3914SMichael S. Tsirkin static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy) 20825db9ebeSStefan Hajnoczi { 209a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 21025db9ebeSStefan Hajnoczi int n, r; 21125db9ebeSStefan Hajnoczi 21225db9ebeSStefan Hajnoczi if (!(proxy->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD) || 21325db9ebeSStefan Hajnoczi proxy->ioeventfd_disabled || 21425db9ebeSStefan Hajnoczi proxy->ioeventfd_started) { 215b36e3914SMichael S. Tsirkin return; 21625db9ebeSStefan Hajnoczi } 21725db9ebeSStefan Hajnoczi 21825db9ebeSStefan Hajnoczi for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) { 219a3fc66d9SPaolo Bonzini if (!virtio_queue_get_num(vdev, n)) { 22025db9ebeSStefan Hajnoczi continue; 22125db9ebeSStefan Hajnoczi } 22225db9ebeSStefan Hajnoczi 22326b9b5feSPaolo Bonzini r = virtio_pci_set_host_notifier_internal(proxy, n, true, true); 22425db9ebeSStefan Hajnoczi if (r < 0) { 22525db9ebeSStefan Hajnoczi goto assign_error; 22625db9ebeSStefan Hajnoczi } 22725db9ebeSStefan Hajnoczi } 22825db9ebeSStefan Hajnoczi proxy->ioeventfd_started = true; 229b36e3914SMichael S. Tsirkin return; 23025db9ebeSStefan Hajnoczi 23125db9ebeSStefan Hajnoczi assign_error: 23225db9ebeSStefan Hajnoczi while (--n >= 0) { 233a3fc66d9SPaolo Bonzini if (!virtio_queue_get_num(vdev, n)) { 23425db9ebeSStefan Hajnoczi continue; 23525db9ebeSStefan Hajnoczi } 23625db9ebeSStefan Hajnoczi 23726b9b5feSPaolo Bonzini r = virtio_pci_set_host_notifier_internal(proxy, n, false, false); 238b36e3914SMichael S. Tsirkin assert(r >= 0); 23925db9ebeSStefan Hajnoczi } 24025db9ebeSStefan Hajnoczi proxy->ioeventfd_started = false; 241b36e3914SMichael S. Tsirkin error_report("%s: failed. Fallback to a userspace (slower).", __func__); 24225db9ebeSStefan Hajnoczi } 24325db9ebeSStefan Hajnoczi 244b36e3914SMichael S. Tsirkin static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy) 24525db9ebeSStefan Hajnoczi { 246a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 247b36e3914SMichael S. Tsirkin int r; 24825db9ebeSStefan Hajnoczi int n; 24925db9ebeSStefan Hajnoczi 25025db9ebeSStefan Hajnoczi if (!proxy->ioeventfd_started) { 251b36e3914SMichael S. Tsirkin return; 25225db9ebeSStefan Hajnoczi } 25325db9ebeSStefan Hajnoczi 25425db9ebeSStefan Hajnoczi for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) { 255a3fc66d9SPaolo Bonzini if (!virtio_queue_get_num(vdev, n)) { 25625db9ebeSStefan Hajnoczi continue; 25725db9ebeSStefan Hajnoczi } 25825db9ebeSStefan Hajnoczi 25926b9b5feSPaolo Bonzini r = virtio_pci_set_host_notifier_internal(proxy, n, false, false); 260b36e3914SMichael S. Tsirkin assert(r >= 0); 26125db9ebeSStefan Hajnoczi } 26225db9ebeSStefan Hajnoczi proxy->ioeventfd_started = false; 26325db9ebeSStefan Hajnoczi } 26425db9ebeSStefan Hajnoczi 26553c25ceaSPaul Brook static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) 26653c25ceaSPaul Brook { 26753c25ceaSPaul Brook VirtIOPCIProxy *proxy = opaque; 268a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 269a8170e5eSAvi Kivity hwaddr pa; 27053c25ceaSPaul Brook 27153c25ceaSPaul Brook switch (addr) { 27253c25ceaSPaul Brook case VIRTIO_PCI_GUEST_FEATURES: 27353c25ceaSPaul Brook /* Guest does not negotiate properly? We have to assume nothing. */ 27453c25ceaSPaul Brook if (val & (1 << VIRTIO_F_BAD_FEATURE)) { 275181103cdSKONRAD Frederic val = virtio_bus_get_vdev_bad_features(&proxy->bus); 27653c25ceaSPaul Brook } 277ad0c9332SPaolo Bonzini virtio_set_features(vdev, val); 27853c25ceaSPaul Brook break; 27953c25ceaSPaul Brook case VIRTIO_PCI_QUEUE_PFN: 280a8170e5eSAvi Kivity pa = (hwaddr)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT; 2811b8e9b27SMichael S. Tsirkin if (pa == 0) { 28225db9ebeSStefan Hajnoczi virtio_pci_stop_ioeventfd(proxy); 283a3fc66d9SPaolo Bonzini virtio_reset(vdev); 2841b8e9b27SMichael S. Tsirkin msix_unuse_all_vectors(&proxy->pci_dev); 2851b8e9b27SMichael S. Tsirkin } 2867055e687SMichael S. Tsirkin else 28753c25ceaSPaul Brook virtio_queue_set_addr(vdev, vdev->queue_sel, pa); 28853c25ceaSPaul Brook break; 28953c25ceaSPaul Brook case VIRTIO_PCI_QUEUE_SEL: 29053c25ceaSPaul Brook if (val < VIRTIO_PCI_QUEUE_MAX) 29153c25ceaSPaul Brook vdev->queue_sel = val; 29253c25ceaSPaul Brook break; 29353c25ceaSPaul Brook case VIRTIO_PCI_QUEUE_NOTIFY: 2947157e2e2SStefan Hajnoczi if (val < VIRTIO_PCI_QUEUE_MAX) { 29553c25ceaSPaul Brook virtio_queue_notify(vdev, val); 2967157e2e2SStefan Hajnoczi } 29753c25ceaSPaul Brook break; 29853c25ceaSPaul Brook case VIRTIO_PCI_STATUS: 29925db9ebeSStefan Hajnoczi if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) { 30025db9ebeSStefan Hajnoczi virtio_pci_stop_ioeventfd(proxy); 30125db9ebeSStefan Hajnoczi } 30225db9ebeSStefan Hajnoczi 3033e607cb5SMichael S. Tsirkin virtio_set_status(vdev, val & 0xFF); 30425db9ebeSStefan Hajnoczi 30525db9ebeSStefan Hajnoczi if (val & VIRTIO_CONFIG_S_DRIVER_OK) { 30625db9ebeSStefan Hajnoczi virtio_pci_start_ioeventfd(proxy); 30725db9ebeSStefan Hajnoczi } 30825db9ebeSStefan Hajnoczi 3091b8e9b27SMichael S. Tsirkin if (vdev->status == 0) { 310a3fc66d9SPaolo Bonzini virtio_reset(vdev); 3111b8e9b27SMichael S. Tsirkin msix_unuse_all_vectors(&proxy->pci_dev); 3121b8e9b27SMichael S. Tsirkin } 313c81131dbSAlexander Graf 314e43c0b2eSMichael S. Tsirkin /* Linux before 2.6.34 drives the device without enabling 315e43c0b2eSMichael S. Tsirkin the PCI device bus master bit. Enable it automatically 316e43c0b2eSMichael S. Tsirkin for the guest. This is a PCI spec violation but so is 317e43c0b2eSMichael S. Tsirkin initiating DMA with bus master bit clear. */ 318e43c0b2eSMichael S. Tsirkin if (val == (VIRTIO_CONFIG_S_ACKNOWLEDGE | VIRTIO_CONFIG_S_DRIVER)) { 319e43c0b2eSMichael S. Tsirkin pci_default_write_config(&proxy->pci_dev, PCI_COMMAND, 320e43c0b2eSMichael S. Tsirkin proxy->pci_dev.config[PCI_COMMAND] | 321e43c0b2eSMichael S. Tsirkin PCI_COMMAND_MASTER, 1); 322e43c0b2eSMichael S. Tsirkin } 32353c25ceaSPaul Brook break; 324aba800a3SMichael S. Tsirkin case VIRTIO_MSI_CONFIG_VECTOR: 325aba800a3SMichael S. Tsirkin msix_vector_unuse(&proxy->pci_dev, vdev->config_vector); 326aba800a3SMichael S. Tsirkin /* Make it possible for guest to discover an error took place. */ 327aba800a3SMichael S. Tsirkin if (msix_vector_use(&proxy->pci_dev, val) < 0) 328aba800a3SMichael S. Tsirkin val = VIRTIO_NO_VECTOR; 329aba800a3SMichael S. Tsirkin vdev->config_vector = val; 330aba800a3SMichael S. Tsirkin break; 331aba800a3SMichael S. Tsirkin case VIRTIO_MSI_QUEUE_VECTOR: 332aba800a3SMichael S. Tsirkin msix_vector_unuse(&proxy->pci_dev, 333aba800a3SMichael S. Tsirkin virtio_queue_vector(vdev, vdev->queue_sel)); 334aba800a3SMichael S. Tsirkin /* Make it possible for guest to discover an error took place. */ 335aba800a3SMichael S. Tsirkin if (msix_vector_use(&proxy->pci_dev, val) < 0) 336aba800a3SMichael S. Tsirkin val = VIRTIO_NO_VECTOR; 337aba800a3SMichael S. Tsirkin virtio_queue_set_vector(vdev, vdev->queue_sel, val); 338aba800a3SMichael S. Tsirkin break; 339aba800a3SMichael S. Tsirkin default: 3404e02d460SStefan Hajnoczi error_report("%s: unexpected address 0x%x value 0x%x", 341aba800a3SMichael S. Tsirkin __func__, addr, val); 342aba800a3SMichael S. Tsirkin break; 34353c25ceaSPaul Brook } 34453c25ceaSPaul Brook } 34553c25ceaSPaul Brook 346aba800a3SMichael S. Tsirkin static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr) 34753c25ceaSPaul Brook { 348a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 34953c25ceaSPaul Brook uint32_t ret = 0xFFFFFFFF; 35053c25ceaSPaul Brook 35153c25ceaSPaul Brook switch (addr) { 35253c25ceaSPaul Brook case VIRTIO_PCI_HOST_FEATURES: 3538172539dSMichael S. Tsirkin ret = proxy->host_features; 35453c25ceaSPaul Brook break; 35553c25ceaSPaul Brook case VIRTIO_PCI_GUEST_FEATURES: 356704a76fcSMichael S. Tsirkin ret = vdev->guest_features; 35753c25ceaSPaul Brook break; 35853c25ceaSPaul Brook case VIRTIO_PCI_QUEUE_PFN: 35953c25ceaSPaul Brook ret = virtio_queue_get_addr(vdev, vdev->queue_sel) 36053c25ceaSPaul Brook >> VIRTIO_PCI_QUEUE_ADDR_SHIFT; 36153c25ceaSPaul Brook break; 36253c25ceaSPaul Brook case VIRTIO_PCI_QUEUE_NUM: 36353c25ceaSPaul Brook ret = virtio_queue_get_num(vdev, vdev->queue_sel); 36453c25ceaSPaul Brook break; 36553c25ceaSPaul Brook case VIRTIO_PCI_QUEUE_SEL: 36653c25ceaSPaul Brook ret = vdev->queue_sel; 36753c25ceaSPaul Brook break; 36853c25ceaSPaul Brook case VIRTIO_PCI_STATUS: 36953c25ceaSPaul Brook ret = vdev->status; 37053c25ceaSPaul Brook break; 37153c25ceaSPaul Brook case VIRTIO_PCI_ISR: 37253c25ceaSPaul Brook /* reading from the ISR also clears it. */ 37353c25ceaSPaul Brook ret = vdev->isr; 37453c25ceaSPaul Brook vdev->isr = 0; 3759e64f8a3SMarcel Apfelbaum pci_irq_deassert(&proxy->pci_dev); 37653c25ceaSPaul Brook break; 377aba800a3SMichael S. Tsirkin case VIRTIO_MSI_CONFIG_VECTOR: 378aba800a3SMichael S. Tsirkin ret = vdev->config_vector; 379aba800a3SMichael S. Tsirkin break; 380aba800a3SMichael S. Tsirkin case VIRTIO_MSI_QUEUE_VECTOR: 381aba800a3SMichael S. Tsirkin ret = virtio_queue_vector(vdev, vdev->queue_sel); 382aba800a3SMichael S. Tsirkin break; 38353c25ceaSPaul Brook default: 38453c25ceaSPaul Brook break; 38553c25ceaSPaul Brook } 38653c25ceaSPaul Brook 38753c25ceaSPaul Brook return ret; 38853c25ceaSPaul Brook } 38953c25ceaSPaul Brook 390df6db5b3SAlexander Graf static uint64_t virtio_pci_config_read(void *opaque, hwaddr addr, 391df6db5b3SAlexander Graf unsigned size) 39253c25ceaSPaul Brook { 39353c25ceaSPaul Brook VirtIOPCIProxy *proxy = opaque; 394a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 395aba800a3SMichael S. Tsirkin uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev); 396df6db5b3SAlexander Graf uint64_t val = 0; 397df6db5b3SAlexander Graf if (addr < config) { 398aba800a3SMichael S. Tsirkin return virtio_ioport_read(proxy, addr); 39953c25ceaSPaul Brook } 400aba800a3SMichael S. Tsirkin addr -= config; 401df6db5b3SAlexander Graf 402df6db5b3SAlexander Graf switch (size) { 403df6db5b3SAlexander Graf case 1: 404a3fc66d9SPaolo Bonzini val = virtio_config_readb(vdev, addr); 405df6db5b3SAlexander Graf break; 406df6db5b3SAlexander Graf case 2: 407a3fc66d9SPaolo Bonzini val = virtio_config_readw(vdev, addr); 408616a6552SGreg Kurz if (virtio_is_big_endian(vdev)) { 4098e4a424bSBlue Swirl val = bswap16(val); 4108e4a424bSBlue Swirl } 411df6db5b3SAlexander Graf break; 412df6db5b3SAlexander Graf case 4: 413a3fc66d9SPaolo Bonzini val = virtio_config_readl(vdev, addr); 414616a6552SGreg Kurz if (virtio_is_big_endian(vdev)) { 4158e4a424bSBlue Swirl val = bswap32(val); 4168e4a424bSBlue Swirl } 417df6db5b3SAlexander Graf break; 418df6db5b3SAlexander Graf } 41982afa586SBenjamin Herrenschmidt return val; 42053c25ceaSPaul Brook } 42153c25ceaSPaul Brook 422df6db5b3SAlexander Graf static void virtio_pci_config_write(void *opaque, hwaddr addr, 423df6db5b3SAlexander Graf uint64_t val, unsigned size) 42453c25ceaSPaul Brook { 42553c25ceaSPaul Brook VirtIOPCIProxy *proxy = opaque; 426aba800a3SMichael S. Tsirkin uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev); 427a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 428aba800a3SMichael S. Tsirkin if (addr < config) { 429aba800a3SMichael S. Tsirkin virtio_ioport_write(proxy, addr, val); 430aba800a3SMichael S. Tsirkin return; 431aba800a3SMichael S. Tsirkin } 432aba800a3SMichael S. Tsirkin addr -= config; 433df6db5b3SAlexander Graf /* 434df6db5b3SAlexander Graf * Virtio-PCI is odd. Ioports are LE but config space is target native 435df6db5b3SAlexander Graf * endian. 436df6db5b3SAlexander Graf */ 437df6db5b3SAlexander Graf switch (size) { 438df6db5b3SAlexander Graf case 1: 439a3fc66d9SPaolo Bonzini virtio_config_writeb(vdev, addr, val); 440df6db5b3SAlexander Graf break; 441df6db5b3SAlexander Graf case 2: 442616a6552SGreg Kurz if (virtio_is_big_endian(vdev)) { 4438e4a424bSBlue Swirl val = bswap16(val); 4448e4a424bSBlue Swirl } 445a3fc66d9SPaolo Bonzini virtio_config_writew(vdev, addr, val); 446df6db5b3SAlexander Graf break; 447df6db5b3SAlexander Graf case 4: 448616a6552SGreg Kurz if (virtio_is_big_endian(vdev)) { 4498e4a424bSBlue Swirl val = bswap32(val); 4508e4a424bSBlue Swirl } 451a3fc66d9SPaolo Bonzini virtio_config_writel(vdev, addr, val); 452df6db5b3SAlexander Graf break; 453df6db5b3SAlexander Graf } 45453c25ceaSPaul Brook } 45553c25ceaSPaul Brook 456da146d0aSAvi Kivity static const MemoryRegionOps virtio_pci_config_ops = { 457df6db5b3SAlexander Graf .read = virtio_pci_config_read, 458df6db5b3SAlexander Graf .write = virtio_pci_config_write, 459df6db5b3SAlexander Graf .impl = { 460df6db5b3SAlexander Graf .min_access_size = 1, 461df6db5b3SAlexander Graf .max_access_size = 4, 462df6db5b3SAlexander Graf }, 4638e4a424bSBlue Swirl .endianness = DEVICE_LITTLE_ENDIAN, 464da146d0aSAvi Kivity }; 465aba800a3SMichael S. Tsirkin 466aba800a3SMichael S. Tsirkin static void virtio_write_config(PCIDevice *pci_dev, uint32_t address, 467aba800a3SMichael S. Tsirkin uint32_t val, int len) 468aba800a3SMichael S. Tsirkin { 469ed757e14SYan Vugenfirer VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); 470a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 471ed757e14SYan Vugenfirer 4724d43d3f3SMichael S. Tsirkin uint8_t cmd = proxy->pci_dev.config[PCI_COMMAND]; 4734d43d3f3SMichael S. Tsirkin 4741129714fSMichael S. Tsirkin pci_default_write_config(pci_dev, address, val, len); 4751129714fSMichael S. Tsirkin 4761129714fSMichael S. Tsirkin if (range_covers_byte(address, len, PCI_COMMAND) && 4771129714fSMichael S. Tsirkin !(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) && 4784d43d3f3SMichael S. Tsirkin (cmd & PCI_COMMAND_MASTER)) { 4794d43d3f3SMichael S. Tsirkin /* Bus driver disables bus mastering - make it act 4804d43d3f3SMichael S. Tsirkin * as a kind of reset to render the device quiescent. */ 48125db9ebeSStefan Hajnoczi virtio_pci_stop_ioeventfd(proxy); 4824d43d3f3SMichael S. Tsirkin virtio_reset(vdev); 4834d43d3f3SMichael S. Tsirkin msix_unuse_all_vectors(&proxy->pci_dev); 484ed757e14SYan Vugenfirer } 48553c25ceaSPaul Brook } 48653c25ceaSPaul Brook 487d2a0ccc6SMichael S. Tsirkin static unsigned virtio_pci_get_features(DeviceState *d) 4886d74ca5aSMichael S. Tsirkin { 489d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 4908172539dSMichael S. Tsirkin return proxy->host_features; 4916d74ca5aSMichael S. Tsirkin } 4926d74ca5aSMichael S. Tsirkin 4937d37d351SJan Kiszka static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy, 4947d37d351SJan Kiszka unsigned int queue_no, 4957d37d351SJan Kiszka unsigned int vector, 4967d37d351SJan Kiszka MSIMessage msg) 4977d37d351SJan Kiszka { 4987d37d351SJan Kiszka VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; 49915b2bd18SPaolo Bonzini int ret; 5007d37d351SJan Kiszka 5017d37d351SJan Kiszka if (irqfd->users == 0) { 5027d37d351SJan Kiszka ret = kvm_irqchip_add_msi_route(kvm_state, msg); 5037d37d351SJan Kiszka if (ret < 0) { 5047d37d351SJan Kiszka return ret; 5057d37d351SJan Kiszka } 5067d37d351SJan Kiszka irqfd->virq = ret; 5077d37d351SJan Kiszka } 5087d37d351SJan Kiszka irqfd->users++; 5097d37d351SJan Kiszka return 0; 5107d37d351SJan Kiszka } 5117d37d351SJan Kiszka 5127d37d351SJan Kiszka static void kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy, 513774345f9SMichael S. Tsirkin unsigned int vector) 514774345f9SMichael S. Tsirkin { 515774345f9SMichael S. Tsirkin VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; 516774345f9SMichael S. Tsirkin if (--irqfd->users == 0) { 517774345f9SMichael S. Tsirkin kvm_irqchip_release_virq(kvm_state, irqfd->virq); 518774345f9SMichael S. Tsirkin } 519774345f9SMichael S. Tsirkin } 520774345f9SMichael S. Tsirkin 521f1d0f15aSMichael S. Tsirkin static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy, 522f1d0f15aSMichael S. Tsirkin unsigned int queue_no, 523f1d0f15aSMichael S. Tsirkin unsigned int vector) 524f1d0f15aSMichael S. Tsirkin { 525f1d0f15aSMichael S. Tsirkin VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; 526a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 527a3fc66d9SPaolo Bonzini VirtQueue *vq = virtio_get_queue(vdev, queue_no); 528f1d0f15aSMichael S. Tsirkin EventNotifier *n = virtio_queue_get_guest_notifier(vq); 529f1d0f15aSMichael S. Tsirkin int ret; 530ca916d37SVincenzo Maffione ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, NULL, irqfd->virq); 531f1d0f15aSMichael S. Tsirkin return ret; 532f1d0f15aSMichael S. Tsirkin } 533f1d0f15aSMichael S. Tsirkin 534f1d0f15aSMichael S. Tsirkin static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy, 5357d37d351SJan Kiszka unsigned int queue_no, 5367d37d351SJan Kiszka unsigned int vector) 5377d37d351SJan Kiszka { 538a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 539a3fc66d9SPaolo Bonzini VirtQueue *vq = virtio_get_queue(vdev, queue_no); 54015b2bd18SPaolo Bonzini EventNotifier *n = virtio_queue_get_guest_notifier(vq); 5417d37d351SJan Kiszka VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; 54215b2bd18SPaolo Bonzini int ret; 5437d37d351SJan Kiszka 544b131c74aSJan Kiszka ret = kvm_irqchip_remove_irqfd_notifier(kvm_state, n, irqfd->virq); 5457d37d351SJan Kiszka assert(ret == 0); 546f1d0f15aSMichael S. Tsirkin } 5477d37d351SJan Kiszka 548774345f9SMichael S. Tsirkin static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) 549774345f9SMichael S. Tsirkin { 550774345f9SMichael S. Tsirkin PCIDevice *dev = &proxy->pci_dev; 551a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 552181103cdSKONRAD Frederic VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); 553774345f9SMichael S. Tsirkin unsigned int vector; 554774345f9SMichael S. Tsirkin int ret, queue_no; 555774345f9SMichael S. Tsirkin MSIMessage msg; 556774345f9SMichael S. Tsirkin 557774345f9SMichael S. Tsirkin for (queue_no = 0; queue_no < nvqs; queue_no++) { 558774345f9SMichael S. Tsirkin if (!virtio_queue_get_num(vdev, queue_no)) { 559774345f9SMichael S. Tsirkin break; 560774345f9SMichael S. Tsirkin } 561774345f9SMichael S. Tsirkin vector = virtio_queue_vector(vdev, queue_no); 562774345f9SMichael S. Tsirkin if (vector >= msix_nr_vectors_allocated(dev)) { 563774345f9SMichael S. Tsirkin continue; 564774345f9SMichael S. Tsirkin } 565774345f9SMichael S. Tsirkin msg = msix_get_message(dev, vector); 566774345f9SMichael S. Tsirkin ret = kvm_virtio_pci_vq_vector_use(proxy, queue_no, vector, msg); 567774345f9SMichael S. Tsirkin if (ret < 0) { 568774345f9SMichael S. Tsirkin goto undo; 569774345f9SMichael S. Tsirkin } 570f1d0f15aSMichael S. Tsirkin /* If guest supports masking, set up irqfd now. 571f1d0f15aSMichael S. Tsirkin * Otherwise, delay until unmasked in the frontend. 572f1d0f15aSMichael S. Tsirkin */ 573181103cdSKONRAD Frederic if (k->guest_notifier_mask) { 574f1d0f15aSMichael S. Tsirkin ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector); 575f1d0f15aSMichael S. Tsirkin if (ret < 0) { 576f1d0f15aSMichael S. Tsirkin kvm_virtio_pci_vq_vector_release(proxy, vector); 577f1d0f15aSMichael S. Tsirkin goto undo; 578f1d0f15aSMichael S. Tsirkin } 579f1d0f15aSMichael S. Tsirkin } 580774345f9SMichael S. Tsirkin } 581774345f9SMichael S. Tsirkin return 0; 582774345f9SMichael S. Tsirkin 583774345f9SMichael S. Tsirkin undo: 584774345f9SMichael S. Tsirkin while (--queue_no >= 0) { 585774345f9SMichael S. Tsirkin vector = virtio_queue_vector(vdev, queue_no); 586774345f9SMichael S. Tsirkin if (vector >= msix_nr_vectors_allocated(dev)) { 587774345f9SMichael S. Tsirkin continue; 588774345f9SMichael S. Tsirkin } 589181103cdSKONRAD Frederic if (k->guest_notifier_mask) { 590e387f99eSMichael S. Tsirkin kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); 591f1d0f15aSMichael S. Tsirkin } 592774345f9SMichael S. Tsirkin kvm_virtio_pci_vq_vector_release(proxy, vector); 593774345f9SMichael S. Tsirkin } 594774345f9SMichael S. Tsirkin return ret; 595774345f9SMichael S. Tsirkin } 596774345f9SMichael S. Tsirkin 597774345f9SMichael S. Tsirkin static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) 598774345f9SMichael S. Tsirkin { 599774345f9SMichael S. Tsirkin PCIDevice *dev = &proxy->pci_dev; 600a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 601774345f9SMichael S. Tsirkin unsigned int vector; 602774345f9SMichael S. Tsirkin int queue_no; 603181103cdSKONRAD Frederic VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); 604774345f9SMichael S. Tsirkin 605774345f9SMichael S. Tsirkin for (queue_no = 0; queue_no < nvqs; queue_no++) { 606774345f9SMichael S. Tsirkin if (!virtio_queue_get_num(vdev, queue_no)) { 607774345f9SMichael S. Tsirkin break; 608774345f9SMichael S. Tsirkin } 609774345f9SMichael S. Tsirkin vector = virtio_queue_vector(vdev, queue_no); 610774345f9SMichael S. Tsirkin if (vector >= msix_nr_vectors_allocated(dev)) { 611774345f9SMichael S. Tsirkin continue; 612774345f9SMichael S. Tsirkin } 613f1d0f15aSMichael S. Tsirkin /* If guest supports masking, clean up irqfd now. 614f1d0f15aSMichael S. Tsirkin * Otherwise, it was cleaned when masked in the frontend. 615f1d0f15aSMichael S. Tsirkin */ 616181103cdSKONRAD Frederic if (k->guest_notifier_mask) { 617e387f99eSMichael S. Tsirkin kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); 618f1d0f15aSMichael S. Tsirkin } 619774345f9SMichael S. Tsirkin kvm_virtio_pci_vq_vector_release(proxy, vector); 6207d37d351SJan Kiszka } 6217d37d351SJan Kiszka } 6227d37d351SJan Kiszka 623a38b2c49SMichael S. Tsirkin static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy, 624774345f9SMichael S. Tsirkin unsigned int queue_no, 625774345f9SMichael S. Tsirkin unsigned int vector, 626774345f9SMichael S. Tsirkin MSIMessage msg) 627774345f9SMichael S. Tsirkin { 628a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 629a3fc66d9SPaolo Bonzini VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); 630a3fc66d9SPaolo Bonzini VirtQueue *vq = virtio_get_queue(vdev, queue_no); 631774345f9SMichael S. Tsirkin EventNotifier *n = virtio_queue_get_guest_notifier(vq); 632a38b2c49SMichael S. Tsirkin VirtIOIRQFD *irqfd; 63353510bfcSMichael Roth int ret = 0; 634774345f9SMichael S. Tsirkin 635a38b2c49SMichael S. Tsirkin if (proxy->vector_irqfd) { 636a38b2c49SMichael S. Tsirkin irqfd = &proxy->vector_irqfd[vector]; 637774345f9SMichael S. Tsirkin if (irqfd->msg.data != msg.data || irqfd->msg.address != msg.address) { 638774345f9SMichael S. Tsirkin ret = kvm_irqchip_update_msi_route(kvm_state, irqfd->virq, msg); 639774345f9SMichael S. Tsirkin if (ret < 0) { 640774345f9SMichael S. Tsirkin return ret; 641774345f9SMichael S. Tsirkin } 642774345f9SMichael S. Tsirkin } 643a38b2c49SMichael S. Tsirkin } 644774345f9SMichael S. Tsirkin 645f1d0f15aSMichael S. Tsirkin /* If guest supports masking, irqfd is already setup, unmask it. 646f1d0f15aSMichael S. Tsirkin * Otherwise, set it up now. 647f1d0f15aSMichael S. Tsirkin */ 648181103cdSKONRAD Frederic if (k->guest_notifier_mask) { 649a3fc66d9SPaolo Bonzini k->guest_notifier_mask(vdev, queue_no, false); 650f1d0f15aSMichael S. Tsirkin /* Test after unmasking to avoid losing events. */ 651181103cdSKONRAD Frederic if (k->guest_notifier_pending && 652a3fc66d9SPaolo Bonzini k->guest_notifier_pending(vdev, queue_no)) { 653f1d0f15aSMichael S. Tsirkin event_notifier_set(n); 654f1d0f15aSMichael S. Tsirkin } 655f1d0f15aSMichael S. Tsirkin } else { 656f1d0f15aSMichael S. Tsirkin ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector); 657f1d0f15aSMichael S. Tsirkin } 658774345f9SMichael S. Tsirkin return ret; 659774345f9SMichael S. Tsirkin } 660774345f9SMichael S. Tsirkin 661a38b2c49SMichael S. Tsirkin static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy, 6627d37d351SJan Kiszka unsigned int queue_no, 6637d37d351SJan Kiszka unsigned int vector) 6647d37d351SJan Kiszka { 665a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 666a3fc66d9SPaolo Bonzini VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); 667181103cdSKONRAD Frederic 668f1d0f15aSMichael S. Tsirkin /* If guest supports masking, keep irqfd but mask it. 669f1d0f15aSMichael S. Tsirkin * Otherwise, clean it up now. 670f1d0f15aSMichael S. Tsirkin */ 671181103cdSKONRAD Frederic if (k->guest_notifier_mask) { 672a3fc66d9SPaolo Bonzini k->guest_notifier_mask(vdev, queue_no, true); 673f1d0f15aSMichael S. Tsirkin } else { 674e387f99eSMichael S. Tsirkin kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); 675f1d0f15aSMichael S. Tsirkin } 6767d37d351SJan Kiszka } 6777d37d351SJan Kiszka 678a38b2c49SMichael S. Tsirkin static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, 6797d37d351SJan Kiszka MSIMessage msg) 6807d37d351SJan Kiszka { 6817d37d351SJan Kiszka VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); 682a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 6837d37d351SJan Kiszka int ret, queue_no; 6847d37d351SJan Kiszka 6852d620f59SMichael S. Tsirkin for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) { 6867d37d351SJan Kiszka if (!virtio_queue_get_num(vdev, queue_no)) { 6877d37d351SJan Kiszka break; 6887d37d351SJan Kiszka } 6897d37d351SJan Kiszka if (virtio_queue_vector(vdev, queue_no) != vector) { 6907d37d351SJan Kiszka continue; 6917d37d351SJan Kiszka } 692a38b2c49SMichael S. Tsirkin ret = virtio_pci_vq_vector_unmask(proxy, queue_no, vector, msg); 6937d37d351SJan Kiszka if (ret < 0) { 6947d37d351SJan Kiszka goto undo; 6957d37d351SJan Kiszka } 6967d37d351SJan Kiszka } 6977d37d351SJan Kiszka return 0; 6987d37d351SJan Kiszka 6997d37d351SJan Kiszka undo: 7007d37d351SJan Kiszka while (--queue_no >= 0) { 7017d37d351SJan Kiszka if (virtio_queue_vector(vdev, queue_no) != vector) { 7027d37d351SJan Kiszka continue; 7037d37d351SJan Kiszka } 704a38b2c49SMichael S. Tsirkin virtio_pci_vq_vector_mask(proxy, queue_no, vector); 7057d37d351SJan Kiszka } 7067d37d351SJan Kiszka return ret; 7077d37d351SJan Kiszka } 7087d37d351SJan Kiszka 709a38b2c49SMichael S. Tsirkin static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector) 7107d37d351SJan Kiszka { 7117d37d351SJan Kiszka VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); 712a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 7137d37d351SJan Kiszka int queue_no; 7147d37d351SJan Kiszka 7152d620f59SMichael S. Tsirkin for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) { 7167d37d351SJan Kiszka if (!virtio_queue_get_num(vdev, queue_no)) { 7177d37d351SJan Kiszka break; 7187d37d351SJan Kiszka } 7197d37d351SJan Kiszka if (virtio_queue_vector(vdev, queue_no) != vector) { 7207d37d351SJan Kiszka continue; 7217d37d351SJan Kiszka } 722a38b2c49SMichael S. Tsirkin virtio_pci_vq_vector_mask(proxy, queue_no, vector); 7237d37d351SJan Kiszka } 7247d37d351SJan Kiszka } 7257d37d351SJan Kiszka 726a38b2c49SMichael S. Tsirkin static void virtio_pci_vector_poll(PCIDevice *dev, 72789d62be9SMichael S. Tsirkin unsigned int vector_start, 72889d62be9SMichael S. Tsirkin unsigned int vector_end) 72989d62be9SMichael S. Tsirkin { 73089d62be9SMichael S. Tsirkin VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); 731a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 732181103cdSKONRAD Frederic VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); 73389d62be9SMichael S. Tsirkin int queue_no; 73489d62be9SMichael S. Tsirkin unsigned int vector; 73589d62be9SMichael S. Tsirkin EventNotifier *notifier; 73689d62be9SMichael S. Tsirkin VirtQueue *vq; 73789d62be9SMichael S. Tsirkin 7382d620f59SMichael S. Tsirkin for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) { 73989d62be9SMichael S. Tsirkin if (!virtio_queue_get_num(vdev, queue_no)) { 74089d62be9SMichael S. Tsirkin break; 74189d62be9SMichael S. Tsirkin } 74289d62be9SMichael S. Tsirkin vector = virtio_queue_vector(vdev, queue_no); 74389d62be9SMichael S. Tsirkin if (vector < vector_start || vector >= vector_end || 74489d62be9SMichael S. Tsirkin !msix_is_masked(dev, vector)) { 74589d62be9SMichael S. Tsirkin continue; 74689d62be9SMichael S. Tsirkin } 74789d62be9SMichael S. Tsirkin vq = virtio_get_queue(vdev, queue_no); 74889d62be9SMichael S. Tsirkin notifier = virtio_queue_get_guest_notifier(vq); 749181103cdSKONRAD Frederic if (k->guest_notifier_pending) { 750181103cdSKONRAD Frederic if (k->guest_notifier_pending(vdev, queue_no)) { 751f1d0f15aSMichael S. Tsirkin msix_set_pending(dev, vector); 752f1d0f15aSMichael S. Tsirkin } 753f1d0f15aSMichael S. Tsirkin } else if (event_notifier_test_and_clear(notifier)) { 75489d62be9SMichael S. Tsirkin msix_set_pending(dev, vector); 75589d62be9SMichael S. Tsirkin } 75689d62be9SMichael S. Tsirkin } 75789d62be9SMichael S. Tsirkin } 75889d62be9SMichael S. Tsirkin 75989d62be9SMichael S. Tsirkin static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign, 76089d62be9SMichael S. Tsirkin bool with_irqfd) 761ade80dc8SMichael S. Tsirkin { 762d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 763a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 764a3fc66d9SPaolo Bonzini VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); 765a3fc66d9SPaolo Bonzini VirtQueue *vq = virtio_get_queue(vdev, n); 766ade80dc8SMichael S. Tsirkin EventNotifier *notifier = virtio_queue_get_guest_notifier(vq); 767ade80dc8SMichael S. Tsirkin 768ade80dc8SMichael S. Tsirkin if (assign) { 769ade80dc8SMichael S. Tsirkin int r = event_notifier_init(notifier, 0); 770ade80dc8SMichael S. Tsirkin if (r < 0) { 771ade80dc8SMichael S. Tsirkin return r; 772ade80dc8SMichael S. Tsirkin } 77389d62be9SMichael S. Tsirkin virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd); 774ade80dc8SMichael S. Tsirkin } else { 77589d62be9SMichael S. Tsirkin virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd); 776ade80dc8SMichael S. Tsirkin event_notifier_cleanup(notifier); 777ade80dc8SMichael S. Tsirkin } 778ade80dc8SMichael S. Tsirkin 77962c96360SMichael S. Tsirkin if (!msix_enabled(&proxy->pci_dev) && vdc->guest_notifier_mask) { 780a3fc66d9SPaolo Bonzini vdc->guest_notifier_mask(vdev, n, !assign); 78162c96360SMichael S. Tsirkin } 78262c96360SMichael S. Tsirkin 783ade80dc8SMichael S. Tsirkin return 0; 784ade80dc8SMichael S. Tsirkin } 785ade80dc8SMichael S. Tsirkin 786d2a0ccc6SMichael S. Tsirkin static bool virtio_pci_query_guest_notifiers(DeviceState *d) 7875430a28fSmst@redhat.com { 788d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 7895430a28fSmst@redhat.com return msix_enabled(&proxy->pci_dev); 7905430a28fSmst@redhat.com } 7915430a28fSmst@redhat.com 7922d620f59SMichael S. Tsirkin static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) 79354dd9321SMichael S. Tsirkin { 794d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 795a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 796181103cdSKONRAD Frederic VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); 79754dd9321SMichael S. Tsirkin int r, n; 79889d62be9SMichael S. Tsirkin bool with_irqfd = msix_enabled(&proxy->pci_dev) && 79989d62be9SMichael S. Tsirkin kvm_msi_via_irqfd_enabled(); 80054dd9321SMichael S. Tsirkin 8012d620f59SMichael S. Tsirkin nvqs = MIN(nvqs, VIRTIO_PCI_QUEUE_MAX); 8022d620f59SMichael S. Tsirkin 8032d620f59SMichael S. Tsirkin /* When deassigning, pass a consistent nvqs value 8042d620f59SMichael S. Tsirkin * to avoid leaking notifiers. 8052d620f59SMichael S. Tsirkin */ 8062d620f59SMichael S. Tsirkin assert(assign || nvqs == proxy->nvqs_with_notifiers); 8072d620f59SMichael S. Tsirkin 8082d620f59SMichael S. Tsirkin proxy->nvqs_with_notifiers = nvqs; 8092d620f59SMichael S. Tsirkin 8107d37d351SJan Kiszka /* Must unset vector notifier while guest notifier is still assigned */ 811181103cdSKONRAD Frederic if ((proxy->vector_irqfd || k->guest_notifier_mask) && !assign) { 8127d37d351SJan Kiszka msix_unset_vector_notifiers(&proxy->pci_dev); 813a38b2c49SMichael S. Tsirkin if (proxy->vector_irqfd) { 814774345f9SMichael S. Tsirkin kvm_virtio_pci_vector_release(proxy, nvqs); 8157d37d351SJan Kiszka g_free(proxy->vector_irqfd); 8167d37d351SJan Kiszka proxy->vector_irqfd = NULL; 8177d37d351SJan Kiszka } 818a38b2c49SMichael S. Tsirkin } 8197d37d351SJan Kiszka 8202d620f59SMichael S. Tsirkin for (n = 0; n < nvqs; n++) { 82154dd9321SMichael S. Tsirkin if (!virtio_queue_get_num(vdev, n)) { 82254dd9321SMichael S. Tsirkin break; 82354dd9321SMichael S. Tsirkin } 82454dd9321SMichael S. Tsirkin 82523fe2b3fSMichael S. Tsirkin r = virtio_pci_set_guest_notifier(d, n, assign, with_irqfd); 82654dd9321SMichael S. Tsirkin if (r < 0) { 82754dd9321SMichael S. Tsirkin goto assign_error; 82854dd9321SMichael S. Tsirkin } 82954dd9321SMichael S. Tsirkin } 83054dd9321SMichael S. Tsirkin 8317d37d351SJan Kiszka /* Must set vector notifier after guest notifier has been assigned */ 832181103cdSKONRAD Frederic if ((with_irqfd || k->guest_notifier_mask) && assign) { 833a38b2c49SMichael S. Tsirkin if (with_irqfd) { 8347d37d351SJan Kiszka proxy->vector_irqfd = 8357d37d351SJan Kiszka g_malloc0(sizeof(*proxy->vector_irqfd) * 8367d37d351SJan Kiszka msix_nr_vectors_allocated(&proxy->pci_dev)); 837774345f9SMichael S. Tsirkin r = kvm_virtio_pci_vector_use(proxy, nvqs); 8387d37d351SJan Kiszka if (r < 0) { 8397d37d351SJan Kiszka goto assign_error; 8407d37d351SJan Kiszka } 841a38b2c49SMichael S. Tsirkin } 842774345f9SMichael S. Tsirkin r = msix_set_vector_notifiers(&proxy->pci_dev, 843a38b2c49SMichael S. Tsirkin virtio_pci_vector_unmask, 844a38b2c49SMichael S. Tsirkin virtio_pci_vector_mask, 845a38b2c49SMichael S. Tsirkin virtio_pci_vector_poll); 846774345f9SMichael S. Tsirkin if (r < 0) { 847774345f9SMichael S. Tsirkin goto notifiers_error; 848774345f9SMichael S. Tsirkin } 8497d37d351SJan Kiszka } 8507d37d351SJan Kiszka 85154dd9321SMichael S. Tsirkin return 0; 85254dd9321SMichael S. Tsirkin 853774345f9SMichael S. Tsirkin notifiers_error: 854a38b2c49SMichael S. Tsirkin if (with_irqfd) { 855774345f9SMichael S. Tsirkin assert(assign); 856774345f9SMichael S. Tsirkin kvm_virtio_pci_vector_release(proxy, nvqs); 857a38b2c49SMichael S. Tsirkin } 858774345f9SMichael S. Tsirkin 85954dd9321SMichael S. Tsirkin assign_error: 86054dd9321SMichael S. Tsirkin /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */ 8617d37d351SJan Kiszka assert(assign); 86254dd9321SMichael S. Tsirkin while (--n >= 0) { 86389d62be9SMichael S. Tsirkin virtio_pci_set_guest_notifier(d, n, !assign, with_irqfd); 86454dd9321SMichael S. Tsirkin } 86554dd9321SMichael S. Tsirkin return r; 86654dd9321SMichael S. Tsirkin } 86754dd9321SMichael S. Tsirkin 868d2a0ccc6SMichael S. Tsirkin static int virtio_pci_set_host_notifier(DeviceState *d, int n, bool assign) 869ade80dc8SMichael S. Tsirkin { 870d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 87125db9ebeSStefan Hajnoczi 87225db9ebeSStefan Hajnoczi /* Stop using ioeventfd for virtqueue kick if the device starts using host 87325db9ebeSStefan Hajnoczi * notifiers. This makes it easy to avoid stepping on each others' toes. 87425db9ebeSStefan Hajnoczi */ 87525db9ebeSStefan Hajnoczi proxy->ioeventfd_disabled = assign; 876ade80dc8SMichael S. Tsirkin if (assign) { 87725db9ebeSStefan Hajnoczi virtio_pci_stop_ioeventfd(proxy); 878ade80dc8SMichael S. Tsirkin } 87925db9ebeSStefan Hajnoczi /* We don't need to start here: it's not needed because backend 88025db9ebeSStefan Hajnoczi * currently only stops on status change away from ok, 88125db9ebeSStefan Hajnoczi * reset, vmstop and such. If we do add code to start here, 88225db9ebeSStefan Hajnoczi * need to check vmstate, device state etc. */ 88326b9b5feSPaolo Bonzini return virtio_pci_set_host_notifier_internal(proxy, n, assign, false); 884ade80dc8SMichael S. Tsirkin } 88525db9ebeSStefan Hajnoczi 886d2a0ccc6SMichael S. Tsirkin static void virtio_pci_vmstate_change(DeviceState *d, bool running) 88725db9ebeSStefan Hajnoczi { 888d2a0ccc6SMichael S. Tsirkin VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); 889a3fc66d9SPaolo Bonzini VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); 89025db9ebeSStefan Hajnoczi 89125db9ebeSStefan Hajnoczi if (running) { 8924d43d3f3SMichael S. Tsirkin /* Linux before 2.6.34 drives the device without enabling 8934d43d3f3SMichael S. Tsirkin the PCI device bus master bit. Enable it automatically 8944d43d3f3SMichael S. Tsirkin for the guest. This is a PCI spec violation but so is 8954d43d3f3SMichael S. Tsirkin initiating DMA with bus master bit clear. 8964d43d3f3SMichael S. Tsirkin Note: this only makes a difference when migrating 8974d43d3f3SMichael S. Tsirkin across QEMU versions from an old QEMU, as for new QEMU 8984d43d3f3SMichael S. Tsirkin bus master and driver bits are always in sync. 8994d43d3f3SMichael S. Tsirkin TODO: consider enabling conditionally for compat machine types. */ 9004d43d3f3SMichael S. Tsirkin if (vdev->status & (VIRTIO_CONFIG_S_ACKNOWLEDGE | 9014d43d3f3SMichael S. Tsirkin VIRTIO_CONFIG_S_DRIVER)) { 9024d43d3f3SMichael S. Tsirkin pci_default_write_config(&proxy->pci_dev, PCI_COMMAND, 9034d43d3f3SMichael S. Tsirkin proxy->pci_dev.config[PCI_COMMAND] | 9044d43d3f3SMichael S. Tsirkin PCI_COMMAND_MASTER, 1); 90589c473fdSMichael S. Tsirkin } 90625db9ebeSStefan Hajnoczi virtio_pci_start_ioeventfd(proxy); 907ade80dc8SMichael S. Tsirkin } else { 90825db9ebeSStefan Hajnoczi virtio_pci_stop_ioeventfd(proxy); 909ade80dc8SMichael S. Tsirkin } 910ade80dc8SMichael S. Tsirkin } 911ade80dc8SMichael S. Tsirkin 91260653b28SPaolo Bonzini #ifdef CONFIG_VIRTFS 913234a336fSKONRAD Frederic static int virtio_9p_init_pci(VirtIOPCIProxy *vpci_dev) 91460653b28SPaolo Bonzini { 915234a336fSKONRAD Frederic V9fsPCIState *dev = VIRTIO_9P_PCI(vpci_dev); 916234a336fSKONRAD Frederic DeviceState *vdev = DEVICE(&dev->vdev); 91760653b28SPaolo Bonzini 918234a336fSKONRAD Frederic qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); 919234a336fSKONRAD Frederic if (qdev_init(vdev) < 0) { 920234a336fSKONRAD Frederic return -1; 921234a336fSKONRAD Frederic } 92260653b28SPaolo Bonzini return 0; 92360653b28SPaolo Bonzini } 92460653b28SPaolo Bonzini 925234a336fSKONRAD Frederic static Property virtio_9p_pci_properties[] = { 926234a336fSKONRAD Frederic DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, 927234a336fSKONRAD Frederic VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), 92860653b28SPaolo Bonzini DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), 92960653b28SPaolo Bonzini DEFINE_PROP_END_OF_LIST(), 93060653b28SPaolo Bonzini }; 93160653b28SPaolo Bonzini 932234a336fSKONRAD Frederic static void virtio_9p_pci_class_init(ObjectClass *klass, void *data) 93360653b28SPaolo Bonzini { 93460653b28SPaolo Bonzini DeviceClass *dc = DEVICE_CLASS(klass); 935234a336fSKONRAD Frederic PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); 936234a336fSKONRAD Frederic VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); 93760653b28SPaolo Bonzini 93860653b28SPaolo Bonzini k->init = virtio_9p_init_pci; 939234a336fSKONRAD Frederic pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 940234a336fSKONRAD Frederic pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_9P; 941234a336fSKONRAD Frederic pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; 942234a336fSKONRAD Frederic pcidev_k->class_id = 0x2; 943125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 944234a336fSKONRAD Frederic dc->props = virtio_9p_pci_properties; 94560653b28SPaolo Bonzini } 94660653b28SPaolo Bonzini 947234a336fSKONRAD Frederic static void virtio_9p_pci_instance_init(Object *obj) 948234a336fSKONRAD Frederic { 949234a336fSKONRAD Frederic V9fsPCIState *dev = VIRTIO_9P_PCI(obj); 950*c8075cafSGonglei 951*c8075cafSGonglei virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), 952*c8075cafSGonglei TYPE_VIRTIO_9P); 953234a336fSKONRAD Frederic } 954234a336fSKONRAD Frederic 955234a336fSKONRAD Frederic static const TypeInfo virtio_9p_pci_info = { 956234a336fSKONRAD Frederic .name = TYPE_VIRTIO_9P_PCI, 957234a336fSKONRAD Frederic .parent = TYPE_VIRTIO_PCI, 958234a336fSKONRAD Frederic .instance_size = sizeof(V9fsPCIState), 959234a336fSKONRAD Frederic .instance_init = virtio_9p_pci_instance_init, 960234a336fSKONRAD Frederic .class_init = virtio_9p_pci_class_init, 96160653b28SPaolo Bonzini }; 962234a336fSKONRAD Frederic #endif /* CONFIG_VIRTFS */ 96360653b28SPaolo Bonzini 964085bccb7SKONRAD Frederic /* 965085bccb7SKONRAD Frederic * virtio-pci: This is the PCIDevice which has a virtio-pci-bus. 966085bccb7SKONRAD Frederic */ 967085bccb7SKONRAD Frederic 968085bccb7SKONRAD Frederic /* This is called by virtio-bus just after the device is plugged. */ 969085bccb7SKONRAD Frederic static void virtio_pci_device_plugged(DeviceState *d) 970085bccb7SKONRAD Frederic { 971085bccb7SKONRAD Frederic VirtIOPCIProxy *proxy = VIRTIO_PCI(d); 972085bccb7SKONRAD Frederic VirtioBusState *bus = &proxy->bus; 973085bccb7SKONRAD Frederic uint8_t *config; 974085bccb7SKONRAD Frederic uint32_t size; 975085bccb7SKONRAD Frederic 976085bccb7SKONRAD Frederic config = proxy->pci_dev.config; 977085bccb7SKONRAD Frederic if (proxy->class_code) { 978085bccb7SKONRAD Frederic pci_config_set_class(config, proxy->class_code); 979085bccb7SKONRAD Frederic } 980085bccb7SKONRAD Frederic pci_set_word(config + PCI_SUBSYSTEM_VENDOR_ID, 981085bccb7SKONRAD Frederic pci_get_word(config + PCI_VENDOR_ID)); 982085bccb7SKONRAD Frederic pci_set_word(config + PCI_SUBSYSTEM_ID, virtio_bus_get_vdev_id(bus)); 983085bccb7SKONRAD Frederic config[PCI_INTERRUPT_PIN] = 1; 984085bccb7SKONRAD Frederic 985085bccb7SKONRAD Frederic if (proxy->nvectors && 986085bccb7SKONRAD Frederic msix_init_exclusive_bar(&proxy->pci_dev, proxy->nvectors, 1)) { 987c7ff5482SFam Zheng error_report("unable to init msix vectors to %" PRIu32, 988c7ff5482SFam Zheng proxy->nvectors); 989085bccb7SKONRAD Frederic proxy->nvectors = 0; 990085bccb7SKONRAD Frederic } 991085bccb7SKONRAD Frederic 992085bccb7SKONRAD Frederic proxy->pci_dev.config_write = virtio_write_config; 993085bccb7SKONRAD Frederic 994085bccb7SKONRAD Frederic size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) 995085bccb7SKONRAD Frederic + virtio_bus_get_vdev_config_len(bus); 996085bccb7SKONRAD Frederic if (size & (size - 1)) { 997085bccb7SKONRAD Frederic size = 1 << qemu_fls(size); 998085bccb7SKONRAD Frederic } 999085bccb7SKONRAD Frederic 100022fc860bSPaolo Bonzini memory_region_init_io(&proxy->bar, OBJECT(proxy), &virtio_pci_config_ops, 100122fc860bSPaolo Bonzini proxy, "virtio-pci", size); 1002085bccb7SKONRAD Frederic pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, 1003085bccb7SKONRAD Frederic &proxy->bar); 1004085bccb7SKONRAD Frederic 1005085bccb7SKONRAD Frederic if (!kvm_has_many_ioeventfds()) { 1006085bccb7SKONRAD Frederic proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD; 1007085bccb7SKONRAD Frederic } 1008085bccb7SKONRAD Frederic 1009085bccb7SKONRAD Frederic proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY; 1010085bccb7SKONRAD Frederic proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE; 1011085bccb7SKONRAD Frederic proxy->host_features = virtio_bus_get_vdev_features(bus, 1012085bccb7SKONRAD Frederic proxy->host_features); 1013085bccb7SKONRAD Frederic } 1014085bccb7SKONRAD Frederic 101506a13073SPaolo Bonzini static void virtio_pci_device_unplugged(DeviceState *d) 101606a13073SPaolo Bonzini { 101706a13073SPaolo Bonzini VirtIOPCIProxy *proxy = VIRTIO_PCI(d); 101806a13073SPaolo Bonzini 101906a13073SPaolo Bonzini virtio_pci_stop_ioeventfd(proxy); 102006a13073SPaolo Bonzini } 102106a13073SPaolo Bonzini 1022085bccb7SKONRAD Frederic static int virtio_pci_init(PCIDevice *pci_dev) 1023085bccb7SKONRAD Frederic { 1024085bccb7SKONRAD Frederic VirtIOPCIProxy *dev = VIRTIO_PCI(pci_dev); 1025085bccb7SKONRAD Frederic VirtioPCIClass *k = VIRTIO_PCI_GET_CLASS(pci_dev); 1026ac7af112SAndreas Färber virtio_pci_bus_new(&dev->bus, sizeof(dev->bus), dev); 1027085bccb7SKONRAD Frederic if (k->init != NULL) { 1028085bccb7SKONRAD Frederic return k->init(dev); 1029085bccb7SKONRAD Frederic } 1030085bccb7SKONRAD Frederic return 0; 1031085bccb7SKONRAD Frederic } 1032085bccb7SKONRAD Frederic 1033085bccb7SKONRAD Frederic static void virtio_pci_exit(PCIDevice *pci_dev) 1034085bccb7SKONRAD Frederic { 10358b81bb3bSPaolo Bonzini msix_uninit_exclusive_bar(pci_dev); 1036085bccb7SKONRAD Frederic } 1037085bccb7SKONRAD Frederic 103859ccd20aSKONRAD Frederic static void virtio_pci_reset(DeviceState *qdev) 1039085bccb7SKONRAD Frederic { 1040085bccb7SKONRAD Frederic VirtIOPCIProxy *proxy = VIRTIO_PCI(qdev); 1041085bccb7SKONRAD Frederic VirtioBusState *bus = VIRTIO_BUS(&proxy->bus); 1042085bccb7SKONRAD Frederic virtio_pci_stop_ioeventfd(proxy); 1043085bccb7SKONRAD Frederic virtio_bus_reset(bus); 1044085bccb7SKONRAD Frederic msix_unuse_all_vectors(&proxy->pci_dev); 1045085bccb7SKONRAD Frederic } 1046085bccb7SKONRAD Frederic 104785d1277eSMing Lei static Property virtio_pci_properties[] = { 104885d1277eSMing Lei DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features), 104985d1277eSMing Lei DEFINE_PROP_END_OF_LIST(), 105085d1277eSMing Lei }; 105185d1277eSMing Lei 1052085bccb7SKONRAD Frederic static void virtio_pci_class_init(ObjectClass *klass, void *data) 1053085bccb7SKONRAD Frederic { 1054085bccb7SKONRAD Frederic DeviceClass *dc = DEVICE_CLASS(klass); 1055085bccb7SKONRAD Frederic PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 1056085bccb7SKONRAD Frederic 105785d1277eSMing Lei dc->props = virtio_pci_properties; 1058085bccb7SKONRAD Frederic k->init = virtio_pci_init; 1059085bccb7SKONRAD Frederic k->exit = virtio_pci_exit; 1060085bccb7SKONRAD Frederic k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 1061085bccb7SKONRAD Frederic k->revision = VIRTIO_PCI_ABI_VERSION; 1062085bccb7SKONRAD Frederic k->class_id = PCI_CLASS_OTHERS; 106359ccd20aSKONRAD Frederic dc->reset = virtio_pci_reset; 1064085bccb7SKONRAD Frederic } 1065085bccb7SKONRAD Frederic 1066085bccb7SKONRAD Frederic static const TypeInfo virtio_pci_info = { 1067085bccb7SKONRAD Frederic .name = TYPE_VIRTIO_PCI, 1068085bccb7SKONRAD Frederic .parent = TYPE_PCI_DEVICE, 1069085bccb7SKONRAD Frederic .instance_size = sizeof(VirtIOPCIProxy), 1070085bccb7SKONRAD Frederic .class_init = virtio_pci_class_init, 1071085bccb7SKONRAD Frederic .class_size = sizeof(VirtioPCIClass), 1072085bccb7SKONRAD Frederic .abstract = true, 1073085bccb7SKONRAD Frederic }; 1074085bccb7SKONRAD Frederic 1075653ced07SKONRAD Frederic /* virtio-blk-pci */ 1076653ced07SKONRAD Frederic 1077653ced07SKONRAD Frederic static Property virtio_blk_pci_properties[] = { 1078c7bcc85dSPaolo Bonzini DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), 1079653ced07SKONRAD Frederic DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, 1080653ced07SKONRAD Frederic VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), 1081653ced07SKONRAD Frederic DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), 1082653ced07SKONRAD Frederic DEFINE_PROP_END_OF_LIST(), 1083653ced07SKONRAD Frederic }; 1084653ced07SKONRAD Frederic 1085653ced07SKONRAD Frederic static int virtio_blk_pci_init(VirtIOPCIProxy *vpci_dev) 1086653ced07SKONRAD Frederic { 1087653ced07SKONRAD Frederic VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(vpci_dev); 1088653ced07SKONRAD Frederic DeviceState *vdev = DEVICE(&dev->vdev); 1089653ced07SKONRAD Frederic qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); 1090653ced07SKONRAD Frederic if (qdev_init(vdev) < 0) { 1091653ced07SKONRAD Frederic return -1; 1092653ced07SKONRAD Frederic } 1093653ced07SKONRAD Frederic return 0; 1094653ced07SKONRAD Frederic } 1095653ced07SKONRAD Frederic 1096653ced07SKONRAD Frederic static void virtio_blk_pci_class_init(ObjectClass *klass, void *data) 1097653ced07SKONRAD Frederic { 1098653ced07SKONRAD Frederic DeviceClass *dc = DEVICE_CLASS(klass); 1099653ced07SKONRAD Frederic VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); 1100653ced07SKONRAD Frederic PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); 1101653ced07SKONRAD Frederic 1102125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 1103653ced07SKONRAD Frederic dc->props = virtio_blk_pci_properties; 1104653ced07SKONRAD Frederic k->init = virtio_blk_pci_init; 1105653ced07SKONRAD Frederic pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 1106653ced07SKONRAD Frederic pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BLOCK; 1107653ced07SKONRAD Frederic pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; 1108653ced07SKONRAD Frederic pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI; 1109653ced07SKONRAD Frederic } 1110653ced07SKONRAD Frederic 1111653ced07SKONRAD Frederic static void virtio_blk_pci_instance_init(Object *obj) 1112653ced07SKONRAD Frederic { 1113653ced07SKONRAD Frederic VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(obj); 1114*c8075cafSGonglei 1115*c8075cafSGonglei virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), 1116*c8075cafSGonglei TYPE_VIRTIO_BLK); 1117467b3f33SStefan Hajnoczi object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev),"iothread", 1118467b3f33SStefan Hajnoczi &error_abort); 1119653ced07SKONRAD Frederic } 1120653ced07SKONRAD Frederic 1121653ced07SKONRAD Frederic static const TypeInfo virtio_blk_pci_info = { 1122653ced07SKONRAD Frederic .name = TYPE_VIRTIO_BLK_PCI, 1123653ced07SKONRAD Frederic .parent = TYPE_VIRTIO_PCI, 1124653ced07SKONRAD Frederic .instance_size = sizeof(VirtIOBlkPCI), 1125653ced07SKONRAD Frederic .instance_init = virtio_blk_pci_instance_init, 1126653ced07SKONRAD Frederic .class_init = virtio_blk_pci_class_init, 1127653ced07SKONRAD Frederic }; 1128653ced07SKONRAD Frederic 1129bc7b90a0SKONRAD Frederic /* virtio-scsi-pci */ 1130bc7b90a0SKONRAD Frederic 1131bc7b90a0SKONRAD Frederic static Property virtio_scsi_pci_properties[] = { 1132bc7b90a0SKONRAD Frederic DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, 1133bc7b90a0SKONRAD Frederic VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), 1134bc7b90a0SKONRAD Frederic DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 1135bc7b90a0SKONRAD Frederic DEV_NVECTORS_UNSPECIFIED), 1136bc7b90a0SKONRAD Frederic DEFINE_VIRTIO_SCSI_FEATURES(VirtIOPCIProxy, host_features), 1137bc7b90a0SKONRAD Frederic DEFINE_PROP_END_OF_LIST(), 1138bc7b90a0SKONRAD Frederic }; 1139bc7b90a0SKONRAD Frederic 1140bc7b90a0SKONRAD Frederic static int virtio_scsi_pci_init_pci(VirtIOPCIProxy *vpci_dev) 1141bc7b90a0SKONRAD Frederic { 1142bc7b90a0SKONRAD Frederic VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(vpci_dev); 1143bc7b90a0SKONRAD Frederic DeviceState *vdev = DEVICE(&dev->vdev); 1144292c8e50SPaolo Bonzini VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev); 11456f32a6b4SKONRAD Frederic DeviceState *proxy = DEVICE(vpci_dev); 11466f32a6b4SKONRAD Frederic char *bus_name; 1147bc7b90a0SKONRAD Frederic 1148bc7b90a0SKONRAD Frederic if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { 1149292c8e50SPaolo Bonzini vpci_dev->nvectors = vs->conf.num_queues + 3; 1150bc7b90a0SKONRAD Frederic } 1151bc7b90a0SKONRAD Frederic 11526f32a6b4SKONRAD Frederic /* 11536f32a6b4SKONRAD Frederic * For command line compatibility, this sets the virtio-scsi-device bus 11546f32a6b4SKONRAD Frederic * name as before. 11556f32a6b4SKONRAD Frederic */ 11566f32a6b4SKONRAD Frederic if (proxy->id) { 11576f32a6b4SKONRAD Frederic bus_name = g_strdup_printf("%s.0", proxy->id); 11586f32a6b4SKONRAD Frederic virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name); 11596f32a6b4SKONRAD Frederic g_free(bus_name); 11606f32a6b4SKONRAD Frederic } 11616f32a6b4SKONRAD Frederic 1162bc7b90a0SKONRAD Frederic qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); 1163bc7b90a0SKONRAD Frederic if (qdev_init(vdev) < 0) { 1164bc7b90a0SKONRAD Frederic return -1; 1165bc7b90a0SKONRAD Frederic } 1166bc7b90a0SKONRAD Frederic return 0; 1167bc7b90a0SKONRAD Frederic } 1168bc7b90a0SKONRAD Frederic 1169bc7b90a0SKONRAD Frederic static void virtio_scsi_pci_class_init(ObjectClass *klass, void *data) 1170bc7b90a0SKONRAD Frederic { 1171bc7b90a0SKONRAD Frederic DeviceClass *dc = DEVICE_CLASS(klass); 1172bc7b90a0SKONRAD Frederic VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); 1173bc7b90a0SKONRAD Frederic PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); 1174bc7b90a0SKONRAD Frederic k->init = virtio_scsi_pci_init_pci; 1175125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 1176bc7b90a0SKONRAD Frederic dc->props = virtio_scsi_pci_properties; 1177bc7b90a0SKONRAD Frederic pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 1178bc7b90a0SKONRAD Frederic pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI; 1179bc7b90a0SKONRAD Frederic pcidev_k->revision = 0x00; 1180bc7b90a0SKONRAD Frederic pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI; 1181bc7b90a0SKONRAD Frederic } 1182bc7b90a0SKONRAD Frederic 1183bc7b90a0SKONRAD Frederic static void virtio_scsi_pci_instance_init(Object *obj) 1184bc7b90a0SKONRAD Frederic { 1185bc7b90a0SKONRAD Frederic VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(obj); 1186*c8075cafSGonglei 1187*c8075cafSGonglei virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), 1188*c8075cafSGonglei TYPE_VIRTIO_SCSI); 1189bc7b90a0SKONRAD Frederic } 1190bc7b90a0SKONRAD Frederic 1191bc7b90a0SKONRAD Frederic static const TypeInfo virtio_scsi_pci_info = { 1192bc7b90a0SKONRAD Frederic .name = TYPE_VIRTIO_SCSI_PCI, 1193bc7b90a0SKONRAD Frederic .parent = TYPE_VIRTIO_PCI, 1194bc7b90a0SKONRAD Frederic .instance_size = sizeof(VirtIOSCSIPCI), 1195bc7b90a0SKONRAD Frederic .instance_init = virtio_scsi_pci_instance_init, 1196bc7b90a0SKONRAD Frederic .class_init = virtio_scsi_pci_class_init, 1197bc7b90a0SKONRAD Frederic }; 1198bc7b90a0SKONRAD Frederic 119950787628SNicholas Bellinger /* vhost-scsi-pci */ 120050787628SNicholas Bellinger 120150787628SNicholas Bellinger #ifdef CONFIG_VHOST_SCSI 120250787628SNicholas Bellinger static Property vhost_scsi_pci_properties[] = { 120350787628SNicholas Bellinger DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 120450787628SNicholas Bellinger DEV_NVECTORS_UNSPECIFIED), 120550787628SNicholas Bellinger DEFINE_PROP_END_OF_LIST(), 120650787628SNicholas Bellinger }; 120750787628SNicholas Bellinger 120850787628SNicholas Bellinger static int vhost_scsi_pci_init_pci(VirtIOPCIProxy *vpci_dev) 120950787628SNicholas Bellinger { 121050787628SNicholas Bellinger VHostSCSIPCI *dev = VHOST_SCSI_PCI(vpci_dev); 121150787628SNicholas Bellinger DeviceState *vdev = DEVICE(&dev->vdev); 121250787628SNicholas Bellinger VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev); 121350787628SNicholas Bellinger 121450787628SNicholas Bellinger if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { 121550787628SNicholas Bellinger vpci_dev->nvectors = vs->conf.num_queues + 3; 121650787628SNicholas Bellinger } 121750787628SNicholas Bellinger 121850787628SNicholas Bellinger qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); 121950787628SNicholas Bellinger if (qdev_init(vdev) < 0) { 122050787628SNicholas Bellinger return -1; 122150787628SNicholas Bellinger } 122250787628SNicholas Bellinger return 0; 122350787628SNicholas Bellinger } 122450787628SNicholas Bellinger 122550787628SNicholas Bellinger static void vhost_scsi_pci_class_init(ObjectClass *klass, void *data) 122650787628SNicholas Bellinger { 122750787628SNicholas Bellinger DeviceClass *dc = DEVICE_CLASS(klass); 122850787628SNicholas Bellinger VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); 122950787628SNicholas Bellinger PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); 123050787628SNicholas Bellinger k->init = vhost_scsi_pci_init_pci; 1231125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 123250787628SNicholas Bellinger dc->props = vhost_scsi_pci_properties; 123350787628SNicholas Bellinger pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 123450787628SNicholas Bellinger pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI; 123550787628SNicholas Bellinger pcidev_k->revision = 0x00; 123650787628SNicholas Bellinger pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI; 123750787628SNicholas Bellinger } 123850787628SNicholas Bellinger 123950787628SNicholas Bellinger static void vhost_scsi_pci_instance_init(Object *obj) 124050787628SNicholas Bellinger { 124150787628SNicholas Bellinger VHostSCSIPCI *dev = VHOST_SCSI_PCI(obj); 1242*c8075cafSGonglei 1243*c8075cafSGonglei virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), 1244*c8075cafSGonglei TYPE_VHOST_SCSI); 124550787628SNicholas Bellinger } 124650787628SNicholas Bellinger 124750787628SNicholas Bellinger static const TypeInfo vhost_scsi_pci_info = { 124850787628SNicholas Bellinger .name = TYPE_VHOST_SCSI_PCI, 124950787628SNicholas Bellinger .parent = TYPE_VIRTIO_PCI, 125050787628SNicholas Bellinger .instance_size = sizeof(VHostSCSIPCI), 125150787628SNicholas Bellinger .instance_init = vhost_scsi_pci_instance_init, 125250787628SNicholas Bellinger .class_init = vhost_scsi_pci_class_init, 125350787628SNicholas Bellinger }; 125450787628SNicholas Bellinger #endif 125550787628SNicholas Bellinger 1256e378e88dSKONRAD Frederic /* virtio-balloon-pci */ 1257e378e88dSKONRAD Frederic 125824a6e7f4SKONRAD Frederic static void balloon_pci_stats_get_all(Object *obj, struct Visitor *v, 125924a6e7f4SKONRAD Frederic void *opaque, const char *name, 126024a6e7f4SKONRAD Frederic Error **errp) 126124a6e7f4SKONRAD Frederic { 126224a6e7f4SKONRAD Frederic VirtIOBalloonPCI *dev = opaque; 126324a6e7f4SKONRAD Frederic object_property_get(OBJECT(&dev->vdev), v, "guest-stats", errp); 126424a6e7f4SKONRAD Frederic } 126524a6e7f4SKONRAD Frederic 126624a6e7f4SKONRAD Frederic static void balloon_pci_stats_get_poll_interval(Object *obj, struct Visitor *v, 126724a6e7f4SKONRAD Frederic void *opaque, const char *name, 126824a6e7f4SKONRAD Frederic Error **errp) 126924a6e7f4SKONRAD Frederic { 127024a6e7f4SKONRAD Frederic VirtIOBalloonPCI *dev = opaque; 127124a6e7f4SKONRAD Frederic object_property_get(OBJECT(&dev->vdev), v, "guest-stats-polling-interval", 127224a6e7f4SKONRAD Frederic errp); 127324a6e7f4SKONRAD Frederic } 127424a6e7f4SKONRAD Frederic 127524a6e7f4SKONRAD Frederic static void balloon_pci_stats_set_poll_interval(Object *obj, struct Visitor *v, 127624a6e7f4SKONRAD Frederic void *opaque, const char *name, 127724a6e7f4SKONRAD Frederic Error **errp) 127824a6e7f4SKONRAD Frederic { 127924a6e7f4SKONRAD Frederic VirtIOBalloonPCI *dev = opaque; 128024a6e7f4SKONRAD Frederic object_property_set(OBJECT(&dev->vdev), v, "guest-stats-polling-interval", 128124a6e7f4SKONRAD Frederic errp); 128224a6e7f4SKONRAD Frederic } 128324a6e7f4SKONRAD Frederic 1284e378e88dSKONRAD Frederic static Property virtio_balloon_pci_properties[] = { 1285c7bcc85dSPaolo Bonzini DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), 1286e378e88dSKONRAD Frederic DEFINE_PROP_END_OF_LIST(), 1287e378e88dSKONRAD Frederic }; 1288e378e88dSKONRAD Frederic 1289e378e88dSKONRAD Frederic static int virtio_balloon_pci_init(VirtIOPCIProxy *vpci_dev) 1290e378e88dSKONRAD Frederic { 1291e378e88dSKONRAD Frederic VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(vpci_dev); 1292e378e88dSKONRAD Frederic DeviceState *vdev = DEVICE(&dev->vdev); 1293e378e88dSKONRAD Frederic 1294e378e88dSKONRAD Frederic if (vpci_dev->class_code != PCI_CLASS_OTHERS && 1295e378e88dSKONRAD Frederic vpci_dev->class_code != PCI_CLASS_MEMORY_RAM) { /* qemu < 1.1 */ 1296e378e88dSKONRAD Frederic vpci_dev->class_code = PCI_CLASS_OTHERS; 1297e378e88dSKONRAD Frederic } 1298e378e88dSKONRAD Frederic 1299e378e88dSKONRAD Frederic qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); 1300e378e88dSKONRAD Frederic if (qdev_init(vdev) < 0) { 1301e378e88dSKONRAD Frederic return -1; 1302e378e88dSKONRAD Frederic } 1303e378e88dSKONRAD Frederic return 0; 1304e378e88dSKONRAD Frederic } 1305e378e88dSKONRAD Frederic 1306e378e88dSKONRAD Frederic static void virtio_balloon_pci_class_init(ObjectClass *klass, void *data) 1307e378e88dSKONRAD Frederic { 1308e378e88dSKONRAD Frederic DeviceClass *dc = DEVICE_CLASS(klass); 1309e378e88dSKONRAD Frederic VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); 1310e378e88dSKONRAD Frederic PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); 1311e378e88dSKONRAD Frederic k->init = virtio_balloon_pci_init; 1312125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_MISC, dc->categories); 1313e378e88dSKONRAD Frederic dc->props = virtio_balloon_pci_properties; 1314e378e88dSKONRAD Frederic pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 1315e378e88dSKONRAD Frederic pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON; 1316e378e88dSKONRAD Frederic pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; 1317e378e88dSKONRAD Frederic pcidev_k->class_id = PCI_CLASS_OTHERS; 1318e378e88dSKONRAD Frederic } 1319e378e88dSKONRAD Frederic 1320e378e88dSKONRAD Frederic static void virtio_balloon_pci_instance_init(Object *obj) 1321e378e88dSKONRAD Frederic { 1322e378e88dSKONRAD Frederic VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(obj); 1323213f0c4fSAndreas Färber object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BALLOON); 1324e378e88dSKONRAD Frederic object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); 132591ba2120SGonglei object_unref(OBJECT(&dev->vdev)); 132624a6e7f4SKONRAD Frederic object_property_add(obj, "guest-stats", "guest statistics", 132724a6e7f4SKONRAD Frederic balloon_pci_stats_get_all, NULL, NULL, dev, 132824a6e7f4SKONRAD Frederic NULL); 132924a6e7f4SKONRAD Frederic 133024a6e7f4SKONRAD Frederic object_property_add(obj, "guest-stats-polling-interval", "int", 133124a6e7f4SKONRAD Frederic balloon_pci_stats_get_poll_interval, 133224a6e7f4SKONRAD Frederic balloon_pci_stats_set_poll_interval, 133324a6e7f4SKONRAD Frederic NULL, dev, NULL); 1334e378e88dSKONRAD Frederic } 1335e378e88dSKONRAD Frederic 1336e378e88dSKONRAD Frederic static const TypeInfo virtio_balloon_pci_info = { 1337e378e88dSKONRAD Frederic .name = TYPE_VIRTIO_BALLOON_PCI, 1338e378e88dSKONRAD Frederic .parent = TYPE_VIRTIO_PCI, 1339e378e88dSKONRAD Frederic .instance_size = sizeof(VirtIOBalloonPCI), 1340e378e88dSKONRAD Frederic .instance_init = virtio_balloon_pci_instance_init, 1341e378e88dSKONRAD Frederic .class_init = virtio_balloon_pci_class_init, 1342e378e88dSKONRAD Frederic }; 1343e378e88dSKONRAD Frederic 1344f7f7464aSKONRAD Frederic /* virtio-serial-pci */ 1345f7f7464aSKONRAD Frederic 1346f7f7464aSKONRAD Frederic static int virtio_serial_pci_init(VirtIOPCIProxy *vpci_dev) 1347f7f7464aSKONRAD Frederic { 1348f7f7464aSKONRAD Frederic VirtIOSerialPCI *dev = VIRTIO_SERIAL_PCI(vpci_dev); 1349f7f7464aSKONRAD Frederic DeviceState *vdev = DEVICE(&dev->vdev); 135080270a19SKONRAD Frederic DeviceState *proxy = DEVICE(vpci_dev); 135180270a19SKONRAD Frederic char *bus_name; 1352f7f7464aSKONRAD Frederic 1353f7f7464aSKONRAD Frederic if (vpci_dev->class_code != PCI_CLASS_COMMUNICATION_OTHER && 1354f7f7464aSKONRAD Frederic vpci_dev->class_code != PCI_CLASS_DISPLAY_OTHER && /* qemu 0.10 */ 1355f7f7464aSKONRAD Frederic vpci_dev->class_code != PCI_CLASS_OTHERS) { /* qemu-kvm */ 1356f7f7464aSKONRAD Frederic vpci_dev->class_code = PCI_CLASS_COMMUNICATION_OTHER; 1357f7f7464aSKONRAD Frederic } 1358f7f7464aSKONRAD Frederic 1359f7f7464aSKONRAD Frederic /* backwards-compatibility with machines that were created with 1360f7f7464aSKONRAD Frederic DEV_NVECTORS_UNSPECIFIED */ 1361f7f7464aSKONRAD Frederic if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { 1362f7f7464aSKONRAD Frederic vpci_dev->nvectors = dev->vdev.serial.max_virtserial_ports + 1; 1363f7f7464aSKONRAD Frederic } 1364f7f7464aSKONRAD Frederic 136580270a19SKONRAD Frederic /* 136680270a19SKONRAD Frederic * For command line compatibility, this sets the virtio-serial-device bus 136780270a19SKONRAD Frederic * name as before. 136880270a19SKONRAD Frederic */ 136980270a19SKONRAD Frederic if (proxy->id) { 137080270a19SKONRAD Frederic bus_name = g_strdup_printf("%s.0", proxy->id); 137180270a19SKONRAD Frederic virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name); 137280270a19SKONRAD Frederic g_free(bus_name); 137380270a19SKONRAD Frederic } 137480270a19SKONRAD Frederic 1375f7f7464aSKONRAD Frederic qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); 1376f7f7464aSKONRAD Frederic if (qdev_init(vdev) < 0) { 1377f7f7464aSKONRAD Frederic return -1; 1378f7f7464aSKONRAD Frederic } 1379f7f7464aSKONRAD Frederic return 0; 1380f7f7464aSKONRAD Frederic } 1381f7f7464aSKONRAD Frederic 1382f7f7464aSKONRAD Frederic static Property virtio_serial_pci_properties[] = { 1383f7f7464aSKONRAD Frederic DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, 1384f7f7464aSKONRAD Frederic VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), 1385f7f7464aSKONRAD Frederic DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), 1386c7bcc85dSPaolo Bonzini DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), 1387f7f7464aSKONRAD Frederic DEFINE_PROP_END_OF_LIST(), 1388f7f7464aSKONRAD Frederic }; 1389f7f7464aSKONRAD Frederic 1390f7f7464aSKONRAD Frederic static void virtio_serial_pci_class_init(ObjectClass *klass, void *data) 1391f7f7464aSKONRAD Frederic { 1392f7f7464aSKONRAD Frederic DeviceClass *dc = DEVICE_CLASS(klass); 1393f7f7464aSKONRAD Frederic VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); 1394f7f7464aSKONRAD Frederic PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); 1395f7f7464aSKONRAD Frederic k->init = virtio_serial_pci_init; 1396125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_INPUT, dc->categories); 1397f7f7464aSKONRAD Frederic dc->props = virtio_serial_pci_properties; 1398f7f7464aSKONRAD Frederic pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 1399f7f7464aSKONRAD Frederic pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE; 1400f7f7464aSKONRAD Frederic pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; 1401f7f7464aSKONRAD Frederic pcidev_k->class_id = PCI_CLASS_COMMUNICATION_OTHER; 1402f7f7464aSKONRAD Frederic } 1403f7f7464aSKONRAD Frederic 1404f7f7464aSKONRAD Frederic static void virtio_serial_pci_instance_init(Object *obj) 1405f7f7464aSKONRAD Frederic { 1406f7f7464aSKONRAD Frederic VirtIOSerialPCI *dev = VIRTIO_SERIAL_PCI(obj); 1407*c8075cafSGonglei 1408*c8075cafSGonglei virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), 1409*c8075cafSGonglei TYPE_VIRTIO_SERIAL); 1410f7f7464aSKONRAD Frederic } 1411f7f7464aSKONRAD Frederic 1412f7f7464aSKONRAD Frederic static const TypeInfo virtio_serial_pci_info = { 1413f7f7464aSKONRAD Frederic .name = TYPE_VIRTIO_SERIAL_PCI, 1414f7f7464aSKONRAD Frederic .parent = TYPE_VIRTIO_PCI, 1415f7f7464aSKONRAD Frederic .instance_size = sizeof(VirtIOSerialPCI), 1416f7f7464aSKONRAD Frederic .instance_init = virtio_serial_pci_instance_init, 1417f7f7464aSKONRAD Frederic .class_init = virtio_serial_pci_class_init, 1418f7f7464aSKONRAD Frederic }; 1419f7f7464aSKONRAD Frederic 1420e37da394SKONRAD Frederic /* virtio-net-pci */ 1421e37da394SKONRAD Frederic 1422e37da394SKONRAD Frederic static Property virtio_net_properties[] = { 1423e37da394SKONRAD Frederic DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, 1424e37da394SKONRAD Frederic VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false), 1425e37da394SKONRAD Frederic DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3), 1426e37da394SKONRAD Frederic DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features), 1427e37da394SKONRAD Frederic DEFINE_PROP_END_OF_LIST(), 1428e37da394SKONRAD Frederic }; 1429e37da394SKONRAD Frederic 1430e37da394SKONRAD Frederic static int virtio_net_pci_init(VirtIOPCIProxy *vpci_dev) 1431e37da394SKONRAD Frederic { 1432800ced8cSKONRAD Frederic DeviceState *qdev = DEVICE(vpci_dev); 1433e37da394SKONRAD Frederic VirtIONetPCI *dev = VIRTIO_NET_PCI(vpci_dev); 1434e37da394SKONRAD Frederic DeviceState *vdev = DEVICE(&dev->vdev); 1435e37da394SKONRAD Frederic 1436e37da394SKONRAD Frederic virtio_net_set_config_size(&dev->vdev, vpci_dev->host_features); 1437800ced8cSKONRAD Frederic virtio_net_set_netclient_name(&dev->vdev, qdev->id, 1438800ced8cSKONRAD Frederic object_get_typename(OBJECT(qdev))); 1439e37da394SKONRAD Frederic qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); 1440e37da394SKONRAD Frederic if (qdev_init(vdev) < 0) { 1441e37da394SKONRAD Frederic return -1; 1442e37da394SKONRAD Frederic } 1443e37da394SKONRAD Frederic return 0; 1444e37da394SKONRAD Frederic } 1445e37da394SKONRAD Frederic 1446e37da394SKONRAD Frederic static void virtio_net_pci_class_init(ObjectClass *klass, void *data) 1447e37da394SKONRAD Frederic { 1448e37da394SKONRAD Frederic DeviceClass *dc = DEVICE_CLASS(klass); 1449e37da394SKONRAD Frederic PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 1450e37da394SKONRAD Frederic VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass); 1451e37da394SKONRAD Frederic 1452e37da394SKONRAD Frederic k->romfile = "efi-virtio.rom"; 1453e37da394SKONRAD Frederic k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 1454e37da394SKONRAD Frederic k->device_id = PCI_DEVICE_ID_VIRTIO_NET; 1455e37da394SKONRAD Frederic k->revision = VIRTIO_PCI_ABI_VERSION; 1456e37da394SKONRAD Frederic k->class_id = PCI_CLASS_NETWORK_ETHERNET; 1457125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); 1458e37da394SKONRAD Frederic dc->props = virtio_net_properties; 1459e37da394SKONRAD Frederic vpciklass->init = virtio_net_pci_init; 1460e37da394SKONRAD Frederic } 1461e37da394SKONRAD Frederic 1462e37da394SKONRAD Frederic static void virtio_net_pci_instance_init(Object *obj) 1463e37da394SKONRAD Frederic { 1464e37da394SKONRAD Frederic VirtIONetPCI *dev = VIRTIO_NET_PCI(obj); 1465*c8075cafSGonglei 1466*c8075cafSGonglei virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), 1467*c8075cafSGonglei TYPE_VIRTIO_NET); 1468e37da394SKONRAD Frederic } 1469e37da394SKONRAD Frederic 1470e37da394SKONRAD Frederic static const TypeInfo virtio_net_pci_info = { 1471e37da394SKONRAD Frederic .name = TYPE_VIRTIO_NET_PCI, 1472e37da394SKONRAD Frederic .parent = TYPE_VIRTIO_PCI, 1473e37da394SKONRAD Frederic .instance_size = sizeof(VirtIONetPCI), 1474e37da394SKONRAD Frederic .instance_init = virtio_net_pci_instance_init, 1475e37da394SKONRAD Frederic .class_init = virtio_net_pci_class_init, 1476e37da394SKONRAD Frederic }; 1477e37da394SKONRAD Frederic 147859ccd20aSKONRAD Frederic /* virtio-rng-pci */ 147959ccd20aSKONRAD Frederic 148059ccd20aSKONRAD Frederic static Property virtio_rng_pci_properties[] = { 148159ccd20aSKONRAD Frederic DEFINE_PROP_END_OF_LIST(), 148259ccd20aSKONRAD Frederic }; 148359ccd20aSKONRAD Frederic 148459ccd20aSKONRAD Frederic static int virtio_rng_pci_init(VirtIOPCIProxy *vpci_dev) 148559ccd20aSKONRAD Frederic { 148659ccd20aSKONRAD Frederic VirtIORngPCI *vrng = VIRTIO_RNG_PCI(vpci_dev); 148759ccd20aSKONRAD Frederic DeviceState *vdev = DEVICE(&vrng->vdev); 148859ccd20aSKONRAD Frederic 148959ccd20aSKONRAD Frederic qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); 149059ccd20aSKONRAD Frederic if (qdev_init(vdev) < 0) { 149159ccd20aSKONRAD Frederic return -1; 149259ccd20aSKONRAD Frederic } 149359ccd20aSKONRAD Frederic 149459ccd20aSKONRAD Frederic object_property_set_link(OBJECT(vrng), 14955b456438SCole Robinson OBJECT(vrng->vdev.conf.rng), "rng", 149659ccd20aSKONRAD Frederic NULL); 149759ccd20aSKONRAD Frederic 149859ccd20aSKONRAD Frederic return 0; 149959ccd20aSKONRAD Frederic } 150059ccd20aSKONRAD Frederic 150159ccd20aSKONRAD Frederic static void virtio_rng_pci_class_init(ObjectClass *klass, void *data) 150259ccd20aSKONRAD Frederic { 150359ccd20aSKONRAD Frederic DeviceClass *dc = DEVICE_CLASS(klass); 150459ccd20aSKONRAD Frederic VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); 150559ccd20aSKONRAD Frederic PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); 150659ccd20aSKONRAD Frederic 150759ccd20aSKONRAD Frederic k->init = virtio_rng_pci_init; 1508125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_MISC, dc->categories); 150959ccd20aSKONRAD Frederic dc->props = virtio_rng_pci_properties; 151059ccd20aSKONRAD Frederic 151159ccd20aSKONRAD Frederic pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; 151259ccd20aSKONRAD Frederic pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_RNG; 151359ccd20aSKONRAD Frederic pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; 151459ccd20aSKONRAD Frederic pcidev_k->class_id = PCI_CLASS_OTHERS; 151559ccd20aSKONRAD Frederic } 151659ccd20aSKONRAD Frederic 151759ccd20aSKONRAD Frederic static void virtio_rng_initfn(Object *obj) 151859ccd20aSKONRAD Frederic { 151959ccd20aSKONRAD Frederic VirtIORngPCI *dev = VIRTIO_RNG_PCI(obj); 1520*c8075cafSGonglei 1521*c8075cafSGonglei virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), 1522*c8075cafSGonglei TYPE_VIRTIO_RNG); 152359ccd20aSKONRAD Frederic object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, 15249561fda8SStefan Hajnoczi (Object **)&dev->vdev.conf.rng, 152539f72ef9SStefan Hajnoczi qdev_prop_allow_set_link_before_realize, 15269561fda8SStefan Hajnoczi OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL); 152759ccd20aSKONRAD Frederic 152859ccd20aSKONRAD Frederic } 152959ccd20aSKONRAD Frederic 153059ccd20aSKONRAD Frederic static const TypeInfo virtio_rng_pci_info = { 153159ccd20aSKONRAD Frederic .name = TYPE_VIRTIO_RNG_PCI, 153259ccd20aSKONRAD Frederic .parent = TYPE_VIRTIO_PCI, 153359ccd20aSKONRAD Frederic .instance_size = sizeof(VirtIORngPCI), 153459ccd20aSKONRAD Frederic .instance_init = virtio_rng_initfn, 153559ccd20aSKONRAD Frederic .class_init = virtio_rng_pci_class_init, 153659ccd20aSKONRAD Frederic }; 153759ccd20aSKONRAD Frederic 15380a2acf5eSKONRAD Frederic /* virtio-pci-bus */ 15390a2acf5eSKONRAD Frederic 1540ac7af112SAndreas Färber static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, 1541ac7af112SAndreas Färber VirtIOPCIProxy *dev) 15420a2acf5eSKONRAD Frederic { 15430a2acf5eSKONRAD Frederic DeviceState *qdev = DEVICE(dev); 15440a2acf5eSKONRAD Frederic BusState *qbus; 1545f4dd69aaSKONRAD Frederic char virtio_bus_name[] = "virtio-bus"; 1546f4dd69aaSKONRAD Frederic 1547fb17dfe0SAndreas Färber qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_PCI_BUS, qdev, 1548f4dd69aaSKONRAD Frederic virtio_bus_name); 15490a2acf5eSKONRAD Frederic qbus = BUS(bus); 1550cbd19063SKONRAD Frederic qbus->allow_hotplug = 1; 15510a2acf5eSKONRAD Frederic } 15520a2acf5eSKONRAD Frederic 15530a2acf5eSKONRAD Frederic static void virtio_pci_bus_class_init(ObjectClass *klass, void *data) 15540a2acf5eSKONRAD Frederic { 15550a2acf5eSKONRAD Frederic BusClass *bus_class = BUS_CLASS(klass); 15560a2acf5eSKONRAD Frederic VirtioBusClass *k = VIRTIO_BUS_CLASS(klass); 15570a2acf5eSKONRAD Frederic bus_class->max_dev = 1; 15580a2acf5eSKONRAD Frederic k->notify = virtio_pci_notify; 15590a2acf5eSKONRAD Frederic k->save_config = virtio_pci_save_config; 15600a2acf5eSKONRAD Frederic k->load_config = virtio_pci_load_config; 15610a2acf5eSKONRAD Frederic k->save_queue = virtio_pci_save_queue; 15620a2acf5eSKONRAD Frederic k->load_queue = virtio_pci_load_queue; 15630a2acf5eSKONRAD Frederic k->get_features = virtio_pci_get_features; 15640a2acf5eSKONRAD Frederic k->query_guest_notifiers = virtio_pci_query_guest_notifiers; 15650a2acf5eSKONRAD Frederic k->set_host_notifier = virtio_pci_set_host_notifier; 15660a2acf5eSKONRAD Frederic k->set_guest_notifiers = virtio_pci_set_guest_notifiers; 15670a2acf5eSKONRAD Frederic k->vmstate_change = virtio_pci_vmstate_change; 1568085bccb7SKONRAD Frederic k->device_plugged = virtio_pci_device_plugged; 156906a13073SPaolo Bonzini k->device_unplugged = virtio_pci_device_unplugged; 15700a2acf5eSKONRAD Frederic } 15710a2acf5eSKONRAD Frederic 15720a2acf5eSKONRAD Frederic static const TypeInfo virtio_pci_bus_info = { 15730a2acf5eSKONRAD Frederic .name = TYPE_VIRTIO_PCI_BUS, 15740a2acf5eSKONRAD Frederic .parent = TYPE_VIRTIO_BUS, 15750a2acf5eSKONRAD Frederic .instance_size = sizeof(VirtioPCIBusState), 15760a2acf5eSKONRAD Frederic .class_init = virtio_pci_bus_class_init, 15770a2acf5eSKONRAD Frederic }; 15780a2acf5eSKONRAD Frederic 157983f7d43aSAndreas Färber static void virtio_pci_register_types(void) 158053c25ceaSPaul Brook { 158159ccd20aSKONRAD Frederic type_register_static(&virtio_rng_pci_info); 15820a2acf5eSKONRAD Frederic type_register_static(&virtio_pci_bus_info); 1583085bccb7SKONRAD Frederic type_register_static(&virtio_pci_info); 158460653b28SPaolo Bonzini #ifdef CONFIG_VIRTFS 1585234a336fSKONRAD Frederic type_register_static(&virtio_9p_pci_info); 158660653b28SPaolo Bonzini #endif 1587653ced07SKONRAD Frederic type_register_static(&virtio_blk_pci_info); 1588bc7b90a0SKONRAD Frederic type_register_static(&virtio_scsi_pci_info); 1589e378e88dSKONRAD Frederic type_register_static(&virtio_balloon_pci_info); 1590f7f7464aSKONRAD Frederic type_register_static(&virtio_serial_pci_info); 1591e37da394SKONRAD Frederic type_register_static(&virtio_net_pci_info); 159250787628SNicholas Bellinger #ifdef CONFIG_VHOST_SCSI 159350787628SNicholas Bellinger type_register_static(&vhost_scsi_pci_info); 159450787628SNicholas Bellinger #endif 159553c25ceaSPaul Brook } 159653c25ceaSPaul Brook 159783f7d43aSAndreas Färber type_init(virtio_pci_register_types) 1598