1 #include "kvm/virtio-pci.h" 2 3 #include "kvm/ioport.h" 4 #include "kvm/kvm.h" 5 #include "kvm/virtio-pci-dev.h" 6 #include "kvm/irq.h" 7 #include "kvm/virtio.h" 8 #include "kvm/ioeventfd.h" 9 10 #include <linux/virtio_pci.h> 11 #include <string.h> 12 13 static void virtio_pci__ioevent_callback(struct kvm *kvm, void *param) 14 { 15 struct virtio_pci_ioevent_param *ioeventfd = param; 16 17 ioeventfd->vpci->ops.notify_vq(kvm, ioeventfd->vpci->dev, ioeventfd->vq); 18 } 19 20 static int virtio_pci__init_ioeventfd(struct kvm *kvm, struct virtio_pci *vpci, u32 vq) 21 { 22 struct ioevent ioevent; 23 24 vpci->ioeventfds[vq] = (struct virtio_pci_ioevent_param) { 25 .vpci = vpci, 26 .vq = vq, 27 }; 28 29 ioevent = (struct ioevent) { 30 .io_addr = vpci->base_addr + VIRTIO_PCI_QUEUE_NOTIFY, 31 .io_len = sizeof(u16), 32 .fn = virtio_pci__ioevent_callback, 33 .fn_ptr = &vpci->ioeventfds[vq], 34 .datamatch = vq, 35 .fn_kvm = kvm, 36 .fd = eventfd(0, 0), 37 }; 38 39 ioeventfd__add_event(&ioevent); 40 41 return 0; 42 } 43 44 static bool virtio_pci__specific_io_in(struct kvm *kvm, struct virtio_pci *vpci, u16 port, 45 void *data, int size, int offset) 46 { 47 u32 config_offset; 48 int type = virtio__get_dev_specific_field(offset - 20, vpci->msix_enabled, 49 0, &config_offset); 50 if (type == VIRTIO_PCI_O_MSIX) { 51 switch (offset) { 52 case VIRTIO_MSI_CONFIG_VECTOR: 53 ioport__write16(data, vpci->config_vector); 54 break; 55 case VIRTIO_MSI_QUEUE_VECTOR: 56 ioport__write16(data, vpci->vq_vector[vpci->queue_selector]); 57 break; 58 }; 59 60 return true; 61 } else if (type == VIRTIO_PCI_O_CONFIG) { 62 u8 cfg; 63 64 cfg = vpci->ops.get_config(kvm, vpci->dev, config_offset); 65 ioport__write8(data, cfg); 66 return true; 67 } 68 69 return false; 70 } 71 72 static bool virtio_pci__io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 73 { 74 unsigned long offset; 75 bool ret = true; 76 struct virtio_pci *vpci; 77 u32 val; 78 79 vpci = ioport->priv; 80 offset = port - vpci->base_addr; 81 82 switch (offset) { 83 case VIRTIO_PCI_HOST_FEATURES: 84 val = vpci->ops.get_host_features(kvm, vpci->dev); 85 ioport__write32(data, val); 86 break; 87 case VIRTIO_PCI_QUEUE_PFN: 88 val = vpci->ops.get_pfn_vq(kvm, vpci->dev, vpci->queue_selector); 89 ioport__write32(data, val); 90 break; 91 case VIRTIO_PCI_QUEUE_NUM: 92 val = vpci->ops.get_size_vq(kvm, vpci->dev, vpci->queue_selector); 93 ioport__write32(data, val); 94 break; 95 break; 96 case VIRTIO_PCI_STATUS: 97 ioport__write8(data, vpci->status); 98 break; 99 case VIRTIO_PCI_ISR: 100 ioport__write8(data, vpci->isr); 101 kvm__irq_line(kvm, vpci->pci_hdr.irq_line, VIRTIO_IRQ_LOW); 102 vpci->isr = VIRTIO_IRQ_LOW; 103 break; 104 default: 105 ret = virtio_pci__specific_io_in(kvm, vpci, port, data, size, offset); 106 break; 107 }; 108 109 return ret; 110 } 111 112 static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_pci *vpci, u16 port, 113 void *data, int size, int offset) 114 { 115 u32 config_offset, gsi, vec; 116 int type = virtio__get_dev_specific_field(offset - 20, vpci->msix_enabled, 117 0, &config_offset); 118 if (type == VIRTIO_PCI_O_MSIX) { 119 switch (offset) { 120 case VIRTIO_MSI_CONFIG_VECTOR: 121 vec = vpci->config_vector = ioport__read16(data); 122 123 gsi = irq__add_msix_route(kvm, 124 vpci->pci_hdr.msix.table[vec].low, 125 vpci->pci_hdr.msix.table[vec].high, 126 vpci->pci_hdr.msix.table[vec].data); 127 128 vpci->config_gsi = gsi; 129 break; 130 case VIRTIO_MSI_QUEUE_VECTOR: { 131 vec = vpci->vq_vector[vpci->queue_selector] = ioport__read16(data); 132 133 gsi = irq__add_msix_route(kvm, 134 vpci->pci_hdr.msix.table[vec].low, 135 vpci->pci_hdr.msix.table[vec].high, 136 vpci->pci_hdr.msix.table[vec].data); 137 vpci->gsis[vpci->queue_selector] = gsi; 138 break; 139 } 140 }; 141 142 return true; 143 } else if (type == VIRTIO_PCI_O_CONFIG) { 144 vpci->ops.set_config(kvm, vpci->dev, *(u8 *)data, config_offset); 145 146 return true; 147 } 148 149 return false; 150 } 151 152 static bool virtio_pci__io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 153 { 154 unsigned long offset; 155 bool ret = true; 156 struct virtio_pci *vpci; 157 u32 val; 158 159 vpci = ioport->priv; 160 offset = port - vpci->base_addr; 161 162 switch (offset) { 163 case VIRTIO_PCI_GUEST_FEATURES: 164 val = ioport__read32(data); 165 vpci->ops.set_guest_features(kvm, vpci, val); 166 break; 167 case VIRTIO_PCI_QUEUE_PFN: 168 val = ioport__read32(data); 169 virtio_pci__init_ioeventfd(kvm, vpci, vpci->queue_selector); 170 vpci->ops.init_vq(kvm, vpci->dev, vpci->queue_selector, val); 171 break; 172 case VIRTIO_PCI_QUEUE_SEL: 173 vpci->queue_selector = ioport__read16(data); 174 break; 175 case VIRTIO_PCI_QUEUE_NOTIFY: 176 val = ioport__read16(data); 177 vpci->ops.notify_vq(kvm, vpci->dev, val); 178 break; 179 case VIRTIO_PCI_STATUS: 180 vpci->status = ioport__read8(data); 181 break; 182 default: 183 ret = virtio_pci__specific_io_out(kvm, vpci, port, data, size, offset); 184 break; 185 }; 186 187 return ret; 188 } 189 190 static struct ioport_operations virtio_pci__io_ops = { 191 .io_in = virtio_pci__io_in, 192 .io_out = virtio_pci__io_out, 193 }; 194 195 static void callback_mmio(u64 addr, u8 *data, u32 len, u8 is_write, void *ptr) 196 { 197 struct virtio_pci *vpci = ptr; 198 void *table = &vpci->pci_hdr.msix.table; 199 200 vpci->msix_enabled = 1; 201 if (is_write) 202 memcpy(table + addr - vpci->msix_io_block, data, len); 203 else 204 memcpy(data, table + addr - vpci->msix_io_block, len); 205 } 206 207 int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_pci *vpci, u32 vq) 208 { 209 kvm__irq_line(kvm, vpci->gsis[vq], VIRTIO_IRQ_HIGH); 210 211 return 0; 212 } 213 214 int virtio_pci__signal_config(struct kvm *kvm, struct virtio_pci *vpci) 215 { 216 kvm__irq_line(kvm, vpci->config_gsi, VIRTIO_IRQ_HIGH); 217 218 return 0; 219 } 220 221 int virtio_pci__init(struct kvm *kvm, struct virtio_pci *vpci, void *dev, 222 int device_id, int subsys_id) 223 { 224 u8 pin, line, ndev; 225 226 vpci->dev = dev; 227 vpci->msix_io_block = pci_get_io_space_block(); 228 229 vpci->base_addr = ioport__register(IOPORT_EMPTY, &virtio_pci__io_ops, IOPORT_SIZE, vpci); 230 kvm__register_mmio(kvm, vpci->msix_io_block, 0x100, callback_mmio, vpci); 231 232 vpci->pci_hdr = (struct pci_device_header) { 233 .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET, 234 .device_id = device_id, 235 .header_type = PCI_HEADER_TYPE_NORMAL, 236 .revision_id = 0, 237 .class = 0x010000, 238 .subsys_vendor_id = PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET, 239 .subsys_id = subsys_id, 240 .bar[0] = vpci->base_addr | PCI_BASE_ADDRESS_SPACE_IO, 241 .bar[1] = vpci->msix_io_block | 242 PCI_BASE_ADDRESS_SPACE_MEMORY | 243 PCI_BASE_ADDRESS_MEM_TYPE_64, 244 /* bar[2] is the continuation of bar[1] for 64bit addressing */ 245 .bar[2] = 0, 246 .status = PCI_STATUS_CAP_LIST, 247 .capabilities = (void *)&vpci->pci_hdr.msix - (void *)&vpci->pci_hdr, 248 }; 249 250 vpci->pci_hdr.msix.cap = PCI_CAP_ID_MSIX; 251 vpci->pci_hdr.msix.next = 0; 252 vpci->pci_hdr.msix.table_size = (VIRTIO_PCI_MAX_VQ + 1) | PCI_MSIX_FLAGS_ENABLE; 253 vpci->pci_hdr.msix.table_offset = 1; /* Use BAR 1 */ 254 vpci->config_vector = 0; 255 256 if (irq__register_device(VIRTIO_ID_RNG, &ndev, &pin, &line) < 0) 257 return -1; 258 259 vpci->pci_hdr.irq_pin = pin; 260 vpci->pci_hdr.irq_line = line; 261 pci__register(&vpci->pci_hdr, ndev); 262 263 return 0; 264 } 265