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; 27a463650cSWill Deacon int i, r, flags = IOEVENTFD_FLAG_PIO; 28a463650cSWill 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 /* 43a463650cSWill Deacon * Vhost will poll the eventfd in host kernel side, otherwise we 44a463650cSWill Deacon * need to poll in userspace. 45627d6874SAsias He */ 46a463650cSWill Deacon if (!vdev->use_vhost) 47a463650cSWill Deacon flags |= IOEVENTFD_FLAG_USER_POLL; 48a463650cSWill Deacon 49a463650cSWill Deacon /* ioport */ 50a463650cSWill Deacon ioevent.io_addr = vpci->port_addr + VIRTIO_PCI_QUEUE_NOTIFY; 51a463650cSWill Deacon ioevent.io_len = sizeof(u16); 52a463650cSWill Deacon ioevent.fd = fds[0] = eventfd(0, 0); 53a463650cSWill Deacon r = ioeventfd__add_event(&ioevent, flags); 54ea6eeb1cSSasha Levin if (r) 55ea6eeb1cSSasha Levin return r; 561599d724SSasha Levin 57a463650cSWill Deacon /* mmio */ 58a463650cSWill Deacon ioevent.io_addr = vpci->mmio_addr + VIRTIO_PCI_QUEUE_NOTIFY; 59a463650cSWill Deacon ioevent.io_len = sizeof(u32); 60a463650cSWill Deacon ioevent.fd = fds[1] = eventfd(0, 0); 61a463650cSWill Deacon r = ioeventfd__add_event(&ioevent, flags); 62a463650cSWill Deacon if (r) 63a463650cSWill Deacon goto free_ioport_evt; 64263b80e8SSasha Levin 65a463650cSWill Deacon if (vdev->ops->notify_vq_eventfd) 66a463650cSWill Deacon for (i = 0; i < 2; ++i) 67a463650cSWill Deacon vdev->ops->notify_vq_eventfd(kvm, vpci->dev, vq, 68a463650cSWill Deacon fds[i]); 691599d724SSasha Levin return 0; 70a463650cSWill Deacon 71a463650cSWill Deacon free_ioport_evt: 72a463650cSWill Deacon ioeventfd__del_event(vpci->port_addr + VIRTIO_PCI_QUEUE_NOTIFY, vq); 73a463650cSWill 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; 121a463650cSWill 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; 204a463650cSWill 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*9b735910SMarc Zyngier static void virtio_pci__msix_mmio_callback(struct kvm_cpu *vcpu, 244*9b735910SMarc Zyngier u64 addr, u8 *data, u32 len, 245a463650cSWill Deacon u8 is_write, void *ptr) 24636f5dc91SSasha Levin { 24736f5dc91SSasha Levin struct virtio_pci *vpci = ptr; 2489c26dab4SSasha Levin void *table; 2499c26dab4SSasha Levin u32 offset; 25036f5dc91SSasha Levin 2519c26dab4SSasha Levin if (addr > vpci->msix_io_block + PCI_IO_SIZE) { 2529c26dab4SSasha Levin table = &vpci->msix_pba; 2539c26dab4SSasha Levin offset = vpci->msix_io_block + PCI_IO_SIZE; 2549c26dab4SSasha Levin } else { 2559c26dab4SSasha Levin table = &vpci->msix_table; 2569c26dab4SSasha Levin offset = vpci->msix_io_block; 25736f5dc91SSasha Levin } 25836f5dc91SSasha Levin 25906f48103SSasha Levin if (is_write) 2609c26dab4SSasha Levin memcpy(table + addr - offset, data, len); 26106f48103SSasha Levin else 2629c26dab4SSasha Levin memcpy(data, table + addr - offset, len); 26306f48103SSasha Levin } 26406f48103SSasha Levin 26543c81c74SSasha Levin static void virtio_pci__signal_msi(struct kvm *kvm, struct virtio_pci *vpci, int vec) 26643c81c74SSasha Levin { 26743c81c74SSasha Levin struct kvm_msi msi = { 26843c81c74SSasha Levin .address_lo = vpci->msix_table[vec].msg.address_lo, 26943c81c74SSasha Levin .address_hi = vpci->msix_table[vec].msg.address_hi, 27043c81c74SSasha Levin .data = vpci->msix_table[vec].msg.data, 27143c81c74SSasha Levin }; 27243c81c74SSasha Levin 27343c81c74SSasha Levin ioctl(kvm->vm_fd, KVM_SIGNAL_MSI, &msi); 27443c81c74SSasha Levin } 27543c81c74SSasha Levin 27602eca50cSAsias He int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_device *vdev, u32 vq) 27736f5dc91SSasha Levin { 27802eca50cSAsias He struct virtio_pci *vpci = vdev->virtio; 27906f48103SSasha Levin int tbl = vpci->vq_vector[vq]; 28036f5dc91SSasha Levin 281f8327b05SSasha Levin if (virtio_pci__msix_enabled(vpci) && tbl != VIRTIO_MSI_NO_VECTOR) { 282aa73be70SMatt Evans if (vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_MASKALL) || 283aa73be70SMatt Evans vpci->msix_table[tbl].ctrl & cpu_to_le16(PCI_MSIX_ENTRY_CTRL_MASKBIT)) { 28406f48103SSasha Levin 28506f48103SSasha Levin vpci->msix_pba |= 1 << tbl; 28606f48103SSasha Levin return 0; 28706f48103SSasha Levin } 28806f48103SSasha Levin 28943c81c74SSasha Levin if (vpci->features & VIRTIO_PCI_F_SIGNAL_MSI) 29043c81c74SSasha Levin virtio_pci__signal_msi(kvm, vpci, vpci->vq_vector[vq]); 29143c81c74SSasha Levin else 29206f48103SSasha Levin kvm__irq_trigger(kvm, vpci->gsis[vq]); 29306f48103SSasha Levin } else { 294a36eca7bSSasha Levin vpci->isr = VIRTIO_IRQ_HIGH; 29506f48103SSasha Levin kvm__irq_trigger(kvm, vpci->pci_hdr.irq_line); 29606f48103SSasha Levin } 29736f5dc91SSasha Levin return 0; 29836f5dc91SSasha Levin } 29936f5dc91SSasha Levin 30002eca50cSAsias He int virtio_pci__signal_config(struct kvm *kvm, struct virtio_device *vdev) 30136f5dc91SSasha Levin { 30202eca50cSAsias He struct virtio_pci *vpci = vdev->virtio; 30306f48103SSasha Levin int tbl = vpci->config_vector; 30406f48103SSasha Levin 305f8327b05SSasha Levin if (virtio_pci__msix_enabled(vpci) && tbl != VIRTIO_MSI_NO_VECTOR) { 306aa73be70SMatt Evans if (vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_MASKALL) || 307aa73be70SMatt Evans vpci->msix_table[tbl].ctrl & cpu_to_le16(PCI_MSIX_ENTRY_CTRL_MASKBIT)) { 30806f48103SSasha Levin 30906f48103SSasha Levin vpci->msix_pba |= 1 << tbl; 31006f48103SSasha Levin return 0; 31106f48103SSasha Levin } 31206f48103SSasha Levin 31343c81c74SSasha Levin if (vpci->features & VIRTIO_PCI_F_SIGNAL_MSI) 314f8327b05SSasha Levin virtio_pci__signal_msi(kvm, vpci, tbl); 31543c81c74SSasha Levin else 31606f48103SSasha Levin kvm__irq_trigger(kvm, vpci->config_gsi); 31706f48103SSasha Levin } else { 31806f48103SSasha Levin vpci->isr = VIRTIO_PCI_ISR_CONFIG; 31906f48103SSasha Levin kvm__irq_trigger(kvm, vpci->pci_hdr.irq_line); 32006f48103SSasha Levin } 32136f5dc91SSasha Levin 32236f5dc91SSasha Levin return 0; 32336f5dc91SSasha Levin } 32436f5dc91SSasha Levin 325*9b735910SMarc Zyngier static void virtio_pci__io_mmio_callback(struct kvm_cpu *vcpu, 326*9b735910SMarc Zyngier u64 addr, u8 *data, u32 len, 327a463650cSWill Deacon u8 is_write, void *ptr) 328a463650cSWill Deacon { 329a463650cSWill Deacon struct virtio_pci *vpci = ptr; 330a463650cSWill Deacon int direction = is_write ? KVM_EXIT_IO_OUT : KVM_EXIT_IO_IN; 331a463650cSWill Deacon u16 port = vpci->port_addr + (addr & (IOPORT_SIZE - 1)); 332a463650cSWill Deacon 333a463650cSWill Deacon kvm__emulate_io(vpci->kvm, port, data, direction, len, 1); 334a463650cSWill Deacon } 335a463650cSWill Deacon 33602eca50cSAsias He int virtio_pci__init(struct kvm *kvm, void *dev, struct virtio_device *vdev, 337507e02d8SAsias He int device_id, int subsys_id, int class) 33836f5dc91SSasha Levin { 33902eca50cSAsias He struct virtio_pci *vpci = vdev->virtio; 3407af40b91SSasha Levin int r; 34136f5dc91SSasha Levin 342a463650cSWill Deacon vpci->kvm = kvm; 34336f5dc91SSasha Levin vpci->dev = dev; 34436f5dc91SSasha Levin 3454346fd8fSSasha Levin r = ioport__register(kvm, IOPORT_EMPTY, &virtio_pci__io_ops, IOPORT_SIZE, vdev); 3467af40b91SSasha Levin if (r < 0) 3477af40b91SSasha Levin return r; 348a463650cSWill Deacon vpci->port_addr = (u16)r; 3497af40b91SSasha Levin 350a463650cSWill Deacon vpci->mmio_addr = pci_get_io_space_block(IOPORT_SIZE); 351a463650cSWill Deacon r = kvm__register_mmio(kvm, vpci->mmio_addr, IOPORT_SIZE, false, 352a463650cSWill Deacon virtio_pci__io_mmio_callback, vpci); 353495fbd4eSSasha Levin if (r < 0) 354495fbd4eSSasha Levin goto free_ioport; 35536f5dc91SSasha Levin 356a463650cSWill Deacon vpci->msix_io_block = pci_get_io_space_block(PCI_IO_SIZE * 2); 357a463650cSWill Deacon r = kvm__register_mmio(kvm, vpci->msix_io_block, PCI_IO_SIZE * 2, false, 358a463650cSWill Deacon virtio_pci__msix_mmio_callback, vpci); 359a463650cSWill Deacon if (r < 0) 360a463650cSWill Deacon goto free_mmio; 361a463650cSWill Deacon 36236f5dc91SSasha Levin vpci->pci_hdr = (struct pci_device_header) { 363aa73be70SMatt Evans .vendor_id = cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET), 364aa73be70SMatt Evans .device_id = cpu_to_le16(device_id), 365ec7dd52fSSasha Levin .command = PCI_COMMAND_IO | PCI_COMMAND_MEMORY, 36636f5dc91SSasha Levin .header_type = PCI_HEADER_TYPE_NORMAL, 36736f5dc91SSasha Levin .revision_id = 0, 368aa73be70SMatt Evans .class[0] = class & 0xff, 369aa73be70SMatt Evans .class[1] = (class >> 8) & 0xff, 370aa73be70SMatt Evans .class[2] = (class >> 16) & 0xff, 371aa73be70SMatt Evans .subsys_vendor_id = cpu_to_le16(PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET), 372aa73be70SMatt Evans .subsys_id = cpu_to_le16(subsys_id), 373a463650cSWill Deacon .bar[0] = cpu_to_le32(vpci->mmio_addr 374a463650cSWill Deacon | PCI_BASE_ADDRESS_SPACE_MEMORY), 375a463650cSWill Deacon .bar[1] = cpu_to_le32(vpci->port_addr 3769c26dab4SSasha Levin | PCI_BASE_ADDRESS_SPACE_IO), 377a463650cSWill Deacon .bar[2] = cpu_to_le32(vpci->msix_io_block 378b4dab816SSasha Levin | PCI_BASE_ADDRESS_SPACE_MEMORY), 379aa73be70SMatt Evans .status = cpu_to_le16(PCI_STATUS_CAP_LIST), 38036f5dc91SSasha Levin .capabilities = (void *)&vpci->pci_hdr.msix - (void *)&vpci->pci_hdr, 3816b868987SMatt Evans .bar_size[0] = IOPORT_SIZE, 382a463650cSWill Deacon .bar_size[1] = IOPORT_SIZE, 383a463650cSWill Deacon .bar_size[2] = PCI_IO_SIZE * 2, 38436f5dc91SSasha Levin }; 38536f5dc91SSasha Levin 38621ff329dSWill Deacon vpci->dev_hdr = (struct device_header) { 38721ff329dSWill Deacon .bus_type = DEVICE_BUS_PCI, 38821ff329dSWill Deacon .data = &vpci->pci_hdr, 38921ff329dSWill Deacon }; 39021ff329dSWill Deacon 39136f5dc91SSasha Levin vpci->pci_hdr.msix.cap = PCI_CAP_ID_MSIX; 39236f5dc91SSasha Levin vpci->pci_hdr.msix.next = 0; 39314bba8a0SAsias He /* 39414bba8a0SAsias He * We at most have VIRTIO_PCI_MAX_VQ entries for virt queue, 39514bba8a0SAsias He * VIRTIO_PCI_MAX_CONFIG entries for config. 39614bba8a0SAsias He * 39714bba8a0SAsias He * To quote the PCI spec: 39814bba8a0SAsias He * 39914bba8a0SAsias He * System software reads this field to determine the 40014bba8a0SAsias He * MSI-X Table Size N, which is encoded as N-1. 40114bba8a0SAsias He * For example, a returned value of "00000000011" 40214bba8a0SAsias He * indicates a table size of 4. 40314bba8a0SAsias He */ 404aa73be70SMatt Evans vpci->pci_hdr.msix.ctrl = cpu_to_le16(VIRTIO_PCI_MAX_VQ + VIRTIO_PCI_MAX_CONFIG - 1); 40506f48103SSasha Levin 406a463650cSWill Deacon /* Both table and PBA are mapped to the same BAR (2) */ 407a463650cSWill Deacon vpci->pci_hdr.msix.table_offset = cpu_to_le32(2); 408a463650cSWill Deacon vpci->pci_hdr.msix.pba_offset = cpu_to_le32(2 | PCI_IO_SIZE); 40936f5dc91SSasha Levin vpci->config_vector = 0; 41036f5dc91SSasha Levin 41143c81c74SSasha Levin if (kvm__supports_extension(kvm, KVM_CAP_SIGNAL_MSI)) 41243c81c74SSasha Levin vpci->features |= VIRTIO_PCI_F_SIGNAL_MSI; 41343c81c74SSasha Levin 41421ff329dSWill Deacon r = device__register(&vpci->dev_hdr); 415495fbd4eSSasha Levin if (r < 0) 416a463650cSWill Deacon goto free_msix_mmio; 417495fbd4eSSasha Levin 418495fbd4eSSasha Levin return 0; 419495fbd4eSSasha Levin 420a463650cSWill Deacon free_msix_mmio: 421495fbd4eSSasha Levin kvm__deregister_mmio(kvm, vpci->msix_io_block); 422a463650cSWill Deacon free_mmio: 423a463650cSWill Deacon kvm__deregister_mmio(kvm, vpci->mmio_addr); 424495fbd4eSSasha Levin free_ioport: 425a463650cSWill Deacon ioport__unregister(kvm, vpci->port_addr); 426495fbd4eSSasha Levin return r; 427495fbd4eSSasha Levin } 428495fbd4eSSasha Levin 42902eca50cSAsias He int virtio_pci__exit(struct kvm *kvm, struct virtio_device *vdev) 430495fbd4eSSasha Levin { 43102eca50cSAsias He struct virtio_pci *vpci = vdev->virtio; 432495fbd4eSSasha Levin int i; 433495fbd4eSSasha Levin 434a463650cSWill Deacon kvm__deregister_mmio(kvm, vpci->mmio_addr); 435495fbd4eSSasha Levin kvm__deregister_mmio(kvm, vpci->msix_io_block); 436a463650cSWill Deacon ioport__unregister(kvm, vpci->port_addr); 437495fbd4eSSasha Levin 438a463650cSWill Deacon for (i = 0; i < VIRTIO_PCI_MAX_VQ; i++) { 439a463650cSWill Deacon ioeventfd__del_event(vpci->port_addr + VIRTIO_PCI_QUEUE_NOTIFY, i); 440a463650cSWill Deacon ioeventfd__del_event(vpci->mmio_addr + VIRTIO_PCI_QUEUE_NOTIFY, i); 441a463650cSWill Deacon } 44236f5dc91SSasha Levin 44336f5dc91SSasha Levin return 0; 44436f5dc91SSasha Levin } 445