178f33d2bSAlex Williamson /*
278f33d2bSAlex Williamson * vfio based device assignment support - PCI devices
378f33d2bSAlex Williamson *
478f33d2bSAlex Williamson * Copyright Red Hat, Inc. 2012-2015
578f33d2bSAlex Williamson *
678f33d2bSAlex Williamson * Authors:
778f33d2bSAlex Williamson * Alex Williamson <alex.williamson@redhat.com>
878f33d2bSAlex Williamson *
978f33d2bSAlex Williamson * This work is licensed under the terms of the GNU GPL, version 2. See
1078f33d2bSAlex Williamson * the COPYING file in the top-level directory.
1178f33d2bSAlex Williamson */
1278f33d2bSAlex Williamson #ifndef HW_VFIO_VFIO_PCI_H
1378f33d2bSAlex Williamson #define HW_VFIO_VFIO_PCI_H
1478f33d2bSAlex Williamson
1578f33d2bSAlex Williamson #include "exec/memory.h"
16edf5ca5dSMarkus Armbruster #include "hw/pci/pci_device.h"
1778f33d2bSAlex Williamson #include "hw/vfio/vfio-common.h"
1878f33d2bSAlex Williamson #include "qemu/event_notifier.h"
1978f33d2bSAlex Williamson #include "qemu/queue.h"
2078f33d2bSAlex Williamson #include "qemu/timer.h"
21db1015e9SEduardo Habkost #include "qom/object.h"
22dc580d51SLongpeng(Mike) #include "sysemu/kvm.h"
2378f33d2bSAlex Williamson
2489dcccc5SAlex Williamson #define PCI_ANY_ID (~0)
2589dcccc5SAlex Williamson
2678f33d2bSAlex Williamson struct VFIOPCIDevice;
2778f33d2bSAlex Williamson
28c958c51dSAlex Williamson typedef struct VFIOIOEventFD {
29c958c51dSAlex Williamson QLIST_ENTRY(VFIOIOEventFD) next;
30c958c51dSAlex Williamson MemoryRegion *mr;
31c958c51dSAlex Williamson hwaddr addr;
32c958c51dSAlex Williamson unsigned size;
33c958c51dSAlex Williamson uint64_t data;
34c958c51dSAlex Williamson EventNotifier e;
35c958c51dSAlex Williamson VFIORegion *region;
36c958c51dSAlex Williamson hwaddr region_addr;
37c958c51dSAlex Williamson bool dynamic; /* Added runtime, removed on device reset */
382b1dbd0dSAlex Williamson bool vfio;
39c958c51dSAlex Williamson } VFIOIOEventFD;
40c958c51dSAlex Williamson
418c4f2348SAlex Williamson typedef struct VFIOQuirk {
428c4f2348SAlex Williamson QLIST_ENTRY(VFIOQuirk) next;
438c4f2348SAlex Williamson void *data;
44c958c51dSAlex Williamson QLIST_HEAD(, VFIOIOEventFD) ioeventfds;
458c4f2348SAlex Williamson int nr_mem;
468c4f2348SAlex Williamson MemoryRegion *mem;
47469d02deSAlex Williamson void (*reset)(struct VFIOPCIDevice *vdev, struct VFIOQuirk *quirk);
4878f33d2bSAlex Williamson } VFIOQuirk;
4978f33d2bSAlex Williamson
5078f33d2bSAlex Williamson typedef struct VFIOBAR {
5178f33d2bSAlex Williamson VFIORegion region;
523a286732SAlex Williamson MemoryRegion *mr;
533a286732SAlex Williamson size_t size;
543a286732SAlex Williamson uint8_t type;
5578f33d2bSAlex Williamson bool ioport;
5678f33d2bSAlex Williamson bool mem64;
5778f33d2bSAlex Williamson QLIST_HEAD(, VFIOQuirk) quirks;
5878f33d2bSAlex Williamson } VFIOBAR;
5978f33d2bSAlex Williamson
6078f33d2bSAlex Williamson typedef struct VFIOVGARegion {
6178f33d2bSAlex Williamson MemoryRegion mem;
6278f33d2bSAlex Williamson off_t offset;
6378f33d2bSAlex Williamson int nr;
6478f33d2bSAlex Williamson QLIST_HEAD(, VFIOQuirk) quirks;
6578f33d2bSAlex Williamson } VFIOVGARegion;
6678f33d2bSAlex Williamson
6778f33d2bSAlex Williamson typedef struct VFIOVGA {
6878f33d2bSAlex Williamson off_t fd_offset;
6978f33d2bSAlex Williamson int fd;
7078f33d2bSAlex Williamson VFIOVGARegion region[QEMU_PCI_VGA_NUM_REGIONS];
7178f33d2bSAlex Williamson } VFIOVGA;
7278f33d2bSAlex Williamson
7378f33d2bSAlex Williamson typedef struct VFIOINTx {
7478f33d2bSAlex Williamson bool pending; /* interrupt pending */
7578f33d2bSAlex Williamson bool kvm_accel; /* set when QEMU bypass through KVM enabled */
7678f33d2bSAlex Williamson uint8_t pin; /* which pin to pull for qemu_set_irq */
7778f33d2bSAlex Williamson EventNotifier interrupt; /* eventfd triggered on interrupt */
7878f33d2bSAlex Williamson EventNotifier unmask; /* eventfd for unmask on QEMU bypass */
7978f33d2bSAlex Williamson PCIINTxRoute route; /* routing info for QEMU bypass */
8078f33d2bSAlex Williamson uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */
8178f33d2bSAlex Williamson QEMUTimer *mmap_timer; /* enable mmaps after periods w/o interrupts */
8278f33d2bSAlex Williamson } VFIOINTx;
8378f33d2bSAlex Williamson
8478f33d2bSAlex Williamson typedef struct VFIOMSIVector {
8578f33d2bSAlex Williamson /*
8678f33d2bSAlex Williamson * Two interrupt paths are configured per vector. The first, is only used
8778f33d2bSAlex Williamson * for interrupts injected via QEMU. This is typically the non-accel path,
8878f33d2bSAlex Williamson * but may also be used when we want QEMU to handle masking and pending
8978f33d2bSAlex Williamson * bits. The KVM path bypasses QEMU and is therefore higher performance,
9078f33d2bSAlex Williamson * but requires masking at the device. virq is used to track the MSI route
9178f33d2bSAlex Williamson * through KVM, thus kvm_interrupt is only available when virq is set to a
9278f33d2bSAlex Williamson * valid (>= 0) value.
9378f33d2bSAlex Williamson */
9478f33d2bSAlex Williamson EventNotifier interrupt;
9578f33d2bSAlex Williamson EventNotifier kvm_interrupt;
9678f33d2bSAlex Williamson struct VFIOPCIDevice *vdev; /* back pointer to device */
9778f33d2bSAlex Williamson int virq;
9878f33d2bSAlex Williamson bool use;
9978f33d2bSAlex Williamson } VFIOMSIVector;
10078f33d2bSAlex Williamson
10178f33d2bSAlex Williamson enum {
10278f33d2bSAlex Williamson VFIO_INT_NONE = 0,
10378f33d2bSAlex Williamson VFIO_INT_INTx = 1,
10478f33d2bSAlex Williamson VFIO_INT_MSI = 2,
10578f33d2bSAlex Williamson VFIO_INT_MSIX = 3,
10678f33d2bSAlex Williamson };
10778f33d2bSAlex Williamson
108edd09278SAlex Williamson /* Cache of MSI-X setup */
10978f33d2bSAlex Williamson typedef struct VFIOMSIXInfo {
11078f33d2bSAlex Williamson uint8_t table_bar;
11178f33d2bSAlex Williamson uint8_t pba_bar;
11278f33d2bSAlex Williamson uint16_t entries;
11378f33d2bSAlex Williamson uint32_t table_offset;
11478f33d2bSAlex Williamson uint32_t pba_offset;
11595239e16SAlex Williamson unsigned long *pending;
11645d85f62SJing Liu bool noresize;
11778f33d2bSAlex Williamson } VFIOMSIXInfo;
11878f33d2bSAlex Williamson
11942db0fb5SEduardo Habkost #define TYPE_VFIO_PCI "vfio-pci"
1208063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(VFIOPCIDevice, VFIO_PCI)
12142db0fb5SEduardo Habkost
122db1015e9SEduardo Habkost struct VFIOPCIDevice {
12378f33d2bSAlex Williamson PCIDevice pdev;
12478f33d2bSAlex Williamson VFIODevice vbasedev;
12578f33d2bSAlex Williamson VFIOINTx intx;
12678f33d2bSAlex Williamson unsigned int config_size;
12778f33d2bSAlex Williamson uint8_t *emulated_config_bits; /* QEMU emulated bits, little-endian */
12878f33d2bSAlex Williamson off_t config_offset; /* Offset of config space region within device fd */
12978f33d2bSAlex Williamson unsigned int rom_size;
13078f33d2bSAlex Williamson off_t rom_offset; /* Offset of ROM region within device fd */
13178f33d2bSAlex Williamson void *rom;
13278f33d2bSAlex Williamson int msi_cap_size;
13378f33d2bSAlex Williamson VFIOMSIVector *msi_vectors;
13478f33d2bSAlex Williamson VFIOMSIXInfo *msix;
13578f33d2bSAlex Williamson int nr_vectors; /* Number of MSI/MSIX vectors currently in use */
13678f33d2bSAlex Williamson int interrupt; /* Current interrupt type */
13778f33d2bSAlex Williamson VFIOBAR bars[PCI_NUM_REGIONS - 1]; /* No ROM */
1382d82f8a3SAlex Williamson VFIOVGA *vga; /* 0xa0000, 0x3b0, 0x3c0 */
139c4c45e94SAlex Williamson void *igd_opregion;
14078f33d2bSAlex Williamson PCIHostDeviceAddress host;
1412dca1b37SMinwoo Im QemuUUID vf_token;
14278f33d2bSAlex Williamson EventNotifier err_notifier;
14378f33d2bSAlex Williamson EventNotifier req_notifier;
14478f33d2bSAlex Williamson int (*resetfn)(struct VFIOPCIDevice *);
14589dcccc5SAlex Williamson uint32_t vendor_id;
14689dcccc5SAlex Williamson uint32_t device_id;
14789dcccc5SAlex Williamson uint32_t sub_vendor_id;
14889dcccc5SAlex Williamson uint32_t sub_device_id;
14978f33d2bSAlex Williamson uint32_t features;
15078f33d2bSAlex Williamson #define VFIO_FEATURE_ENABLE_VGA_BIT 0
15178f33d2bSAlex Williamson #define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT)
15278f33d2bSAlex Williamson #define VFIO_FEATURE_ENABLE_REQ_BIT 1
15378f33d2bSAlex Williamson #define VFIO_FEATURE_ENABLE_REQ (1 << VFIO_FEATURE_ENABLE_REQ_BIT)
1546ced0bbaSAlex Williamson #define VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT 2
1556ced0bbaSAlex Williamson #define VFIO_FEATURE_ENABLE_IGD_OPREGION \
1566ced0bbaSAlex Williamson (1 << VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT)
157a9994687SGerd Hoffmann OnOffAuto display;
158c62a0c7cSGerd Hoffmann uint32_t display_xres;
159c62a0c7cSGerd Hoffmann uint32_t display_yres;
16078f33d2bSAlex Williamson int32_t bootindex;
161c4c45e94SAlex Williamson uint32_t igd_gms;
16289d5202eSAlex Williamson OffAutoPCIBAR msix_relo;
16378f33d2bSAlex Williamson uint8_t pm_cap;
164dfbee78dSAlex Williamson uint8_t nv_gpudirect_clique;
16578f33d2bSAlex Williamson bool pci_aer;
16678f33d2bSAlex Williamson bool req_enabled;
16778f33d2bSAlex Williamson bool has_flr;
16878f33d2bSAlex Williamson bool has_pm_reset;
16978f33d2bSAlex Williamson bool rom_read_failed;
17078f33d2bSAlex Williamson bool no_kvm_intx;
17178f33d2bSAlex Williamson bool no_kvm_msi;
17278f33d2bSAlex Williamson bool no_kvm_msix;
173db32d0f4SAlex Williamson bool no_geforce_quirks;
174c958c51dSAlex Williamson bool no_kvm_ioeventfd;
1752b1dbd0dSAlex Williamson bool no_vfio_ioeventfd;
176b290659fSGerd Hoffmann bool enable_ramfb;
17787417811SMarc-André Lureau OnOffAuto ramfb_migrate;
178dc580d51SLongpeng(Mike) bool defer_kvm_irq_routing;
179c00aac6fSAlex Williamson bool clear_parent_atomics_on_exit;
180187716feSVinayak Kale bool skip_vsc_check;
18100195ba7SGerd Hoffmann VFIODisplay *dpy;
182c5478feaSDavid Gibson Notifier irqchip_change_notifier;
183db1015e9SEduardo Habkost };
18478f33d2bSAlex Williamson
18529d62771SThomas Huth /* Use uin32_t for vendor & device so PCI_ANY_ID expands and cannot match hw */
vfio_pci_is(VFIOPCIDevice * vdev,uint32_t vendor,uint32_t device)18629d62771SThomas Huth static inline bool vfio_pci_is(VFIOPCIDevice *vdev, uint32_t vendor, uint32_t device)
18729d62771SThomas Huth {
18829d62771SThomas Huth return (vendor == PCI_ANY_ID || vendor == vdev->vendor_id) &&
18929d62771SThomas Huth (device == PCI_ANY_ID || device == vdev->device_id);
19029d62771SThomas Huth }
19129d62771SThomas Huth
vfio_is_vga(VFIOPCIDevice * vdev)19229d62771SThomas Huth static inline bool vfio_is_vga(VFIOPCIDevice *vdev)
19329d62771SThomas Huth {
19429d62771SThomas Huth PCIDevice *pdev = &vdev->pdev;
19529d62771SThomas Huth uint16_t class = pci_get_word(pdev->config + PCI_CLASS_DEVICE);
19629d62771SThomas Huth
19729d62771SThomas Huth return class == PCI_CLASS_DISPLAY_VGA;
19829d62771SThomas Huth }
19929d62771SThomas Huth
200c00d61d8SAlex Williamson uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len);
201c00d61d8SAlex Williamson void vfio_pci_write_config(PCIDevice *pdev,
202c00d61d8SAlex Williamson uint32_t addr, uint32_t val, int len);
203c00d61d8SAlex Williamson
204c00d61d8SAlex Williamson uint64_t vfio_vga_read(void *opaque, hwaddr addr, unsigned size);
205c00d61d8SAlex Williamson void vfio_vga_write(void *opaque, hwaddr addr, uint64_t data, unsigned size);
206c00d61d8SAlex Williamson
2074eda914cSPhilippe Mathieu-Daudé bool vfio_opt_rom_in_denylist(VFIOPCIDevice *vdev);
208c00d61d8SAlex Williamson void vfio_vga_quirk_setup(VFIOPCIDevice *vdev);
2092d82f8a3SAlex Williamson void vfio_vga_quirk_exit(VFIOPCIDevice *vdev);
2102d82f8a3SAlex Williamson void vfio_vga_quirk_finalize(VFIOPCIDevice *vdev);
211c00d61d8SAlex Williamson void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr);
2122d82f8a3SAlex Williamson void vfio_bar_quirk_exit(VFIOPCIDevice *vdev, int nr);
2132d82f8a3SAlex Williamson void vfio_bar_quirk_finalize(VFIOPCIDevice *vdev, int nr);
214c9c50009SAlex Williamson void vfio_setup_resetfn_quirk(VFIOPCIDevice *vdev);
2150a0bda0aSZhenzhong Duan bool vfio_add_virt_caps(VFIOPCIDevice *vdev, Error **errp);
216469d02deSAlex Williamson void vfio_quirk_reset(VFIOPCIDevice *vdev);
21729d62771SThomas Huth VFIOQuirk *vfio_quirk_alloc(int nr_mem);
218*11b5ce95SCorvin Köhne void vfio_probe_igd_bar0_quirk(VFIOPCIDevice *vdev, int nr);
21929d62771SThomas Huth void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr);
220c00d61d8SAlex Williamson
221dfbee78dSAlex Williamson extern const PropertyInfo qdev_prop_nv_gpudirect_clique;
222dfbee78dSAlex Williamson
223c328e7e8SZhenzhong Duan void vfio_pci_pre_reset(VFIOPCIDevice *vdev);
224c328e7e8SZhenzhong Duan void vfio_pci_post_reset(VFIOPCIDevice *vdev);
225c328e7e8SZhenzhong Duan bool vfio_pci_host_match(PCIHostDeviceAddress *addr, const char *name);
2264d36ec23SZhenzhong Duan int vfio_pci_get_pci_hot_reset_info(VFIOPCIDevice *vdev,
2274d36ec23SZhenzhong Duan struct vfio_pci_hot_reset_info **info_p);
2284d36ec23SZhenzhong Duan
22964410a74SZhenzhong Duan bool vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp);
230e593c021SAlex Williamson
231d3c6a18bSZhenzhong Duan bool vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev,
2327237011dSEric Auger struct vfio_region_info *info,
2337237011dSEric Auger Error **errp);
2346ced0bbaSAlex Williamson
2358983e3e3STina Zhang void vfio_display_reset(VFIOPCIDevice *vdev);
236455c009dSZhenzhong Duan bool vfio_display_probe(VFIOPCIDevice *vdev, Error **errp);
237a9994687SGerd Hoffmann void vfio_display_finalize(VFIOPCIDevice *vdev);
238a9994687SGerd Hoffmann
23987417811SMarc-André Lureau extern const VMStateDescription vfio_display_vmstate;
24087417811SMarc-André Lureau
24178f33d2bSAlex Williamson #endif /* HW_VFIO_VFIO_PCI_H */
242