]>
Commit | Line | Data |
---|---|---|
78f33d2b AW |
1 | /* |
2 | * vfio based device assignment support - PCI devices | |
3 | * | |
4 | * Copyright Red Hat, Inc. 2012-2015 | |
5 | * | |
6 | * Authors: | |
7 | * Alex Williamson <alex.williamson@redhat.com> | |
8 | * | |
9 | * This work is licensed under the terms of the GNU GPL, version 2. See | |
10 | * the COPYING file in the top-level directory. | |
11 | */ | |
12 | #ifndef HW_VFIO_VFIO_PCI_H | |
13 | #define HW_VFIO_VFIO_PCI_H | |
14 | ||
78f33d2b AW |
15 | #include "exec/memory.h" |
16 | #include "hw/pci/pci.h" | |
17 | #include "hw/vfio/vfio-common.h" | |
18 | #include "qemu/event_notifier.h" | |
19 | #include "qemu/queue.h" | |
20 | #include "qemu/timer.h" | |
db1015e9 | 21 | #include "qom/object.h" |
dc580d51 | 22 | #include "sysemu/kvm.h" |
78f33d2b | 23 | |
89dcccc5 AW |
24 | #define PCI_ANY_ID (~0) |
25 | ||
78f33d2b AW |
26 | struct VFIOPCIDevice; |
27 | ||
c958c51d AW |
28 | typedef struct VFIOIOEventFD { |
29 | QLIST_ENTRY(VFIOIOEventFD) next; | |
30 | MemoryRegion *mr; | |
31 | hwaddr addr; | |
32 | unsigned size; | |
33 | uint64_t data; | |
34 | EventNotifier e; | |
35 | VFIORegion *region; | |
36 | hwaddr region_addr; | |
37 | bool dynamic; /* Added runtime, removed on device reset */ | |
2b1dbd0d | 38 | bool vfio; |
c958c51d AW |
39 | } VFIOIOEventFD; |
40 | ||
8c4f2348 AW |
41 | typedef struct VFIOQuirk { |
42 | QLIST_ENTRY(VFIOQuirk) next; | |
43 | void *data; | |
c958c51d | 44 | QLIST_HEAD(, VFIOIOEventFD) ioeventfds; |
8c4f2348 AW |
45 | int nr_mem; |
46 | MemoryRegion *mem; | |
469d02de | 47 | void (*reset)(struct VFIOPCIDevice *vdev, struct VFIOQuirk *quirk); |
78f33d2b AW |
48 | } VFIOQuirk; |
49 | ||
50 | typedef struct VFIOBAR { | |
51 | VFIORegion region; | |
3a286732 AW |
52 | MemoryRegion *mr; |
53 | size_t size; | |
54 | uint8_t type; | |
78f33d2b AW |
55 | bool ioport; |
56 | bool mem64; | |
57 | QLIST_HEAD(, VFIOQuirk) quirks; | |
58 | } VFIOBAR; | |
59 | ||
60 | typedef struct VFIOVGARegion { | |
61 | MemoryRegion mem; | |
62 | off_t offset; | |
63 | int nr; | |
64 | QLIST_HEAD(, VFIOQuirk) quirks; | |
65 | } VFIOVGARegion; | |
66 | ||
67 | typedef struct VFIOVGA { | |
68 | off_t fd_offset; | |
69 | int fd; | |
70 | VFIOVGARegion region[QEMU_PCI_VGA_NUM_REGIONS]; | |
71 | } VFIOVGA; | |
72 | ||
73 | typedef struct VFIOINTx { | |
74 | bool pending; /* interrupt pending */ | |
75 | bool kvm_accel; /* set when QEMU bypass through KVM enabled */ | |
76 | uint8_t pin; /* which pin to pull for qemu_set_irq */ | |
77 | EventNotifier interrupt; /* eventfd triggered on interrupt */ | |
78 | EventNotifier unmask; /* eventfd for unmask on QEMU bypass */ | |
79 | PCIINTxRoute route; /* routing info for QEMU bypass */ | |
80 | uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */ | |
81 | QEMUTimer *mmap_timer; /* enable mmaps after periods w/o interrupts */ | |
82 | } VFIOINTx; | |
83 | ||
84 | typedef struct VFIOMSIVector { | |
85 | /* | |
86 | * Two interrupt paths are configured per vector. The first, is only used | |
87 | * for interrupts injected via QEMU. This is typically the non-accel path, | |
88 | * but may also be used when we want QEMU to handle masking and pending | |
89 | * bits. The KVM path bypasses QEMU and is therefore higher performance, | |
90 | * but requires masking at the device. virq is used to track the MSI route | |
91 | * through KVM, thus kvm_interrupt is only available when virq is set to a | |
92 | * valid (>= 0) value. | |
93 | */ | |
94 | EventNotifier interrupt; | |
95 | EventNotifier kvm_interrupt; | |
96 | struct VFIOPCIDevice *vdev; /* back pointer to device */ | |
97 | int virq; | |
98 | bool use; | |
99 | } VFIOMSIVector; | |
100 | ||
101 | enum { | |
102 | VFIO_INT_NONE = 0, | |
103 | VFIO_INT_INTx = 1, | |
104 | VFIO_INT_MSI = 2, | |
105 | VFIO_INT_MSIX = 3, | |
106 | }; | |
107 | ||
edd09278 | 108 | /* Cache of MSI-X setup */ |
78f33d2b AW |
109 | typedef struct VFIOMSIXInfo { |
110 | uint8_t table_bar; | |
111 | uint8_t pba_bar; | |
112 | uint16_t entries; | |
113 | uint32_t table_offset; | |
114 | uint32_t pba_offset; | |
95239e16 | 115 | unsigned long *pending; |
78f33d2b AW |
116 | } VFIOMSIXInfo; |
117 | ||
42db0fb5 | 118 | #define TYPE_VFIO_PCI "vfio-pci" |
8063396b | 119 | OBJECT_DECLARE_SIMPLE_TYPE(VFIOPCIDevice, VFIO_PCI) |
42db0fb5 | 120 | |
db1015e9 | 121 | struct VFIOPCIDevice { |
78f33d2b AW |
122 | PCIDevice pdev; |
123 | VFIODevice vbasedev; | |
124 | VFIOINTx intx; | |
125 | unsigned int config_size; | |
126 | uint8_t *emulated_config_bits; /* QEMU emulated bits, little-endian */ | |
127 | off_t config_offset; /* Offset of config space region within device fd */ | |
128 | unsigned int rom_size; | |
129 | off_t rom_offset; /* Offset of ROM region within device fd */ | |
130 | void *rom; | |
131 | int msi_cap_size; | |
132 | VFIOMSIVector *msi_vectors; | |
133 | VFIOMSIXInfo *msix; | |
134 | int nr_vectors; /* Number of MSI/MSIX vectors currently in use */ | |
135 | int interrupt; /* Current interrupt type */ | |
136 | VFIOBAR bars[PCI_NUM_REGIONS - 1]; /* No ROM */ | |
2d82f8a3 | 137 | VFIOVGA *vga; /* 0xa0000, 0x3b0, 0x3c0 */ |
c4c45e94 | 138 | void *igd_opregion; |
78f33d2b AW |
139 | PCIHostDeviceAddress host; |
140 | EventNotifier err_notifier; | |
141 | EventNotifier req_notifier; | |
142 | int (*resetfn)(struct VFIOPCIDevice *); | |
89dcccc5 AW |
143 | uint32_t vendor_id; |
144 | uint32_t device_id; | |
145 | uint32_t sub_vendor_id; | |
146 | uint32_t sub_device_id; | |
78f33d2b AW |
147 | uint32_t features; |
148 | #define VFIO_FEATURE_ENABLE_VGA_BIT 0 | |
149 | #define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT) | |
150 | #define VFIO_FEATURE_ENABLE_REQ_BIT 1 | |
151 | #define VFIO_FEATURE_ENABLE_REQ (1 << VFIO_FEATURE_ENABLE_REQ_BIT) | |
6ced0bba AW |
152 | #define VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT 2 |
153 | #define VFIO_FEATURE_ENABLE_IGD_OPREGION \ | |
154 | (1 << VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT) | |
a9994687 | 155 | OnOffAuto display; |
c62a0c7c GH |
156 | uint32_t display_xres; |
157 | uint32_t display_yres; | |
78f33d2b | 158 | int32_t bootindex; |
c4c45e94 | 159 | uint32_t igd_gms; |
89d5202e | 160 | OffAutoPCIBAR msix_relo; |
78f33d2b | 161 | uint8_t pm_cap; |
dfbee78d | 162 | uint8_t nv_gpudirect_clique; |
78f33d2b AW |
163 | bool pci_aer; |
164 | bool req_enabled; | |
165 | bool has_flr; | |
166 | bool has_pm_reset; | |
167 | bool rom_read_failed; | |
168 | bool no_kvm_intx; | |
169 | bool no_kvm_msi; | |
170 | bool no_kvm_msix; | |
db32d0f4 | 171 | bool no_geforce_quirks; |
c958c51d | 172 | bool no_kvm_ioeventfd; |
2b1dbd0d | 173 | bool no_vfio_ioeventfd; |
b290659f | 174 | bool enable_ramfb; |
dc580d51 | 175 | bool defer_kvm_irq_routing; |
00195ba7 | 176 | VFIODisplay *dpy; |
c5478fea | 177 | Notifier irqchip_change_notifier; |
db1015e9 | 178 | }; |
78f33d2b | 179 | |
29d62771 TH |
180 | /* Use uin32_t for vendor & device so PCI_ANY_ID expands and cannot match hw */ |
181 | static inline bool vfio_pci_is(VFIOPCIDevice *vdev, uint32_t vendor, uint32_t device) | |
182 | { | |
183 | return (vendor == PCI_ANY_ID || vendor == vdev->vendor_id) && | |
184 | (device == PCI_ANY_ID || device == vdev->device_id); | |
185 | } | |
186 | ||
187 | static inline bool vfio_is_vga(VFIOPCIDevice *vdev) | |
188 | { | |
189 | PCIDevice *pdev = &vdev->pdev; | |
190 | uint16_t class = pci_get_word(pdev->config + PCI_CLASS_DEVICE); | |
191 | ||
192 | return class == PCI_CLASS_DISPLAY_VGA; | |
193 | } | |
194 | ||
c00d61d8 AW |
195 | uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len); |
196 | void vfio_pci_write_config(PCIDevice *pdev, | |
197 | uint32_t addr, uint32_t val, int len); | |
198 | ||
199 | uint64_t vfio_vga_read(void *opaque, hwaddr addr, unsigned size); | |
200 | void vfio_vga_write(void *opaque, hwaddr addr, uint64_t data, unsigned size); | |
201 | ||
4eda914c | 202 | bool vfio_opt_rom_in_denylist(VFIOPCIDevice *vdev); |
c00d61d8 | 203 | void vfio_vga_quirk_setup(VFIOPCIDevice *vdev); |
2d82f8a3 AW |
204 | void vfio_vga_quirk_exit(VFIOPCIDevice *vdev); |
205 | void vfio_vga_quirk_finalize(VFIOPCIDevice *vdev); | |
c00d61d8 | 206 | void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr); |
2d82f8a3 AW |
207 | void vfio_bar_quirk_exit(VFIOPCIDevice *vdev, int nr); |
208 | void vfio_bar_quirk_finalize(VFIOPCIDevice *vdev, int nr); | |
c9c50009 | 209 | void vfio_setup_resetfn_quirk(VFIOPCIDevice *vdev); |
e3f79f3b | 210 | int vfio_add_virt_caps(VFIOPCIDevice *vdev, Error **errp); |
469d02de | 211 | void vfio_quirk_reset(VFIOPCIDevice *vdev); |
29d62771 TH |
212 | VFIOQuirk *vfio_quirk_alloc(int nr_mem); |
213 | void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr); | |
c00d61d8 | 214 | |
dfbee78d AW |
215 | extern const PropertyInfo qdev_prop_nv_gpudirect_clique; |
216 | ||
cde4279b | 217 | int vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp); |
e593c021 | 218 | |
6ced0bba | 219 | int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev, |
7237011d EA |
220 | struct vfio_region_info *info, |
221 | Error **errp); | |
ec132efa AK |
222 | int vfio_pci_nvidia_v100_ram_init(VFIOPCIDevice *vdev, Error **errp); |
223 | int vfio_pci_nvlink2_init(VFIOPCIDevice *vdev, Error **errp); | |
6ced0bba | 224 | |
8983e3e3 | 225 | void vfio_display_reset(VFIOPCIDevice *vdev); |
a9994687 GH |
226 | int vfio_display_probe(VFIOPCIDevice *vdev, Error **errp); |
227 | void vfio_display_finalize(VFIOPCIDevice *vdev); | |
228 | ||
78f33d2b | 229 | #endif /* HW_VFIO_VFIO_PCI_H */ |