xref: /kvmtool/include/kvm/virtio-pci.h (revision b0d56e3c994a0feb3ffb519cecda5c1f6da8b1ab)
136f5dc91SSasha Levin #ifndef KVM__VIRTIO_PCI_H
236f5dc91SSasha Levin #define KVM__VIRTIO_PCI_H
336f5dc91SSasha Levin 
421ff329dSWill Deacon #include "kvm/devices.h"
536f5dc91SSasha Levin #include "kvm/pci.h"
6*b0d56e3cSJean-Philippe Brucker #include "kvm/virtio.h"
736f5dc91SSasha Levin 
8930876d5SJean-Philippe Brucker #include <stdbool.h>
9930876d5SJean-Philippe Brucker #include <linux/byteorder.h>
1036f5dc91SSasha Levin #include <linux/types.h>
1136f5dc91SSasha Levin 
1245d3b59eSSasha Levin #define VIRTIO_PCI_MAX_VQ	32
1314bba8a0SAsias He #define VIRTIO_PCI_MAX_CONFIG	1
1436f5dc91SSasha Levin 
1536f5dc91SSasha Levin struct kvm;
16930876d5SJean-Philippe Brucker struct kvm_cpu;
1736f5dc91SSasha Levin 
181599d724SSasha Levin struct virtio_pci_ioevent_param {
1902eca50cSAsias He 	struct virtio_device	*vdev;
201599d724SSasha Levin 	u32			vq;
211599d724SSasha Levin };
221599d724SSasha Levin 
2343c81c74SSasha Levin #define VIRTIO_PCI_F_SIGNAL_MSI (1 << 0)
2443c81c74SSasha Levin 
25930876d5SJean-Philippe Brucker #define ALIGN_UP(x, s)		ALIGN((x) + (s) - 1, (s))
26930876d5SJean-Philippe Brucker #define VIRTIO_NR_MSIX		(VIRTIO_PCI_MAX_VQ + VIRTIO_PCI_MAX_CONFIG)
27930876d5SJean-Philippe Brucker #define VIRTIO_MSIX_TABLE_SIZE	(VIRTIO_NR_MSIX * 16)
28930876d5SJean-Philippe Brucker #define VIRTIO_MSIX_PBA_SIZE	(ALIGN_UP(VIRTIO_MSIX_TABLE_SIZE, 64) / 8)
29930876d5SJean-Philippe Brucker #define VIRTIO_MSIX_BAR_SIZE	(1UL << fls_long(VIRTIO_MSIX_TABLE_SIZE + \
30930876d5SJean-Philippe Brucker 						 VIRTIO_MSIX_PBA_SIZE))
31930876d5SJean-Philippe Brucker 
3236f5dc91SSasha Levin struct virtio_pci {
3336f5dc91SSasha Levin 	struct pci_device_header pci_hdr;
3421ff329dSWill Deacon 	struct device_header	dev_hdr;
3536f5dc91SSasha Levin 	void			*dev;
36a463650cSWill Deacon 	struct kvm		*kvm;
3736f5dc91SSasha Levin 
3821c9bc74SJean-Philippe Brucker 	u32			doorbell_offset;
3936f5dc91SSasha Levin 	u8			status;
4036f5dc91SSasha Levin 	u8			isr;
41*b0d56e3cSJean-Philippe Brucker 	u32			device_features_sel;
42*b0d56e3cSJean-Philippe Brucker 	u32			driver_features_sel;
4343c81c74SSasha Levin 	u32			features;
4436f5dc91SSasha Levin 
45e9922aafSAndre Przywara 	/*
46e9922aafSAndre Przywara 	 * We cannot rely on the INTERRUPT_LINE byte in the config space once
47e9922aafSAndre Przywara 	 * we have run guest code, as the OS is allowed to use that field
48e9922aafSAndre Przywara 	 * as a scratch pad to communicate between driver and PCI layer.
49e9922aafSAndre Przywara 	 * So store our legacy interrupt line number in here for internal use.
50e9922aafSAndre Przywara 	 */
51e9922aafSAndre Przywara 	u8			legacy_irq_line;
52e9922aafSAndre Przywara 
5336f5dc91SSasha Levin 	/* MSI-X */
5436f5dc91SSasha Levin 	u16			config_vector;
5536f5dc91SSasha Levin 	u32			config_gsi;
5636f5dc91SSasha Levin 	u32			vq_vector[VIRTIO_PCI_MAX_VQ];
5736f5dc91SSasha Levin 	u32			gsis[VIRTIO_PCI_MAX_VQ];
5806f48103SSasha Levin 	u64			msix_pba;
5914bba8a0SAsias He 	struct msix_table	msix_table[VIRTIO_PCI_MAX_VQ + VIRTIO_PCI_MAX_CONFIG];
6036f5dc91SSasha Levin 
6136f5dc91SSasha Levin 	/* virtio queue */
6236f5dc91SSasha Levin 	u16			queue_selector;
631599d724SSasha Levin 	struct virtio_pci_ioevent_param ioeventfds[VIRTIO_PCI_MAX_VQ];
6436f5dc91SSasha Levin };
6536f5dc91SSasha Levin 
6602eca50cSAsias He int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_device *vdev, u32 vq);
6702eca50cSAsias He int virtio_pci__signal_config(struct kvm *kvm, struct virtio_device *vdev);
6802eca50cSAsias He int virtio_pci__exit(struct kvm *kvm, struct virtio_device *vdev);
69eb34a8c2SJean-Philippe Brucker int virtio_pci__reset(struct kvm *kvm, struct virtio_device *vdev);
7002eca50cSAsias He int virtio_pci__init(struct kvm *kvm, void *dev, struct virtio_device *vdev,
71507e02d8SAsias He 		     int device_id, int subsys_id, int class);
72*b0d56e3cSJean-Philippe Brucker int virtio_pci_modern_init(struct virtio_device *vdev);
7336f5dc91SSasha Levin 
74930876d5SJean-Philippe Brucker static inline bool virtio_pci__msix_enabled(struct virtio_pci *vpci)
75930876d5SJean-Philippe Brucker {
76930876d5SJean-Philippe Brucker 	return vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_ENABLE);
77930876d5SJean-Philippe Brucker }
78930876d5SJean-Philippe Brucker 
79930876d5SJean-Philippe Brucker static inline u16 virtio_pci__port_addr(struct virtio_pci *vpci)
80930876d5SJean-Philippe Brucker {
81930876d5SJean-Philippe Brucker 	return pci__bar_address(&vpci->pci_hdr, 0);
82930876d5SJean-Philippe Brucker }
83930876d5SJean-Philippe Brucker 
84930876d5SJean-Philippe Brucker static inline u32 virtio_pci__mmio_addr(struct virtio_pci *vpci)
85930876d5SJean-Philippe Brucker {
86930876d5SJean-Philippe Brucker 	return pci__bar_address(&vpci->pci_hdr, 1);
87930876d5SJean-Philippe Brucker }
88930876d5SJean-Philippe Brucker 
89930876d5SJean-Philippe Brucker static inline u32 virtio_pci__msix_io_addr(struct virtio_pci *vpci)
90930876d5SJean-Philippe Brucker {
91930876d5SJean-Philippe Brucker 	return pci__bar_address(&vpci->pci_hdr, 2);
92930876d5SJean-Philippe Brucker }
93930876d5SJean-Philippe Brucker 
94930876d5SJean-Philippe Brucker int virtio_pci__add_msix_route(struct virtio_pci *vpci, u32 vec);
95930876d5SJean-Philippe Brucker int virtio_pci__init_ioeventfd(struct kvm *kvm, struct virtio_device *vdev,
96930876d5SJean-Philippe Brucker 			       u32 vq);
97930876d5SJean-Philippe Brucker int virtio_pci_init_vq(struct kvm *kvm, struct virtio_device *vdev, int vq);
98930876d5SJean-Philippe Brucker void virtio_pci_exit_vq(struct kvm *kvm, struct virtio_device *vdev, int vq);
99930876d5SJean-Philippe Brucker 
100930876d5SJean-Philippe Brucker void virtio_pci_legacy__io_mmio_callback(struct kvm_cpu *vcpu, u64 addr, u8 *data,
101930876d5SJean-Philippe Brucker 				  u32 len, u8 is_write, void *ptr);
102*b0d56e3cSJean-Philippe Brucker void virtio_pci_modern__io_mmio_callback(struct kvm_cpu *vcpu, u64 addr, u8 *data,
103*b0d56e3cSJean-Philippe Brucker 					 u32 len, u8 is_write, void *ptr);
104930876d5SJean-Philippe Brucker 
10536f5dc91SSasha Levin #endif
106