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"
6b0d56e3cSJean-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
23930876d5SJean-Philippe Brucker #define ALIGN_UP(x, s) ALIGN((x) + (s) - 1, (s))
24930876d5SJean-Philippe Brucker #define VIRTIO_NR_MSIX (VIRTIO_PCI_MAX_VQ + VIRTIO_PCI_MAX_CONFIG)
25930876d5SJean-Philippe Brucker #define VIRTIO_MSIX_TABLE_SIZE (VIRTIO_NR_MSIX * 16)
26930876d5SJean-Philippe Brucker #define VIRTIO_MSIX_PBA_SIZE (ALIGN_UP(VIRTIO_MSIX_TABLE_SIZE, 64) / 8)
27930876d5SJean-Philippe Brucker #define VIRTIO_MSIX_BAR_SIZE (1UL << fls_long(VIRTIO_MSIX_TABLE_SIZE + \
28930876d5SJean-Philippe Brucker VIRTIO_MSIX_PBA_SIZE))
29930876d5SJean-Philippe Brucker
3036f5dc91SSasha Levin struct virtio_pci {
3136f5dc91SSasha Levin struct pci_device_header pci_hdr;
3221ff329dSWill Deacon struct device_header dev_hdr;
3336f5dc91SSasha Levin void *dev;
34a463650cSWill Deacon struct kvm *kvm;
3536f5dc91SSasha Levin
3621c9bc74SJean-Philippe Brucker u32 doorbell_offset;
37*c86ef0b8SJean-Philippe Brucker bool signal_msi;
3836f5dc91SSasha Levin u8 status;
3936f5dc91SSasha Levin u8 isr;
40b0d56e3cSJean-Philippe Brucker u32 device_features_sel;
41b0d56e3cSJean-Philippe Brucker u32 driver_features_sel;
4236f5dc91SSasha Levin
43e9922aafSAndre Przywara /*
44e9922aafSAndre Przywara * We cannot rely on the INTERRUPT_LINE byte in the config space once
45e9922aafSAndre Przywara * we have run guest code, as the OS is allowed to use that field
46e9922aafSAndre Przywara * as a scratch pad to communicate between driver and PCI layer.
47e9922aafSAndre Przywara * So store our legacy interrupt line number in here for internal use.
48e9922aafSAndre Przywara */
49e9922aafSAndre Przywara u8 legacy_irq_line;
50e9922aafSAndre Przywara
5136f5dc91SSasha Levin /* MSI-X */
5236f5dc91SSasha Levin u16 config_vector;
5336f5dc91SSasha Levin u32 config_gsi;
543d5cefc2SJean-Philippe Brucker u16 vq_vector[VIRTIO_PCI_MAX_VQ];
5536f5dc91SSasha Levin u32 gsis[VIRTIO_PCI_MAX_VQ];
5606f48103SSasha Levin u64 msix_pba;
5714bba8a0SAsias He struct msix_table msix_table[VIRTIO_PCI_MAX_VQ + VIRTIO_PCI_MAX_CONFIG];
5836f5dc91SSasha Levin
5936f5dc91SSasha Levin /* virtio queue */
6036f5dc91SSasha Levin u16 queue_selector;
611599d724SSasha Levin struct virtio_pci_ioevent_param ioeventfds[VIRTIO_PCI_MAX_VQ];
6236f5dc91SSasha Levin };
6336f5dc91SSasha Levin
6402eca50cSAsias He int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_device *vdev, u32 vq);
6502eca50cSAsias He int virtio_pci__signal_config(struct kvm *kvm, struct virtio_device *vdev);
6602eca50cSAsias He int virtio_pci__exit(struct kvm *kvm, struct virtio_device *vdev);
67eb34a8c2SJean-Philippe Brucker int virtio_pci__reset(struct kvm *kvm, struct virtio_device *vdev);
6802eca50cSAsias He int virtio_pci__init(struct kvm *kvm, void *dev, struct virtio_device *vdev,
69507e02d8SAsias He int device_id, int subsys_id, int class);
70b0d56e3cSJean-Philippe Brucker int virtio_pci_modern_init(struct virtio_device *vdev);
7136f5dc91SSasha Levin
virtio_pci__msix_enabled(struct virtio_pci * vpci)72930876d5SJean-Philippe Brucker static inline bool virtio_pci__msix_enabled(struct virtio_pci *vpci)
73930876d5SJean-Philippe Brucker {
74930876d5SJean-Philippe Brucker return vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_ENABLE);
75930876d5SJean-Philippe Brucker }
76930876d5SJean-Philippe Brucker
virtio_pci__port_addr(struct virtio_pci * vpci)77930876d5SJean-Philippe Brucker static inline u16 virtio_pci__port_addr(struct virtio_pci *vpci)
78930876d5SJean-Philippe Brucker {
79930876d5SJean-Philippe Brucker return pci__bar_address(&vpci->pci_hdr, 0);
80930876d5SJean-Philippe Brucker }
81930876d5SJean-Philippe Brucker
virtio_pci__mmio_addr(struct virtio_pci * vpci)82930876d5SJean-Philippe Brucker static inline u32 virtio_pci__mmio_addr(struct virtio_pci *vpci)
83930876d5SJean-Philippe Brucker {
84930876d5SJean-Philippe Brucker return pci__bar_address(&vpci->pci_hdr, 1);
85930876d5SJean-Philippe Brucker }
86930876d5SJean-Philippe Brucker
virtio_pci__msix_io_addr(struct virtio_pci * vpci)87930876d5SJean-Philippe Brucker static inline u32 virtio_pci__msix_io_addr(struct virtio_pci *vpci)
88930876d5SJean-Philippe Brucker {
89930876d5SJean-Philippe Brucker return pci__bar_address(&vpci->pci_hdr, 2);
90930876d5SJean-Philippe Brucker }
91930876d5SJean-Philippe Brucker
92930876d5SJean-Philippe Brucker int virtio_pci__add_msix_route(struct virtio_pci *vpci, u32 vec);
93930876d5SJean-Philippe Brucker int virtio_pci__init_ioeventfd(struct kvm *kvm, struct virtio_device *vdev,
94930876d5SJean-Philippe Brucker u32 vq);
95930876d5SJean-Philippe Brucker int virtio_pci_init_vq(struct kvm *kvm, struct virtio_device *vdev, int vq);
96930876d5SJean-Philippe Brucker void virtio_pci_exit_vq(struct kvm *kvm, struct virtio_device *vdev, int vq);
97930876d5SJean-Philippe Brucker
98930876d5SJean-Philippe Brucker void virtio_pci_legacy__io_mmio_callback(struct kvm_cpu *vcpu, u64 addr, u8 *data,
99930876d5SJean-Philippe Brucker u32 len, u8 is_write, void *ptr);
100b0d56e3cSJean-Philippe Brucker void virtio_pci_modern__io_mmio_callback(struct kvm_cpu *vcpu, u64 addr, u8 *data,
101b0d56e3cSJean-Philippe Brucker u32 len, u8 is_write, void *ptr);
102930876d5SJean-Philippe Brucker
10336f5dc91SSasha Levin #endif
104