121ff329dSWill Deacon #include "kvm/devices.h" 260273720SAsias He #include "kvm/virtio-mmio.h" 360273720SAsias He #include "kvm/ioeventfd.h" 460273720SAsias He #include "kvm/virtio.h" 560273720SAsias He #include "kvm/kvm.h" 660273720SAsias He #include "kvm/irq.h" 72454c7dcSWill Deacon #include "kvm/fdt.h" 860273720SAsias He 960273720SAsias He #include <linux/virtio_mmio.h> 1060273720SAsias He #include <string.h> 1160273720SAsias He 1260273720SAsias He static u32 virtio_mmio_io_space_blocks = KVM_VIRTIO_MMIO_AREA; 1360273720SAsias He 1460273720SAsias He static u32 virtio_mmio_get_io_space_block(u32 size) 1560273720SAsias He { 1660273720SAsias He u32 block = virtio_mmio_io_space_blocks; 1760273720SAsias He virtio_mmio_io_space_blocks += size; 1860273720SAsias He 1960273720SAsias He return block; 2060273720SAsias He } 2160273720SAsias He 2260273720SAsias He static void virtio_mmio_ioevent_callback(struct kvm *kvm, void *param) 2360273720SAsias He { 2460273720SAsias He struct virtio_mmio_ioevent_param *ioeventfd = param; 2560273720SAsias He struct virtio_mmio *vmmio = ioeventfd->vdev->virtio; 2660273720SAsias He 2760273720SAsias He ioeventfd->vdev->ops->notify_vq(kvm, vmmio->dev, ioeventfd->vq); 2860273720SAsias He } 2960273720SAsias He 30*22a08236SJean-Philippe Brucker int virtio_mmio_init_ioeventfd(struct kvm *kvm, struct virtio_device *vdev, 31*22a08236SJean-Philippe Brucker u32 vq) 3260273720SAsias He { 3360273720SAsias He struct virtio_mmio *vmmio = vdev->virtio; 3460273720SAsias He struct ioevent ioevent; 3560273720SAsias He int err; 3660273720SAsias He 3760273720SAsias He vmmio->ioeventfds[vq] = (struct virtio_mmio_ioevent_param) { 3860273720SAsias He .vdev = vdev, 3960273720SAsias He .vq = vq, 4060273720SAsias He }; 4160273720SAsias He 4260273720SAsias He ioevent = (struct ioevent) { 4360273720SAsias He .io_addr = vmmio->addr + VIRTIO_MMIO_QUEUE_NOTIFY, 4460273720SAsias He .io_len = sizeof(u32), 4560273720SAsias He .fn = virtio_mmio_ioevent_callback, 4660273720SAsias He .fn_ptr = &vmmio->ioeventfds[vq], 4760273720SAsias He .datamatch = vq, 4860273720SAsias He .fn_kvm = kvm, 4960273720SAsias He .fd = eventfd(0, 0), 5060273720SAsias He }; 5160273720SAsias He 52627d6874SAsias He if (vdev->use_vhost) 53627d6874SAsias He /* 54627d6874SAsias He * Vhost will poll the eventfd in host kernel side, 55627d6874SAsias He * no need to poll in userspace. 56627d6874SAsias He */ 5727347f76SWill Deacon err = ioeventfd__add_event(&ioevent, 0); 58627d6874SAsias He else 59627d6874SAsias He /* Need to poll in userspace. */ 6027347f76SWill Deacon err = ioeventfd__add_event(&ioevent, IOEVENTFD_FLAG_USER_POLL); 6160273720SAsias He if (err) 6260273720SAsias He return err; 6360273720SAsias He 6460273720SAsias He if (vdev->ops->notify_vq_eventfd) 6560273720SAsias He vdev->ops->notify_vq_eventfd(kvm, vmmio->dev, vq, ioevent.fd); 6660273720SAsias He 6760273720SAsias He return 0; 6860273720SAsias He } 6960273720SAsias He 7060273720SAsias He int virtio_mmio_signal_vq(struct kvm *kvm, struct virtio_device *vdev, u32 vq) 7160273720SAsias He { 7260273720SAsias He struct virtio_mmio *vmmio = vdev->virtio; 7360273720SAsias He 7460273720SAsias He vmmio->hdr.interrupt_state |= VIRTIO_MMIO_INT_VRING; 7560273720SAsias He kvm__irq_trigger(vmmio->kvm, vmmio->irq); 7660273720SAsias He 7760273720SAsias He return 0; 7860273720SAsias He } 7960273720SAsias He 80*22a08236SJean-Philippe Brucker int virtio_mmio_init_vq(struct kvm *kvm, struct virtio_device *vdev, int vq) 81d0607293SJean-Philippe Brucker { 82d0607293SJean-Philippe Brucker int ret; 83d0607293SJean-Philippe Brucker struct virtio_mmio *vmmio = vdev->virtio; 84d0607293SJean-Philippe Brucker 85d0607293SJean-Philippe Brucker ret = virtio_mmio_init_ioeventfd(vmmio->kvm, vdev, vq); 86d0607293SJean-Philippe Brucker if (ret) { 87d0607293SJean-Philippe Brucker pr_err("couldn't add ioeventfd for vq %d: %d", vq, ret); 88d0607293SJean-Philippe Brucker return ret; 89d0607293SJean-Philippe Brucker } 90d0607293SJean-Philippe Brucker return vdev->ops->init_vq(vmmio->kvm, vmmio->dev, vq); 91d0607293SJean-Philippe Brucker } 92d0607293SJean-Philippe Brucker 93*22a08236SJean-Philippe Brucker void virtio_mmio_exit_vq(struct kvm *kvm, struct virtio_device *vdev, int vq) 94ad346c2eSJean-Philippe Brucker { 95ad346c2eSJean-Philippe Brucker struct virtio_mmio *vmmio = vdev->virtio; 96ad346c2eSJean-Philippe Brucker 97ad346c2eSJean-Philippe Brucker ioeventfd__del_event(vmmio->addr + VIRTIO_MMIO_QUEUE_NOTIFY, vq); 98ad346c2eSJean-Philippe Brucker virtio_exit_vq(kvm, vdev, vmmio->dev, vq); 99ad346c2eSJean-Philippe Brucker } 100ad346c2eSJean-Philippe Brucker 10160273720SAsias He int virtio_mmio_signal_config(struct kvm *kvm, struct virtio_device *vdev) 10260273720SAsias He { 10360273720SAsias He struct virtio_mmio *vmmio = vdev->virtio; 10460273720SAsias He 10560273720SAsias He vmmio->hdr.interrupt_state |= VIRTIO_MMIO_INT_CONFIG; 10660273720SAsias He kvm__irq_trigger(vmmio->kvm, vmmio->irq); 10760273720SAsias He 10860273720SAsias He return 0; 10960273720SAsias He } 11060273720SAsias He 1112454c7dcSWill Deacon #ifdef CONFIG_HAS_LIBFDT 1122454c7dcSWill Deacon #define DEVICE_NAME_MAX_LEN 32 1132bfd9ac3SAndre Przywara static 1142bfd9ac3SAndre Przywara void generate_virtio_mmio_fdt_node(void *fdt, 1152454c7dcSWill Deacon struct device_header *dev_hdr, 1162454c7dcSWill Deacon void (*generate_irq_prop)(void *fdt, 1172bfd9ac3SAndre Przywara u8 irq, 1182bfd9ac3SAndre Przywara enum irq_type)) 1192454c7dcSWill Deacon { 1202454c7dcSWill Deacon char dev_name[DEVICE_NAME_MAX_LEN]; 1212454c7dcSWill Deacon struct virtio_mmio *vmmio = container_of(dev_hdr, 1222454c7dcSWill Deacon struct virtio_mmio, 1232454c7dcSWill Deacon dev_hdr); 1242454c7dcSWill Deacon u64 addr = vmmio->addr; 1252454c7dcSWill Deacon u64 reg_prop[] = { 1262454c7dcSWill Deacon cpu_to_fdt64(addr), 1272454c7dcSWill Deacon cpu_to_fdt64(VIRTIO_MMIO_IO_SIZE), 1282454c7dcSWill Deacon }; 1292454c7dcSWill Deacon 1302454c7dcSWill Deacon snprintf(dev_name, DEVICE_NAME_MAX_LEN, "virtio@%llx", addr); 1312454c7dcSWill Deacon 1322454c7dcSWill Deacon _FDT(fdt_begin_node(fdt, dev_name)); 1332454c7dcSWill Deacon _FDT(fdt_property_string(fdt, "compatible", "virtio,mmio")); 1342454c7dcSWill Deacon _FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop))); 1359a8af7e3SRobin Murphy _FDT(fdt_property(fdt, "dma-coherent", NULL, 0)); 1362bfd9ac3SAndre Przywara generate_irq_prop(fdt, vmmio->irq, IRQ_TYPE_EDGE_RISING); 1372454c7dcSWill Deacon _FDT(fdt_end_node(fdt)); 1382454c7dcSWill Deacon } 1392454c7dcSWill Deacon #else 1402454c7dcSWill Deacon static void generate_virtio_mmio_fdt_node(void *fdt, 1412454c7dcSWill Deacon struct device_header *dev_hdr, 1422454c7dcSWill Deacon void (*generate_irq_prop)(void *fdt, 1432454c7dcSWill Deacon u8 irq)) 1442454c7dcSWill Deacon { 1452454c7dcSWill Deacon die("Unable to generate device tree nodes without libfdt\n"); 1462454c7dcSWill Deacon } 1472454c7dcSWill Deacon #endif 1482454c7dcSWill Deacon 14960273720SAsias He int virtio_mmio_init(struct kvm *kvm, void *dev, struct virtio_device *vdev, 15060273720SAsias He int device_id, int subsys_id, int class) 15160273720SAsias He { 15260273720SAsias He struct virtio_mmio *vmmio = vdev->virtio; 1538f160708SAlexandru Elisei int r; 15460273720SAsias He 15560273720SAsias He vmmio->addr = virtio_mmio_get_io_space_block(VIRTIO_MMIO_IO_SIZE); 15660273720SAsias He vmmio->kvm = kvm; 15760273720SAsias He vmmio->dev = dev; 15860273720SAsias He 1598f160708SAlexandru Elisei r = kvm__register_mmio(kvm, vmmio->addr, VIRTIO_MMIO_IO_SIZE, 160*22a08236SJean-Philippe Brucker false, virtio_mmio_legacy_callback, vdev); 1618f160708SAlexandru Elisei if (r < 0) 1628f160708SAlexandru Elisei return r; 16360273720SAsias He 16460273720SAsias He vmmio->hdr = (struct virtio_mmio_hdr) { 16560273720SAsias He .magic = {'v', 'i', 'r', 't'}, 16660273720SAsias He .version = 1, 167449d5eb3SWill Deacon .device_id = subsys_id, 16860273720SAsias He .vendor_id = 0x4d564b4c , /* 'LKVM' */ 16960273720SAsias He .queue_num_max = 256, 17060273720SAsias He }; 17160273720SAsias He 17221ff329dSWill Deacon vmmio->dev_hdr = (struct device_header) { 17321ff329dSWill Deacon .bus_type = DEVICE_BUS_MMIO, 1742454c7dcSWill Deacon .data = generate_virtio_mmio_fdt_node, 17521ff329dSWill Deacon }; 17621ff329dSWill Deacon 177af731be3SAndre Przywara vmmio->irq = irq__alloc_line(); 178af731be3SAndre Przywara 1798f160708SAlexandru Elisei r = device__register(&vmmio->dev_hdr); 1808f160708SAlexandru Elisei if (r < 0) { 1818f160708SAlexandru Elisei kvm__deregister_mmio(kvm, vmmio->addr); 1828f160708SAlexandru Elisei return r; 1838f160708SAlexandru Elisei } 18460273720SAsias He 18560273720SAsias He /* 18660273720SAsias He * Instantiate guest virtio-mmio devices using kernel command line 18760273720SAsias He * (or module) parameter, e.g 18860273720SAsias He * 18960273720SAsias He * virtio_mmio.devices=0x200@0xd2000000:5,0x200@0xd2000200:6 19060273720SAsias He */ 191e1c7c62aSAndre Przywara pr_debug("virtio-mmio.devices=0x%x@0x%x:%d", VIRTIO_MMIO_IO_SIZE, 192e1c7c62aSAndre Przywara vmmio->addr, vmmio->irq); 19360273720SAsias He 19460273720SAsias He return 0; 19560273720SAsias He } 19660273720SAsias He 197eb34a8c2SJean-Philippe Brucker int virtio_mmio_reset(struct kvm *kvm, struct virtio_device *vdev) 198eb34a8c2SJean-Philippe Brucker { 19931e0eaccSMartin Radev unsigned int vq; 200eb34a8c2SJean-Philippe Brucker struct virtio_mmio *vmmio = vdev->virtio; 201eb34a8c2SJean-Philippe Brucker 202eb34a8c2SJean-Philippe Brucker for (vq = 0; vq < vdev->ops->get_vq_count(kvm, vmmio->dev); vq++) 203eb34a8c2SJean-Philippe Brucker virtio_mmio_exit_vq(kvm, vdev, vq); 204eb34a8c2SJean-Philippe Brucker 205eb34a8c2SJean-Philippe Brucker return 0; 206eb34a8c2SJean-Philippe Brucker } 207eb34a8c2SJean-Philippe Brucker 20860273720SAsias He int virtio_mmio_exit(struct kvm *kvm, struct virtio_device *vdev) 20960273720SAsias He { 21060273720SAsias He struct virtio_mmio *vmmio = vdev->virtio; 21160273720SAsias He 212eb34a8c2SJean-Philippe Brucker virtio_mmio_reset(kvm, vdev); 21360273720SAsias He kvm__deregister_mmio(kvm, vmmio->addr); 21460273720SAsias He 21560273720SAsias He return 0; 21660273720SAsias He } 217