136f5dc91SSasha Levin #include "kvm/virtio-pci.h" 236f5dc91SSasha Levin 336f5dc91SSasha Levin #include "kvm/ioport.h" 436f5dc91SSasha Levin #include "kvm/kvm.h" 536f5dc91SSasha Levin #include "kvm/virtio-pci-dev.h" 636f5dc91SSasha Levin #include "kvm/irq.h" 736f5dc91SSasha Levin #include "kvm/virtio.h" 81599d724SSasha Levin #include "kvm/ioeventfd.h" 936f5dc91SSasha Levin 1043c81c74SSasha Levin #include <sys/ioctl.h> 1136f5dc91SSasha Levin #include <linux/virtio_pci.h> 12aa73be70SMatt Evans #include <linux/byteorder.h> 1336f5dc91SSasha Levin #include <string.h> 1436f5dc91SSasha Levin 151599d724SSasha Levin static void virtio_pci__ioevent_callback(struct kvm *kvm, void *param) 161599d724SSasha Levin { 171599d724SSasha Levin struct virtio_pci_ioevent_param *ioeventfd = param; 1802eca50cSAsias He struct virtio_pci *vpci = ioeventfd->vdev->virtio; 191599d724SSasha Levin 2002eca50cSAsias He ioeventfd->vdev->ops->notify_vq(kvm, vpci->dev, ioeventfd->vq); 211599d724SSasha Levin } 221599d724SSasha Levin 2302eca50cSAsias He static int virtio_pci__init_ioeventfd(struct kvm *kvm, struct virtio_device *vdev, u32 vq) 241599d724SSasha Levin { 251599d724SSasha Levin struct ioevent ioevent; 2602eca50cSAsias He struct virtio_pci *vpci = vdev->virtio; 27*a463650cSWill Deacon int i, r, flags = IOEVENTFD_FLAG_PIO; 28*a463650cSWill Deacon int fds[2]; 291599d724SSasha Levin 301599d724SSasha Levin vpci->ioeventfds[vq] = (struct virtio_pci_ioevent_param) { 3102eca50cSAsias He .vdev = vdev, 321599d724SSasha Levin .vq = vq, 331599d724SSasha Levin }; 341599d724SSasha Levin 351599d724SSasha Levin ioevent = (struct ioevent) { 361599d724SSasha Levin .fn = virtio_pci__ioevent_callback, 371599d724SSasha Levin .fn_ptr = &vpci->ioeventfds[vq], 381599d724SSasha Levin .datamatch = vq, 391599d724SSasha Levin .fn_kvm = kvm, 401599d724SSasha Levin }; 411599d724SSasha Levin 42627d6874SAsias He /* 43*a463650cSWill Deacon * Vhost will poll the eventfd in host kernel side, otherwise we 44*a463650cSWill Deacon * need to poll in userspace. 45627d6874SAsias He */ 46*a463650cSWill Deacon if (!vdev->use_vhost) 47*a463650cSWill Deacon flags |= IOEVENTFD_FLAG_USER_POLL; 48*a463650cSWill Deacon 49*a463650cSWill Deacon /* ioport */ 50*a463650cSWill Deacon ioevent.io_addr = vpci->port_addr + VIRTIO_PCI_QUEUE_NOTIFY; 51*a463650cSWill Deacon ioevent.io_len = sizeof(u16); 52*a463650cSWill Deacon ioevent.fd = fds[0] = eventfd(0, 0); 53*a463650cSWill Deacon r = ioeventfd__add_event(&ioevent, flags); 54ea6eeb1cSSasha Levin if (r) 55ea6eeb1cSSasha Levin return r; 561599d724SSasha Levin 57*a463650cSWill Deacon /* mmio */ 58*a463650cSWill Deacon ioevent.io_addr = vpci->mmio_addr + VIRTIO_PCI_QUEUE_NOTIFY; 59*a463650cSWill Deacon ioevent.io_len = sizeof(u32); 60*a463650cSWill Deacon ioevent.fd = fds[1] = eventfd(0, 0); 61*a463650cSWill Deacon r = ioeventfd__add_event(&ioevent, flags); 62*a463650cSWill Deacon if (r) 63*a463650cSWill Deacon goto free_ioport_evt; 64263b80e8SSasha Levin 65*a463650cSWill Deacon if (vdev->ops->notify_vq_eventfd) 66*a463650cSWill Deacon for (i = 0; i < 2; ++i) 67*a463650cSWill Deacon vdev->ops->notify_vq_eventfd(kvm, vpci->dev, vq, 68*a463650cSWill Deacon fds[i]); 691599d724SSasha Levin return 0; 70*a463650cSWill Deacon 71*a463650cSWill Deacon free_ioport_evt: 72*a463650cSWill Deacon ioeventfd__del_event(vpci->port_addr + VIRTIO_PCI_QUEUE_NOTIFY, vq); 73*a463650cSWill Deacon return r; 741599d724SSasha Levin } 751599d724SSasha Levin 7606f48103SSasha Levin static inline bool virtio_pci__msix_enabled(struct virtio_pci *vpci) 7706f48103SSasha Levin { 78aa73be70SMatt Evans return vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_ENABLE); 7906f48103SSasha Levin } 8006f48103SSasha Levin 8102eca50cSAsias He static bool virtio_pci__specific_io_in(struct kvm *kvm, struct virtio_device *vdev, u16 port, 8236f5dc91SSasha Levin void *data, int size, int offset) 8336f5dc91SSasha Levin { 8436f5dc91SSasha Levin u32 config_offset; 8502eca50cSAsias He struct virtio_pci *vpci = vdev->virtio; 8606f48103SSasha Levin int type = virtio__get_dev_specific_field(offset - 20, 8706f48103SSasha Levin virtio_pci__msix_enabled(vpci), 881382aba0SSasha Levin &config_offset); 8936f5dc91SSasha Levin if (type == VIRTIO_PCI_O_MSIX) { 9036f5dc91SSasha Levin switch (offset) { 9136f5dc91SSasha Levin case VIRTIO_MSI_CONFIG_VECTOR: 9236f5dc91SSasha Levin ioport__write16(data, vpci->config_vector); 9336f5dc91SSasha Levin break; 9436f5dc91SSasha Levin case VIRTIO_MSI_QUEUE_VECTOR: 9536f5dc91SSasha Levin ioport__write16(data, vpci->vq_vector[vpci->queue_selector]); 9636f5dc91SSasha Levin break; 9736f5dc91SSasha Levin }; 9836f5dc91SSasha Levin 9936f5dc91SSasha Levin return true; 10036f5dc91SSasha Levin } else if (type == VIRTIO_PCI_O_CONFIG) { 10136f5dc91SSasha Levin u8 cfg; 10236f5dc91SSasha Levin 103c5ae742bSSasha Levin cfg = vdev->ops->get_config(kvm, vpci->dev)[config_offset]; 10436f5dc91SSasha Levin ioport__write8(data, cfg); 10536f5dc91SSasha Levin return true; 10636f5dc91SSasha Levin } 10736f5dc91SSasha Levin 10836f5dc91SSasha Levin return false; 10936f5dc91SSasha Levin } 11036f5dc91SSasha Levin 11136f5dc91SSasha Levin static bool virtio_pci__io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 11236f5dc91SSasha Levin { 11336f5dc91SSasha Levin unsigned long offset; 11436f5dc91SSasha Levin bool ret = true; 11502eca50cSAsias He struct virtio_device *vdev; 11636f5dc91SSasha Levin struct virtio_pci *vpci; 11736f5dc91SSasha Levin u32 val; 11836f5dc91SSasha Levin 11902eca50cSAsias He vdev = ioport->priv; 12002eca50cSAsias He vpci = vdev->virtio; 121*a463650cSWill Deacon offset = port - vpci->port_addr; 12236f5dc91SSasha Levin 12336f5dc91SSasha Levin switch (offset) { 12436f5dc91SSasha Levin case VIRTIO_PCI_HOST_FEATURES: 12502eca50cSAsias He val = vdev->ops->get_host_features(kvm, vpci->dev); 12636f5dc91SSasha Levin ioport__write32(data, val); 12736f5dc91SSasha Levin break; 12836f5dc91SSasha Levin case VIRTIO_PCI_QUEUE_PFN: 12902eca50cSAsias He val = vdev->ops->get_pfn_vq(kvm, vpci->dev, vpci->queue_selector); 13036f5dc91SSasha Levin ioport__write32(data, val); 13136f5dc91SSasha Levin break; 13236f5dc91SSasha Levin case VIRTIO_PCI_QUEUE_NUM: 13302eca50cSAsias He val = vdev->ops->get_size_vq(kvm, vpci->dev, vpci->queue_selector); 134657ee18bSMatt Evans ioport__write16(data, val); 13536f5dc91SSasha Levin break; 13636f5dc91SSasha Levin case VIRTIO_PCI_STATUS: 13736f5dc91SSasha Levin ioport__write8(data, vpci->status); 13836f5dc91SSasha Levin break; 13936f5dc91SSasha Levin case VIRTIO_PCI_ISR: 14036f5dc91SSasha Levin ioport__write8(data, vpci->isr); 14136f5dc91SSasha Levin kvm__irq_line(kvm, vpci->pci_hdr.irq_line, VIRTIO_IRQ_LOW); 14236f5dc91SSasha Levin vpci->isr = VIRTIO_IRQ_LOW; 14336f5dc91SSasha Levin break; 14436f5dc91SSasha Levin default: 14502eca50cSAsias He ret = virtio_pci__specific_io_in(kvm, vdev, port, data, size, offset); 14636f5dc91SSasha Levin break; 14736f5dc91SSasha Levin }; 14836f5dc91SSasha Levin 14936f5dc91SSasha Levin return ret; 15036f5dc91SSasha Levin } 15136f5dc91SSasha Levin 15202eca50cSAsias He static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_device *vdev, u16 port, 15336f5dc91SSasha Levin void *data, int size, int offset) 15436f5dc91SSasha Levin { 15502eca50cSAsias He struct virtio_pci *vpci = vdev->virtio; 15636f5dc91SSasha Levin u32 config_offset, gsi, vec; 15706f48103SSasha Levin int type = virtio__get_dev_specific_field(offset - 20, virtio_pci__msix_enabled(vpci), 1581382aba0SSasha Levin &config_offset); 15936f5dc91SSasha Levin if (type == VIRTIO_PCI_O_MSIX) { 16036f5dc91SSasha Levin switch (offset) { 16136f5dc91SSasha Levin case VIRTIO_MSI_CONFIG_VECTOR: 16236f5dc91SSasha Levin vec = vpci->config_vector = ioport__read16(data); 163f8327b05SSasha Levin if (vec == VIRTIO_MSI_NO_VECTOR) 164f8327b05SSasha Levin break; 16536f5dc91SSasha Levin 1661de74957SSasha Levin gsi = irq__add_msix_route(kvm, &vpci->msix_table[vec].msg); 16736f5dc91SSasha Levin 16836f5dc91SSasha Levin vpci->config_gsi = gsi; 16936f5dc91SSasha Levin break; 1703a60be06SSasha Levin case VIRTIO_MSI_QUEUE_VECTOR: 17136f5dc91SSasha Levin vec = vpci->vq_vector[vpci->queue_selector] = ioport__read16(data); 17236f5dc91SSasha Levin 173f8327b05SSasha Levin if (vec == VIRTIO_MSI_NO_VECTOR) 174f8327b05SSasha Levin break; 175f8327b05SSasha Levin 1761de74957SSasha Levin gsi = irq__add_msix_route(kvm, &vpci->msix_table[vec].msg); 17736f5dc91SSasha Levin vpci->gsis[vpci->queue_selector] = gsi; 17802eca50cSAsias He if (vdev->ops->notify_vq_gsi) 17902eca50cSAsias He vdev->ops->notify_vq_gsi(kvm, vpci->dev, 180263b80e8SSasha Levin vpci->queue_selector, gsi); 18136f5dc91SSasha Levin break; 18236f5dc91SSasha Levin }; 18336f5dc91SSasha Levin 18436f5dc91SSasha Levin return true; 18536f5dc91SSasha Levin } else if (type == VIRTIO_PCI_O_CONFIG) { 186c5ae742bSSasha Levin vdev->ops->get_config(kvm, vpci->dev)[config_offset] = *(u8 *)data; 18736f5dc91SSasha Levin 18836f5dc91SSasha Levin return true; 18936f5dc91SSasha Levin } 19036f5dc91SSasha Levin 19136f5dc91SSasha Levin return false; 19236f5dc91SSasha Levin } 19336f5dc91SSasha Levin 19436f5dc91SSasha Levin static bool virtio_pci__io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 19536f5dc91SSasha Levin { 19636f5dc91SSasha Levin unsigned long offset; 19736f5dc91SSasha Levin bool ret = true; 19802eca50cSAsias He struct virtio_device *vdev; 19936f5dc91SSasha Levin struct virtio_pci *vpci; 20036f5dc91SSasha Levin u32 val; 20136f5dc91SSasha Levin 20202eca50cSAsias He vdev = ioport->priv; 20302eca50cSAsias He vpci = vdev->virtio; 204*a463650cSWill Deacon offset = port - vpci->port_addr; 20536f5dc91SSasha Levin 20636f5dc91SSasha Levin switch (offset) { 20736f5dc91SSasha Levin case VIRTIO_PCI_GUEST_FEATURES: 20836f5dc91SSasha Levin val = ioport__read32(data); 20902eca50cSAsias He vdev->ops->set_guest_features(kvm, vpci->dev, val); 21036f5dc91SSasha Levin break; 21136f5dc91SSasha Levin case VIRTIO_PCI_QUEUE_PFN: 21236f5dc91SSasha Levin val = ioport__read32(data); 21302eca50cSAsias He virtio_pci__init_ioeventfd(kvm, vdev, vpci->queue_selector); 214c59ba304SWill Deacon vdev->ops->init_vq(kvm, vpci->dev, vpci->queue_selector, 215c59ba304SWill Deacon 1 << VIRTIO_PCI_QUEUE_ADDR_SHIFT, 216c59ba304SWill Deacon VIRTIO_PCI_VRING_ALIGN, val); 21736f5dc91SSasha Levin break; 21836f5dc91SSasha Levin case VIRTIO_PCI_QUEUE_SEL: 21936f5dc91SSasha Levin vpci->queue_selector = ioport__read16(data); 22036f5dc91SSasha Levin break; 22136f5dc91SSasha Levin case VIRTIO_PCI_QUEUE_NOTIFY: 22236f5dc91SSasha Levin val = ioport__read16(data); 22302eca50cSAsias He vdev->ops->notify_vq(kvm, vpci->dev, val); 22436f5dc91SSasha Levin break; 22536f5dc91SSasha Levin case VIRTIO_PCI_STATUS: 22636f5dc91SSasha Levin vpci->status = ioport__read8(data); 22704b53c16SSasha Levin if (vdev->ops->notify_status) 22804b53c16SSasha Levin vdev->ops->notify_status(kvm, vpci->dev, vpci->status); 22936f5dc91SSasha Levin break; 23036f5dc91SSasha Levin default: 23102eca50cSAsias He ret = virtio_pci__specific_io_out(kvm, vdev, port, data, size, offset); 23236f5dc91SSasha Levin break; 23336f5dc91SSasha Levin }; 23436f5dc91SSasha Levin 23536f5dc91SSasha Levin return ret; 23636f5dc91SSasha Levin } 23736f5dc91SSasha Levin 23836f5dc91SSasha Levin static struct ioport_operations virtio_pci__io_ops = { 23936f5dc91SSasha Levin .io_in = virtio_pci__io_in, 24036f5dc91SSasha Levin .io_out = virtio_pci__io_out, 24136f5dc91SSasha Levin }; 24236f5dc91SSasha Levin 243*a463650cSWill Deacon static void virtio_pci__msix_mmio_callback(u64 addr, u8 *data, u32 len, 244*a463650cSWill Deacon u8 is_write, void *ptr) 24536f5dc91SSasha Levin { 24636f5dc91SSasha Levin struct virtio_pci *vpci = ptr; 2479c26dab4SSasha Levin void *table; 2489c26dab4SSasha Levin u32 offset; 24936f5dc91SSasha Levin 2509c26dab4SSasha Levin if (addr > vpci->msix_io_block + PCI_IO_SIZE) { 2519c26dab4SSasha Levin table = &vpci->msix_pba; 2529c26dab4SSasha Levin offset = vpci->msix_io_block + PCI_IO_SIZE; 2539c26dab4SSasha Levin } else { 2549c26dab4SSasha Levin table = &vpci->msix_table; 2559c26dab4SSasha Levin offset = vpci->msix_io_block; 25636f5dc91SSasha Levin } 25736f5dc91SSasha Levin 25806f48103SSasha Levin if (is_write) 2599c26dab4SSasha Levin memcpy(table + addr - offset, data, len); 26006f48103SSasha Levin else 2619c26dab4SSasha Levin memcpy(data, table + addr - offset, len); 26206f48103SSasha Levin } 26306f48103SSasha Levin 26443c81c74SSasha Levin static void virtio_pci__signal_msi(struct kvm *kvm, struct virtio_pci *vpci, int vec) 26543c81c74SSasha Levin { 26643c81c74SSasha Levin struct kvm_msi msi = { 26743c81c74SSasha Levin .address_lo = vpci->msix_table[vec].msg.address_lo, 26843c81c74SSasha Levin .address_hi = vpci->msix_table[vec].msg.address_hi, 26943c81c74SSasha Levin .data = vpci->msix_table[vec].msg.data, 27043c81c74SSasha Levin }; 27143c81c74SSasha Levin 27243c81c74SSasha Levin ioctl(kvm->vm_fd, KVM_SIGNAL_MSI, &msi); 27343c81c74SSasha Levin } 27443c81c74SSasha Levin 27502eca50cSAsias He int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_device *vdev, u32 vq) 27636f5dc91SSasha Levin { 27702eca50cSAsias He struct virtio_pci *vpci = vdev->virtio; 27806f48103SSasha Levin int tbl = vpci->vq_vector[vq]; 27936f5dc91SSasha Levin 280f8327b05SSasha Levin if (virtio_pci__msix_enabled(vpci) && tbl != VIRTIO_MSI_NO_VECTOR) { 281aa73be70SMatt Evans if (vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_MASKALL) || 282aa73be70SMatt Evans vpci->msix_table[tbl].ctrl & cpu_to_le16(PCI_MSIX_ENTRY_CTRL_MASKBIT)) { 28306f48103SSasha Levin 28406f48103SSasha Levin vpci->msix_pba |= 1 << tbl; 28506f48103SSasha Levin return 0; 28606f48103SSasha Levin } 28706f48103SSasha Levin 28843c81c74SSasha Levin if (vpci->features & VIRTIO_PCI_F_SIGNAL_MSI) 28943c81c74SSasha Levin virtio_pci__signal_msi(kvm, vpci, vpci->vq_vector[vq]); 29043c81c74SSasha Levin else 29106f48103SSasha Levin kvm__irq_trigger(kvm, vpci->gsis[vq]); 29206f48103SSasha Levin } else { 293a36eca7bSSasha Levin vpci->isr = VIRTIO_IRQ_HIGH; 29406f48103SSasha Levin kvm__irq_trigger(kvm, vpci->pci_hdr.irq_line); 29506f48103SSasha Levin } 29636f5dc91SSasha Levin return 0; 29736f5dc91SSasha Levin } 29836f5dc91SSasha Levin 29902eca50cSAsias He int virtio_pci__signal_config(struct kvm *kvm, struct virtio_device *vdev) 30036f5dc91SSasha Levin { 30102eca50cSAsias He struct virtio_pci *vpci = vdev->virtio; 30206f48103SSasha Levin int tbl = vpci->config_vector; 30306f48103SSasha Levin 304f8327b05SSasha Levin if (virtio_pci__msix_enabled(vpci) && tbl != VIRTIO_MSI_NO_VECTOR) { 305aa73be70SMatt Evans if (vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_MASKALL) || 306aa73be70SMatt Evans vpci->msix_table[tbl].ctrl & cpu_to_le16(PCI_MSIX_ENTRY_CTRL_MASKBIT)) { 30706f48103SSasha Levin 30806f48103SSasha Levin vpci->msix_pba |= 1 << tbl; 30906f48103SSasha Levin return 0; 31006f48103SSasha Levin } 31106f48103SSasha Levin 31243c81c74SSasha Levin if (vpci->features & VIRTIO_PCI_F_SIGNAL_MSI) 313f8327b05SSasha Levin virtio_pci__signal_msi(kvm, vpci, tbl); 31443c81c74SSasha Levin else 31506f48103SSasha Levin kvm__irq_trigger(kvm, vpci->config_gsi); 31606f48103SSasha Levin } else { 31706f48103SSasha Levin vpci->isr = VIRTIO_PCI_ISR_CONFIG; 31806f48103SSasha Levin kvm__irq_trigger(kvm, vpci->pci_hdr.irq_line); 31906f48103SSasha Levin } 32036f5dc91SSasha Levin 32136f5dc91SSasha Levin return 0; 32236f5dc91SSasha Levin } 32336f5dc91SSasha Levin 324*a463650cSWill Deacon static void virtio_pci__io_mmio_callback(u64 addr, u8 *data, u32 len, 325*a463650cSWill Deacon u8 is_write, void *ptr) 326*a463650cSWill Deacon { 327*a463650cSWill Deacon struct virtio_pci *vpci = ptr; 328*a463650cSWill Deacon int direction = is_write ? KVM_EXIT_IO_OUT : KVM_EXIT_IO_IN; 329*a463650cSWill Deacon u16 port = vpci->port_addr + (addr & (IOPORT_SIZE - 1)); 330*a463650cSWill Deacon 331*a463650cSWill Deacon kvm__emulate_io(vpci->kvm, port, data, direction, len, 1); 332*a463650cSWill Deacon } 333*a463650cSWill Deacon 33402eca50cSAsias He int virtio_pci__init(struct kvm *kvm, void *dev, struct virtio_device *vdev, 335507e02d8SAsias He int device_id, int subsys_id, int class) 33636f5dc91SSasha Levin { 33702eca50cSAsias He struct virtio_pci *vpci = vdev->virtio; 33821ff329dSWill Deacon u8 pin, line; 3397af40b91SSasha Levin int r; 34036f5dc91SSasha Levin 341*a463650cSWill Deacon vpci->kvm = kvm; 34236f5dc91SSasha Levin vpci->dev = dev; 34336f5dc91SSasha Levin 3444346fd8fSSasha Levin r = ioport__register(kvm, IOPORT_EMPTY, &virtio_pci__io_ops, IOPORT_SIZE, vdev); 3457af40b91SSasha Levin if (r < 0) 3467af40b91SSasha Levin return r; 347*a463650cSWill Deacon vpci->port_addr = (u16)r; 3487af40b91SSasha Levin 349*a463650cSWill Deacon vpci->mmio_addr = pci_get_io_space_block(IOPORT_SIZE); 350*a463650cSWill Deacon r = kvm__register_mmio(kvm, vpci->mmio_addr, IOPORT_SIZE, false, 351*a463650cSWill Deacon virtio_pci__io_mmio_callback, vpci); 352495fbd4eSSasha Levin if (r < 0) 353495fbd4eSSasha Levin goto free_ioport; 35436f5dc91SSasha Levin 355*a463650cSWill Deacon vpci->msix_io_block = pci_get_io_space_block(PCI_IO_SIZE * 2); 356*a463650cSWill Deacon r = kvm__register_mmio(kvm, vpci->msix_io_block, PCI_IO_SIZE * 2, false, 357*a463650cSWill Deacon virtio_pci__msix_mmio_callback, vpci); 358*a463650cSWill Deacon if (r < 0) 359*a463650cSWill Deacon goto free_mmio; 360*a463650cSWill Deacon 36136f5dc91SSasha Levin vpci->pci_hdr = (struct pci_device_header) { 362aa73be70SMatt Evans .vendor_id = cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET), 363aa73be70SMatt Evans .device_id = cpu_to_le16(device_id), 36436f5dc91SSasha Levin .header_type = PCI_HEADER_TYPE_NORMAL, 36536f5dc91SSasha Levin .revision_id = 0, 366aa73be70SMatt Evans .class[0] = class & 0xff, 367aa73be70SMatt Evans .class[1] = (class >> 8) & 0xff, 368aa73be70SMatt Evans .class[2] = (class >> 16) & 0xff, 369aa73be70SMatt Evans .subsys_vendor_id = cpu_to_le16(PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET), 370aa73be70SMatt Evans .subsys_id = cpu_to_le16(subsys_id), 371*a463650cSWill Deacon .bar[0] = cpu_to_le32(vpci->mmio_addr 372*a463650cSWill Deacon | PCI_BASE_ADDRESS_SPACE_MEMORY), 373*a463650cSWill Deacon .bar[1] = cpu_to_le32(vpci->port_addr 3749c26dab4SSasha Levin | PCI_BASE_ADDRESS_SPACE_IO), 375*a463650cSWill Deacon .bar[2] = cpu_to_le32(vpci->msix_io_block 376b4dab816SSasha Levin | PCI_BASE_ADDRESS_SPACE_MEMORY), 377aa73be70SMatt Evans .status = cpu_to_le16(PCI_STATUS_CAP_LIST), 37836f5dc91SSasha Levin .capabilities = (void *)&vpci->pci_hdr.msix - (void *)&vpci->pci_hdr, 3796b868987SMatt Evans .bar_size[0] = IOPORT_SIZE, 380*a463650cSWill Deacon .bar_size[1] = IOPORT_SIZE, 381*a463650cSWill Deacon .bar_size[2] = PCI_IO_SIZE * 2, 38236f5dc91SSasha Levin }; 38336f5dc91SSasha Levin 38421ff329dSWill Deacon vpci->dev_hdr = (struct device_header) { 38521ff329dSWill Deacon .bus_type = DEVICE_BUS_PCI, 38621ff329dSWill Deacon .data = &vpci->pci_hdr, 38721ff329dSWill Deacon }; 38821ff329dSWill Deacon 38936f5dc91SSasha Levin vpci->pci_hdr.msix.cap = PCI_CAP_ID_MSIX; 39036f5dc91SSasha Levin vpci->pci_hdr.msix.next = 0; 39114bba8a0SAsias He /* 39214bba8a0SAsias He * We at most have VIRTIO_PCI_MAX_VQ entries for virt queue, 39314bba8a0SAsias He * VIRTIO_PCI_MAX_CONFIG entries for config. 39414bba8a0SAsias He * 39514bba8a0SAsias He * To quote the PCI spec: 39614bba8a0SAsias He * 39714bba8a0SAsias He * System software reads this field to determine the 39814bba8a0SAsias He * MSI-X Table Size N, which is encoded as N-1. 39914bba8a0SAsias He * For example, a returned value of "00000000011" 40014bba8a0SAsias He * indicates a table size of 4. 40114bba8a0SAsias He */ 402aa73be70SMatt Evans vpci->pci_hdr.msix.ctrl = cpu_to_le16(VIRTIO_PCI_MAX_VQ + VIRTIO_PCI_MAX_CONFIG - 1); 40306f48103SSasha Levin 404*a463650cSWill Deacon /* Both table and PBA are mapped to the same BAR (2) */ 405*a463650cSWill Deacon vpci->pci_hdr.msix.table_offset = cpu_to_le32(2); 406*a463650cSWill Deacon vpci->pci_hdr.msix.pba_offset = cpu_to_le32(2 | PCI_IO_SIZE); 40736f5dc91SSasha Levin vpci->config_vector = 0; 40836f5dc91SSasha Levin 40921ff329dSWill Deacon r = irq__register_device(subsys_id, &pin, &line); 410495fbd4eSSasha Levin if (r < 0) 411*a463650cSWill Deacon goto free_msix_mmio; 41236f5dc91SSasha Levin 41343c81c74SSasha Levin if (kvm__supports_extension(kvm, KVM_CAP_SIGNAL_MSI)) 41443c81c74SSasha Levin vpci->features |= VIRTIO_PCI_F_SIGNAL_MSI; 41543c81c74SSasha Levin 41636f5dc91SSasha Levin vpci->pci_hdr.irq_pin = pin; 41736f5dc91SSasha Levin vpci->pci_hdr.irq_line = line; 41821ff329dSWill Deacon r = device__register(&vpci->dev_hdr); 419495fbd4eSSasha Levin if (r < 0) 420*a463650cSWill Deacon goto free_msix_mmio; 421495fbd4eSSasha Levin 422495fbd4eSSasha Levin return 0; 423495fbd4eSSasha Levin 424*a463650cSWill Deacon free_msix_mmio: 425495fbd4eSSasha Levin kvm__deregister_mmio(kvm, vpci->msix_io_block); 426*a463650cSWill Deacon free_mmio: 427*a463650cSWill Deacon kvm__deregister_mmio(kvm, vpci->mmio_addr); 428495fbd4eSSasha Levin free_ioport: 429*a463650cSWill Deacon ioport__unregister(kvm, vpci->port_addr); 430495fbd4eSSasha Levin return r; 431495fbd4eSSasha Levin } 432495fbd4eSSasha Levin 43302eca50cSAsias He int virtio_pci__exit(struct kvm *kvm, struct virtio_device *vdev) 434495fbd4eSSasha Levin { 43502eca50cSAsias He struct virtio_pci *vpci = vdev->virtio; 436495fbd4eSSasha Levin int i; 437495fbd4eSSasha Levin 438*a463650cSWill Deacon kvm__deregister_mmio(kvm, vpci->mmio_addr); 439495fbd4eSSasha Levin kvm__deregister_mmio(kvm, vpci->msix_io_block); 440*a463650cSWill Deacon ioport__unregister(kvm, vpci->port_addr); 441495fbd4eSSasha Levin 442*a463650cSWill Deacon for (i = 0; i < VIRTIO_PCI_MAX_VQ; i++) { 443*a463650cSWill Deacon ioeventfd__del_event(vpci->port_addr + VIRTIO_PCI_QUEUE_NOTIFY, i); 444*a463650cSWill Deacon ioeventfd__del_event(vpci->mmio_addr + VIRTIO_PCI_QUEUE_NOTIFY, i); 445*a463650cSWill Deacon } 44636f5dc91SSasha Levin 44736f5dc91SSasha Levin return 0; 44836f5dc91SSasha Levin } 449