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