xref: /kvmtool/virtio/pci.c (revision 495fbd4e1f262a9d04cdb79e11818fa5d55b91a9)
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"
91c47ce69SSasha Levin #include "kvm/virtio-trans.h"
1036f5dc91SSasha Levin 
1136f5dc91SSasha Levin #include <linux/virtio_pci.h>
12aa73be70SMatt Evans #include <linux/byteorder.h>
1336f5dc91SSasha Levin #include <string.h>
1436f5dc91SSasha Levin 
151c47ce69SSasha Levin struct virtio_trans_ops *virtio_pci__get_trans_ops(void)
161c47ce69SSasha Levin {
171c47ce69SSasha Levin 	static struct virtio_trans_ops virtio_pci_trans = (struct virtio_trans_ops) {
181c47ce69SSasha Levin 		.signal_vq	= virtio_pci__signal_vq,
191c47ce69SSasha Levin 		.signal_config	= virtio_pci__signal_config,
201c47ce69SSasha Levin 		.init		= virtio_pci__init,
21*495fbd4eSSasha Levin 		.uninit		= virtio_pci__exit,
221c47ce69SSasha Levin 	};
231c47ce69SSasha Levin 	return &virtio_pci_trans;
241c47ce69SSasha Levin };
251c47ce69SSasha Levin 
261599d724SSasha Levin static void virtio_pci__ioevent_callback(struct kvm *kvm, void *param)
271599d724SSasha Levin {
281599d724SSasha Levin 	struct virtio_pci_ioevent_param *ioeventfd = param;
291c47ce69SSasha Levin 	struct virtio_pci *vpci = ioeventfd->vtrans->virtio;
301599d724SSasha Levin 
311c47ce69SSasha Levin 	ioeventfd->vtrans->virtio_ops->notify_vq(kvm, vpci->dev, ioeventfd->vq);
321599d724SSasha Levin }
331599d724SSasha Levin 
341c47ce69SSasha Levin static int virtio_pci__init_ioeventfd(struct kvm *kvm, struct virtio_trans *vtrans, u32 vq)
351599d724SSasha Levin {
361599d724SSasha Levin 	struct ioevent ioevent;
371c47ce69SSasha Levin 	struct virtio_pci *vpci = vtrans->virtio;
38ea6eeb1cSSasha Levin 	int r;
391599d724SSasha Levin 
401599d724SSasha Levin 	vpci->ioeventfds[vq] = (struct virtio_pci_ioevent_param) {
411c47ce69SSasha Levin 		.vtrans		= vtrans,
421599d724SSasha Levin 		.vq		= vq,
431599d724SSasha Levin 	};
441599d724SSasha Levin 
451599d724SSasha Levin 	ioevent = (struct ioevent) {
461599d724SSasha Levin 		.io_addr	= vpci->base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
471599d724SSasha Levin 		.io_len		= sizeof(u16),
481599d724SSasha Levin 		.fn		= virtio_pci__ioevent_callback,
491599d724SSasha Levin 		.fn_ptr		= &vpci->ioeventfds[vq],
501599d724SSasha Levin 		.datamatch	= vq,
511599d724SSasha Levin 		.fn_kvm		= kvm,
521599d724SSasha Levin 		.fd		= eventfd(0, 0),
531599d724SSasha Levin 	};
541599d724SSasha Levin 
55ea6eeb1cSSasha Levin 	r = ioeventfd__add_event(&ioevent);
56ea6eeb1cSSasha Levin 	if (r)
57ea6eeb1cSSasha Levin 		return r;
581599d724SSasha Levin 
59263b80e8SSasha Levin 	if (vtrans->virtio_ops->notify_vq_eventfd)
60263b80e8SSasha Levin 		vtrans->virtio_ops->notify_vq_eventfd(kvm, vpci->dev, vq, ioevent.fd);
61263b80e8SSasha Levin 
621599d724SSasha Levin 	return 0;
631599d724SSasha Levin }
641599d724SSasha Levin 
6506f48103SSasha Levin static inline bool virtio_pci__msix_enabled(struct virtio_pci *vpci)
6606f48103SSasha Levin {
67aa73be70SMatt Evans 	return vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_ENABLE);
6806f48103SSasha Levin }
6906f48103SSasha Levin 
701c47ce69SSasha Levin static bool virtio_pci__specific_io_in(struct kvm *kvm, struct virtio_trans *vtrans, u16 port,
7136f5dc91SSasha Levin 					void *data, int size, int offset)
7236f5dc91SSasha Levin {
7336f5dc91SSasha Levin 	u32 config_offset;
741c47ce69SSasha Levin 	struct virtio_pci *vpci = vtrans->virtio;
7506f48103SSasha Levin 	int type = virtio__get_dev_specific_field(offset - 20,
7606f48103SSasha Levin 							virtio_pci__msix_enabled(vpci),
771382aba0SSasha Levin 							&config_offset);
7836f5dc91SSasha Levin 	if (type == VIRTIO_PCI_O_MSIX) {
7936f5dc91SSasha Levin 		switch (offset) {
8036f5dc91SSasha Levin 		case VIRTIO_MSI_CONFIG_VECTOR:
8136f5dc91SSasha Levin 			ioport__write16(data, vpci->config_vector);
8236f5dc91SSasha Levin 			break;
8336f5dc91SSasha Levin 		case VIRTIO_MSI_QUEUE_VECTOR:
8436f5dc91SSasha Levin 			ioport__write16(data, vpci->vq_vector[vpci->queue_selector]);
8536f5dc91SSasha Levin 			break;
8636f5dc91SSasha Levin 		};
8736f5dc91SSasha Levin 
8836f5dc91SSasha Levin 		return true;
8936f5dc91SSasha Levin 	} else if (type == VIRTIO_PCI_O_CONFIG) {
9036f5dc91SSasha Levin 		u8 cfg;
9136f5dc91SSasha Levin 
921c47ce69SSasha Levin 		cfg = vtrans->virtio_ops->get_config(kvm, vpci->dev, config_offset);
9336f5dc91SSasha Levin 		ioport__write8(data, cfg);
9436f5dc91SSasha Levin 		return true;
9536f5dc91SSasha Levin 	}
9636f5dc91SSasha Levin 
9736f5dc91SSasha Levin 	return false;
9836f5dc91SSasha Levin }
9936f5dc91SSasha Levin 
10036f5dc91SSasha Levin static bool virtio_pci__io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
10136f5dc91SSasha Levin {
10236f5dc91SSasha Levin 	unsigned long offset;
10336f5dc91SSasha Levin 	bool ret = true;
1041c47ce69SSasha Levin 	struct virtio_trans *vtrans;
10536f5dc91SSasha Levin 	struct virtio_pci *vpci;
10636f5dc91SSasha Levin 	u32 val;
10736f5dc91SSasha Levin 
1081c47ce69SSasha Levin 	vtrans = ioport->priv;
1091c47ce69SSasha Levin 	vpci = vtrans->virtio;
11036f5dc91SSasha Levin 	offset = port - vpci->base_addr;
11136f5dc91SSasha Levin 
11236f5dc91SSasha Levin 	switch (offset) {
11336f5dc91SSasha Levin 	case VIRTIO_PCI_HOST_FEATURES:
1141c47ce69SSasha Levin 		val = vtrans->virtio_ops->get_host_features(kvm, vpci->dev);
11536f5dc91SSasha Levin 		ioport__write32(data, val);
11636f5dc91SSasha Levin 		break;
11736f5dc91SSasha Levin 	case VIRTIO_PCI_QUEUE_PFN:
1181c47ce69SSasha Levin 		val = vtrans->virtio_ops->get_pfn_vq(kvm, vpci->dev, vpci->queue_selector);
11936f5dc91SSasha Levin 		ioport__write32(data, val);
12036f5dc91SSasha Levin 		break;
12136f5dc91SSasha Levin 	case VIRTIO_PCI_QUEUE_NUM:
1221c47ce69SSasha Levin 		val = vtrans->virtio_ops->get_size_vq(kvm, vpci->dev, vpci->queue_selector);
123657ee18bSMatt Evans 		ioport__write16(data, val);
12436f5dc91SSasha Levin 		break;
12536f5dc91SSasha Levin 	case VIRTIO_PCI_STATUS:
12636f5dc91SSasha Levin 		ioport__write8(data, vpci->status);
12736f5dc91SSasha Levin 		break;
12836f5dc91SSasha Levin 	case VIRTIO_PCI_ISR:
12936f5dc91SSasha Levin 		ioport__write8(data, vpci->isr);
13036f5dc91SSasha Levin 		kvm__irq_line(kvm, vpci->pci_hdr.irq_line, VIRTIO_IRQ_LOW);
13136f5dc91SSasha Levin 		vpci->isr = VIRTIO_IRQ_LOW;
13236f5dc91SSasha Levin 		break;
13336f5dc91SSasha Levin 	default:
1341c47ce69SSasha Levin 		ret = virtio_pci__specific_io_in(kvm, vtrans, port, data, size, offset);
13536f5dc91SSasha Levin 		break;
13636f5dc91SSasha Levin 	};
13736f5dc91SSasha Levin 
13836f5dc91SSasha Levin 	return ret;
13936f5dc91SSasha Levin }
14036f5dc91SSasha Levin 
1411c47ce69SSasha Levin static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_trans *vtrans, u16 port,
14236f5dc91SSasha Levin 					void *data, int size, int offset)
14336f5dc91SSasha Levin {
1441c47ce69SSasha Levin 	struct virtio_pci *vpci = vtrans->virtio;
14536f5dc91SSasha Levin 	u32 config_offset, gsi, vec;
14606f48103SSasha Levin 	int type = virtio__get_dev_specific_field(offset - 20, virtio_pci__msix_enabled(vpci),
1471382aba0SSasha Levin 							&config_offset);
14836f5dc91SSasha Levin 	if (type == VIRTIO_PCI_O_MSIX) {
14936f5dc91SSasha Levin 		switch (offset) {
15036f5dc91SSasha Levin 		case VIRTIO_MSI_CONFIG_VECTOR:
15136f5dc91SSasha Levin 			vec = vpci->config_vector = ioport__read16(data);
15236f5dc91SSasha Levin 
1531de74957SSasha Levin 			gsi = irq__add_msix_route(kvm, &vpci->msix_table[vec].msg);
15436f5dc91SSasha Levin 
15536f5dc91SSasha Levin 			vpci->config_gsi = gsi;
15636f5dc91SSasha Levin 			break;
1573a60be06SSasha Levin 		case VIRTIO_MSI_QUEUE_VECTOR:
15836f5dc91SSasha Levin 			vec = vpci->vq_vector[vpci->queue_selector] = ioport__read16(data);
15936f5dc91SSasha Levin 
1601de74957SSasha Levin 			gsi = irq__add_msix_route(kvm, &vpci->msix_table[vec].msg);
16136f5dc91SSasha Levin 			vpci->gsis[vpci->queue_selector] = gsi;
162263b80e8SSasha Levin 			if (vtrans->virtio_ops->notify_vq_gsi)
163263b80e8SSasha Levin 				vtrans->virtio_ops->notify_vq_gsi(kvm, vpci->dev,
164263b80e8SSasha Levin 							vpci->queue_selector, gsi);
16536f5dc91SSasha Levin 			break;
16636f5dc91SSasha Levin 		};
16736f5dc91SSasha Levin 
16836f5dc91SSasha Levin 		return true;
16936f5dc91SSasha Levin 	} else if (type == VIRTIO_PCI_O_CONFIG) {
1701c47ce69SSasha Levin 		vtrans->virtio_ops->set_config(kvm, vpci->dev, *(u8 *)data, config_offset);
17136f5dc91SSasha Levin 
17236f5dc91SSasha Levin 		return true;
17336f5dc91SSasha Levin 	}
17436f5dc91SSasha Levin 
17536f5dc91SSasha Levin 	return false;
17636f5dc91SSasha Levin }
17736f5dc91SSasha Levin 
17836f5dc91SSasha Levin static bool virtio_pci__io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
17936f5dc91SSasha Levin {
18036f5dc91SSasha Levin 	unsigned long offset;
18136f5dc91SSasha Levin 	bool ret = true;
1821c47ce69SSasha Levin 	struct virtio_trans *vtrans;
18336f5dc91SSasha Levin 	struct virtio_pci *vpci;
18436f5dc91SSasha Levin 	u32 val;
18536f5dc91SSasha Levin 
1861c47ce69SSasha Levin 	vtrans = ioport->priv;
1871c47ce69SSasha Levin 	vpci = vtrans->virtio;
18836f5dc91SSasha Levin 	offset = port - vpci->base_addr;
18936f5dc91SSasha Levin 
19036f5dc91SSasha Levin 	switch (offset) {
19136f5dc91SSasha Levin 	case VIRTIO_PCI_GUEST_FEATURES:
19236f5dc91SSasha Levin 		val = ioport__read32(data);
19313f9a438SSasha Levin 		vtrans->virtio_ops->set_guest_features(kvm, vpci->dev, val);
19436f5dc91SSasha Levin 		break;
19536f5dc91SSasha Levin 	case VIRTIO_PCI_QUEUE_PFN:
19636f5dc91SSasha Levin 		val = ioport__read32(data);
1971c47ce69SSasha Levin 		virtio_pci__init_ioeventfd(kvm, vtrans, vpci->queue_selector);
1981c47ce69SSasha Levin 		vtrans->virtio_ops->init_vq(kvm, vpci->dev, vpci->queue_selector, val);
19936f5dc91SSasha Levin 		break;
20036f5dc91SSasha Levin 	case VIRTIO_PCI_QUEUE_SEL:
20136f5dc91SSasha Levin 		vpci->queue_selector = ioport__read16(data);
20236f5dc91SSasha Levin 		break;
20336f5dc91SSasha Levin 	case VIRTIO_PCI_QUEUE_NOTIFY:
20436f5dc91SSasha Levin 		val = ioport__read16(data);
2051c47ce69SSasha Levin 		vtrans->virtio_ops->notify_vq(kvm, vpci->dev, val);
20636f5dc91SSasha Levin 		break;
20736f5dc91SSasha Levin 	case VIRTIO_PCI_STATUS:
20836f5dc91SSasha Levin 		vpci->status = ioport__read8(data);
20936f5dc91SSasha Levin 		break;
21036f5dc91SSasha Levin 	default:
2111c47ce69SSasha Levin 		ret = virtio_pci__specific_io_out(kvm, vtrans, port, data, size, offset);
21236f5dc91SSasha Levin 		break;
21336f5dc91SSasha Levin 	};
21436f5dc91SSasha Levin 
21536f5dc91SSasha Levin 	return ret;
21636f5dc91SSasha Levin }
21736f5dc91SSasha Levin 
21836f5dc91SSasha Levin static struct ioport_operations virtio_pci__io_ops = {
21936f5dc91SSasha Levin 	.io_in	= virtio_pci__io_in,
22036f5dc91SSasha Levin 	.io_out	= virtio_pci__io_out,
22136f5dc91SSasha Levin };
22236f5dc91SSasha Levin 
22306f48103SSasha Levin static void callback_mmio_table(u64 addr, u8 *data, u32 len, u8 is_write, void *ptr)
22436f5dc91SSasha Levin {
22536f5dc91SSasha Levin 	struct virtio_pci *vpci = ptr;
2269c26dab4SSasha Levin 	void *table;
2279c26dab4SSasha Levin 	u32 offset;
22836f5dc91SSasha Levin 
2299c26dab4SSasha Levin 	if (addr > vpci->msix_io_block + PCI_IO_SIZE) {
2309c26dab4SSasha Levin 		table	= &vpci->msix_pba;
2319c26dab4SSasha Levin 		offset	= vpci->msix_io_block + PCI_IO_SIZE;
2329c26dab4SSasha Levin 	} else {
2339c26dab4SSasha Levin 		table	= &vpci->msix_table;
2349c26dab4SSasha Levin 		offset	= vpci->msix_io_block;
23536f5dc91SSasha Levin 	}
23636f5dc91SSasha Levin 
23706f48103SSasha Levin 	if (is_write)
2389c26dab4SSasha Levin 		memcpy(table + addr - offset, data, len);
23906f48103SSasha Levin 	else
2409c26dab4SSasha Levin 		memcpy(data, table + addr - offset, len);
24106f48103SSasha Levin }
24206f48103SSasha Levin 
2431c47ce69SSasha Levin int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_trans *vtrans, u32 vq)
24436f5dc91SSasha Levin {
2451c47ce69SSasha Levin 	struct virtio_pci *vpci = vtrans->virtio;
24606f48103SSasha Levin 	int tbl = vpci->vq_vector[vq];
24736f5dc91SSasha Levin 
24806f48103SSasha Levin 	if (virtio_pci__msix_enabled(vpci)) {
249aa73be70SMatt Evans 		if (vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_MASKALL) ||
250aa73be70SMatt Evans 		    vpci->msix_table[tbl].ctrl & cpu_to_le16(PCI_MSIX_ENTRY_CTRL_MASKBIT)) {
25106f48103SSasha Levin 
25206f48103SSasha Levin 			vpci->msix_pba |= 1 << tbl;
25306f48103SSasha Levin 			return 0;
25406f48103SSasha Levin 		}
25506f48103SSasha Levin 
25606f48103SSasha Levin 		kvm__irq_trigger(kvm, vpci->gsis[vq]);
25706f48103SSasha Levin 	} else {
258a36eca7bSSasha Levin 		vpci->isr = VIRTIO_IRQ_HIGH;
25906f48103SSasha Levin 		kvm__irq_trigger(kvm, vpci->pci_hdr.irq_line);
26006f48103SSasha Levin 	}
26136f5dc91SSasha Levin 	return 0;
26236f5dc91SSasha Levin }
26336f5dc91SSasha Levin 
2641c47ce69SSasha Levin int virtio_pci__signal_config(struct kvm *kvm, struct virtio_trans *vtrans)
26536f5dc91SSasha Levin {
2661c47ce69SSasha Levin 	struct virtio_pci *vpci = vtrans->virtio;
26706f48103SSasha Levin 	int tbl = vpci->config_vector;
26806f48103SSasha Levin 
26906f48103SSasha Levin 	if (virtio_pci__msix_enabled(vpci)) {
270aa73be70SMatt Evans 		if (vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_MASKALL) ||
271aa73be70SMatt Evans 		    vpci->msix_table[tbl].ctrl & cpu_to_le16(PCI_MSIX_ENTRY_CTRL_MASKBIT)) {
27206f48103SSasha Levin 
27306f48103SSasha Levin 			vpci->msix_pba |= 1 << tbl;
27406f48103SSasha Levin 			return 0;
27506f48103SSasha Levin 		}
27606f48103SSasha Levin 
27706f48103SSasha Levin 		kvm__irq_trigger(kvm, vpci->config_gsi);
27806f48103SSasha Levin 	} else {
27906f48103SSasha Levin 		vpci->isr = VIRTIO_PCI_ISR_CONFIG;
28006f48103SSasha Levin 		kvm__irq_trigger(kvm, vpci->pci_hdr.irq_line);
28106f48103SSasha Levin 	}
28236f5dc91SSasha Levin 
28336f5dc91SSasha Levin 	return 0;
28436f5dc91SSasha Levin }
28536f5dc91SSasha Levin 
2861c47ce69SSasha Levin int virtio_pci__init(struct kvm *kvm, struct virtio_trans *vtrans, void *dev,
287507e02d8SAsias He 			int device_id, int subsys_id, int class)
28836f5dc91SSasha Levin {
2891c47ce69SSasha Levin 	struct virtio_pci *vpci = vtrans->virtio;
29036f5dc91SSasha Levin 	u8 pin, line, ndev;
2917af40b91SSasha Levin 	int r;
29236f5dc91SSasha Levin 
29336f5dc91SSasha Levin 	vpci->dev = dev;
2949c26dab4SSasha Levin 	vpci->msix_io_block = pci_get_io_space_block(PCI_IO_SIZE * 2);
29536f5dc91SSasha Levin 
2967af40b91SSasha Levin 	r = ioport__register(IOPORT_EMPTY, &virtio_pci__io_ops, IOPORT_SIZE, vtrans);
2977af40b91SSasha Levin 	if (r < 0)
2987af40b91SSasha Levin 		return r;
2997af40b91SSasha Levin 
3007af40b91SSasha Levin 	vpci->base_addr = (u16)r;
301*495fbd4eSSasha Levin 	r = kvm__register_mmio(kvm, vpci->msix_io_block, PCI_IO_SIZE, false, callback_mmio_table, vpci);
302*495fbd4eSSasha Levin 	if (r < 0)
303*495fbd4eSSasha Levin 		goto free_ioport;
30436f5dc91SSasha Levin 
30536f5dc91SSasha Levin 	vpci->pci_hdr = (struct pci_device_header) {
306aa73be70SMatt Evans 		.vendor_id		= cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
307aa73be70SMatt Evans 		.device_id		= cpu_to_le16(device_id),
30836f5dc91SSasha Levin 		.header_type		= PCI_HEADER_TYPE_NORMAL,
30936f5dc91SSasha Levin 		.revision_id		= 0,
310aa73be70SMatt Evans 		.class[0]		= class & 0xff,
311aa73be70SMatt Evans 		.class[1]		= (class >> 8) & 0xff,
312aa73be70SMatt Evans 		.class[2]		= (class >> 16) & 0xff,
313aa73be70SMatt Evans 		.subsys_vendor_id	= cpu_to_le16(PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET),
314aa73be70SMatt Evans 		.subsys_id		= cpu_to_le16(subsys_id),
3159c26dab4SSasha Levin 		.bar[0]			= cpu_to_le32(vpci->base_addr
3169c26dab4SSasha Levin 							| PCI_BASE_ADDRESS_SPACE_IO),
317b4dab816SSasha Levin 		.bar[1]			= cpu_to_le32(vpci->msix_io_block
318b4dab816SSasha Levin 							| PCI_BASE_ADDRESS_SPACE_MEMORY),
319aa73be70SMatt Evans 		.status			= cpu_to_le16(PCI_STATUS_CAP_LIST),
32036f5dc91SSasha Levin 		.capabilities		= (void *)&vpci->pci_hdr.msix - (void *)&vpci->pci_hdr,
3216b868987SMatt Evans 		.bar_size[0]		= IOPORT_SIZE,
3226b868987SMatt Evans 		.bar_size[1]		= PCI_IO_SIZE,
3236b868987SMatt Evans 		.bar_size[3]		= PCI_IO_SIZE,
32436f5dc91SSasha Levin 	};
32536f5dc91SSasha Levin 
32636f5dc91SSasha Levin 	vpci->pci_hdr.msix.cap = PCI_CAP_ID_MSIX;
32736f5dc91SSasha Levin 	vpci->pci_hdr.msix.next = 0;
32814bba8a0SAsias He 	/*
32914bba8a0SAsias He 	 * We at most have VIRTIO_PCI_MAX_VQ entries for virt queue,
33014bba8a0SAsias He 	 * VIRTIO_PCI_MAX_CONFIG entries for config.
33114bba8a0SAsias He 	 *
33214bba8a0SAsias He 	 * To quote the PCI spec:
33314bba8a0SAsias He 	 *
33414bba8a0SAsias He 	 * System software reads this field to determine the
33514bba8a0SAsias He 	 * MSI-X Table Size N, which is encoded as N-1.
33614bba8a0SAsias He 	 * For example, a returned value of "00000000011"
33714bba8a0SAsias He 	 * indicates a table size of 4.
33814bba8a0SAsias He 	 */
339aa73be70SMatt Evans 	vpci->pci_hdr.msix.ctrl = cpu_to_le16(VIRTIO_PCI_MAX_VQ + VIRTIO_PCI_MAX_CONFIG - 1);
34006f48103SSasha Levin 
34106f48103SSasha Levin 	/*
34206f48103SSasha Levin 	 * Both table and PBA could be mapped on the same BAR, but for now
34306f48103SSasha Levin 	 * we're not in short of BARs
34406f48103SSasha Levin 	 */
345aa73be70SMatt Evans 	vpci->pci_hdr.msix.table_offset = cpu_to_le32(1); /* Use BAR 1 */
3469c26dab4SSasha Levin 	vpci->pci_hdr.msix.pba_offset = cpu_to_le32(1 | PCI_IO_SIZE); /* Use BAR 3 */
34736f5dc91SSasha Levin 	vpci->config_vector = 0;
34836f5dc91SSasha Levin 
349*495fbd4eSSasha Levin 	r = irq__register_device(subsys_id, &ndev, &pin, &line);
350*495fbd4eSSasha Levin 	if (r < 0)
351*495fbd4eSSasha Levin 		goto free_mmio;
35236f5dc91SSasha Levin 
35336f5dc91SSasha Levin 	vpci->pci_hdr.irq_pin	= pin;
35436f5dc91SSasha Levin 	vpci->pci_hdr.irq_line	= line;
355*495fbd4eSSasha Levin 	r = pci__register(&vpci->pci_hdr, ndev);
356*495fbd4eSSasha Levin 	if (r < 0)
357*495fbd4eSSasha Levin 		goto free_ioport;
358*495fbd4eSSasha Levin 
359*495fbd4eSSasha Levin 	return 0;
360*495fbd4eSSasha Levin 
361*495fbd4eSSasha Levin free_mmio:
362*495fbd4eSSasha Levin 	kvm__deregister_mmio(kvm, vpci->msix_io_block);
363*495fbd4eSSasha Levin free_ioport:
364*495fbd4eSSasha Levin 	ioport__unregister(vpci->base_addr);
365*495fbd4eSSasha Levin 	return r;
366*495fbd4eSSasha Levin }
367*495fbd4eSSasha Levin 
368*495fbd4eSSasha Levin int virtio_pci__exit(struct kvm *kvm, struct virtio_trans *vtrans)
369*495fbd4eSSasha Levin {
370*495fbd4eSSasha Levin 	struct virtio_pci *vpci = vtrans->virtio;
371*495fbd4eSSasha Levin 	int i;
372*495fbd4eSSasha Levin 
373*495fbd4eSSasha Levin 	kvm__deregister_mmio(kvm, vpci->msix_io_block);
374*495fbd4eSSasha Levin 	ioport__unregister(vpci->base_addr);
375*495fbd4eSSasha Levin 
376*495fbd4eSSasha Levin 	for (i = 0; i < VIRTIO_PCI_MAX_VQ; i++)
377*495fbd4eSSasha Levin 		ioeventfd__del_event(vpci->base_addr + VIRTIO_PCI_QUEUE_NOTIFY, i);
37836f5dc91SSasha Levin 
37936f5dc91SSasha Levin 	return 0;
38036f5dc91SSasha Levin }