| 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 | |
| 15 | #include "system/memory.h" |
| 16 | #include "hw/pci/pci_device.h" |
| 17 | #include "hw/vfio/types.h" |
| 18 | #include "hw/vfio/vfio-device.h" |
| 19 | #include "hw/vfio/vfio-region.h" |
| 20 | #include "qemu/event_notifier.h" |
| 21 | #include "qemu/queue.h" |
| 22 | #include "qemu/timer.h" |
| 23 | #include "qom/object.h" |
| 24 | #include "system/kvm.h" |
| 25 | #include "vfio-display.h" |
| 26 | |
| 27 | #define PCI_ANY_ID (~0) |
| 28 | |
| 29 | struct VFIOPCIDevice; |
| 30 | |
| 31 | typedef struct VFIOIOEventFD { |
| 32 | QLIST_ENTRY(VFIOIOEventFD) next; |
| 33 | MemoryRegion *mr; |
| 34 | hwaddr addr; |
| 35 | unsigned size; |
| 36 | uint64_t data; |
| 37 | EventNotifier e; |
| 38 | VFIORegion *region; |
| 39 | hwaddr region_addr; |
| 40 | bool dynamic; /* Added runtime, removed on device reset */ |
| 41 | bool vfio; |
| 42 | } VFIOIOEventFD; |
| 43 | |
| 44 | typedef struct VFIOQuirk { |
| 45 | QLIST_ENTRY(VFIOQuirk) next; |
| 46 | void *data; |
| 47 | QLIST_HEAD(, VFIOIOEventFD) ioeventfds; |
| 48 | int nr_mem; |
| 49 | MemoryRegion *mem; |
| 50 | void (*reset)(struct VFIOPCIDevice *vdev, struct VFIOQuirk *quirk); |
| 51 | } VFIOQuirk; |
| 52 | |
| 53 | typedef struct VFIOBAR { |
| 54 | VFIORegion region; |
| 55 | MemoryRegion *mr; |
| 56 | size_t size; |
| 57 | uint8_t type; |
| 58 | bool ioport; |
| 59 | bool mem64; |
| 60 | QLIST_HEAD(, VFIOQuirk) quirks; |
| 61 | } VFIOBAR; |
| 62 | |
| 63 | typedef struct VFIOVGARegion { |
| 64 | MemoryRegion mem; |
| 65 | off_t offset; |
| 66 | int nr; |
| 67 | QLIST_HEAD(, VFIOQuirk) quirks; |
| 68 | } VFIOVGARegion; |
| 69 | |
| 70 | typedef struct VFIOVGA { |
| 71 | off_t fd_offset; |
| 72 | int fd; |
| 73 | VFIOVGARegion region[QEMU_PCI_VGA_NUM_REGIONS]; |
| 74 | } VFIOVGA; |
| 75 | |
| 76 | typedef struct VFIOINTx { |
| 77 | bool pending; /* interrupt pending */ |
| 78 | bool kvm_accel; /* set when QEMU bypass through KVM enabled */ |
| 79 | uint8_t pin; /* which pin to pull for qemu_set_irq */ |
| 80 | EventNotifier interrupt; /* eventfd triggered on interrupt */ |
| 81 | EventNotifier unmask; /* eventfd for unmask on QEMU bypass */ |
| 82 | PCIINTxRoute route; /* routing info for QEMU bypass */ |
| 83 | uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */ |
| 84 | QEMUTimer *mmap_timer; /* enable mmaps after periods w/o interrupts */ |
| 85 | } VFIOINTx; |
| 86 | |
| 87 | typedef struct VFIOMSIVector { |
| 88 | /* |
| 89 | * Two interrupt paths are configured per vector. The first, is only used |
| 90 | * for interrupts injected via QEMU. This is typically the non-accel path, |
| 91 | * but may also be used when we want QEMU to handle masking and pending |
| 92 | * bits. The KVM path bypasses QEMU and is therefore higher performance, |
| 93 | * but requires masking at the device. virq is used to track the MSI route |
| 94 | * through KVM, thus kvm_interrupt is only available when virq is set to a |
| 95 | * valid (>= 0) value. |
| 96 | */ |
| 97 | EventNotifier interrupt; |
| 98 | EventNotifier kvm_interrupt; |
| 99 | struct VFIOPCIDevice *vdev; /* back pointer to device */ |
| 100 | int virq; |
| 101 | bool use; |
| 102 | } VFIOMSIVector; |
| 103 | |
| 104 | enum { |
| 105 | VFIO_INT_NONE = 0, |
| 106 | VFIO_INT_INTx = 1, |
| 107 | VFIO_INT_MSI = 2, |
| 108 | VFIO_INT_MSIX = 3, |
| 109 | }; |
| 110 | |
| 111 | /* Cache of MSI-X setup */ |
| 112 | typedef struct VFIOMSIXInfo { |
| 113 | uint8_t table_bar; |
| 114 | uint8_t pba_bar; |
| 115 | uint16_t entries; |
| 116 | uint32_t table_offset; |
| 117 | uint32_t pba_offset; |
| 118 | unsigned long *pending; |
| 119 | bool noresize; |
| 120 | MemoryRegion *pba_region; |
| 121 | } VFIOMSIXInfo; |
| 122 | |
| 123 | OBJECT_DECLARE_SIMPLE_TYPE(VFIOPCIDevice, VFIO_PCI_DEVICE) |
| 124 | |
| 125 | struct VFIOPCIDevice { |
| 126 | PCIDevice parent_obj; |
| 127 | |
| 128 | VFIODevice vbasedev; |
| 129 | VFIOINTx intx; |
| 130 | unsigned int config_size; |
| 131 | uint8_t *emulated_config_bits; /* QEMU emulated bits, little-endian */ |
| 132 | off_t config_offset; /* Offset of config space region within device fd */ |
| 133 | unsigned int rom_size; |
| 134 | off_t rom_offset; /* Offset of ROM region within device fd */ |
| 135 | void *rom; |
| 136 | int msi_cap_size; |
| 137 | VFIOMSIVector *msi_vectors; |
| 138 | VFIOMSIXInfo *msix; |
| 139 | int nr_vectors; /* Number of MSI/MSIX vectors currently in use */ |
| 140 | int interrupt; /* Current interrupt type */ |
| 141 | VFIOBAR bars[PCI_NUM_REGIONS - 1]; /* No ROM */ |
| 142 | VFIOVGA *vga; /* 0xa0000, 0x3b0, 0x3c0 */ |
| 143 | void *igd_opregion; |
| 144 | PCIHostDeviceAddress host; |
| 145 | QemuUUID vf_token; |
| 146 | EventNotifier err_notifier; |
| 147 | EventNotifier req_notifier; |
| 148 | int (*resetfn)(struct VFIOPCIDevice *); |
| 149 | uint32_t vendor_id; |
| 150 | uint32_t device_id; |
| 151 | uint32_t sub_vendor_id; |
| 152 | uint32_t sub_device_id; |
| 153 | uint32_t class_code; |
| 154 | uint32_t features; |
| 155 | #define VFIO_FEATURE_ENABLE_VGA_BIT 0 |
| 156 | #define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT) |
| 157 | #define VFIO_FEATURE_ENABLE_REQ_BIT 1 |
| 158 | #define VFIO_FEATURE_ENABLE_REQ (1 << VFIO_FEATURE_ENABLE_REQ_BIT) |
| 159 | #define VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT 2 |
| 160 | #define VFIO_FEATURE_ENABLE_IGD_OPREGION \ |
| 161 | (1 << VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT) |
| 162 | #define VFIO_FEATURE_ENABLE_IGD_LPC_BIT 3 |
| 163 | #define VFIO_FEATURE_ENABLE_IGD_LPC \ |
| 164 | (1 << VFIO_FEATURE_ENABLE_IGD_LPC_BIT) |
| 165 | OnOffAuto display; |
| 166 | uint32_t display_xres; |
| 167 | uint32_t display_yres; |
| 168 | int32_t bootindex; |
| 169 | OnOffAuto igd_legacy_mode; |
| 170 | uint32_t igd_gms; |
| 171 | OffAutoPCIBAR msix_relo; |
| 172 | uint8_t nv_gpudirect_clique; |
| 173 | bool pci_aer; |
| 174 | bool req_enabled; |
| 175 | bool has_flr; |
| 176 | bool has_pm_reset; |
| 177 | bool rom_read_failed; |
| 178 | bool no_kvm_intx; |
| 179 | bool no_kvm_msi; |
| 180 | bool no_kvm_msix; |
| 181 | bool no_geforce_quirks; |
| 182 | bool no_kvm_ioeventfd; |
| 183 | bool no_vfio_ioeventfd; |
| 184 | bool enable_ramfb; |
| 185 | bool use_legacy_x86_rom; |
| 186 | OnOffAuto ramfb_migrate; |
| 187 | bool defer_kvm_irq_routing; |
| 188 | bool clear_parent_atomics_on_exit; |
| 189 | bool skip_vsc_check; |
| 190 | uint16_t vpasid_cap_offset; |
| 191 | OnOffAuto ats; |
| 192 | VFIODisplay *dpy; |
| 193 | Notifier irqchip_change_notifier; |
| 194 | VFIOPCICPR cpr; |
| 195 | }; |
| 196 | |
| 197 | /* Use uin32_t for vendor & device so PCI_ANY_ID expands and cannot match hw */ |
| 198 | static inline bool vfio_pci_is(VFIOPCIDevice *vdev, uint32_t vendor, uint32_t device) |
| 199 | { |
| 200 | return (vendor == PCI_ANY_ID || vendor == vdev->vendor_id) && |
| 201 | (device == PCI_ANY_ID || device == vdev->device_id); |
| 202 | } |
| 203 | |
| 204 | static inline bool vfio_is_vga(VFIOPCIDevice *vdev) |
| 205 | { |
| 206 | return (vdev->class_code >> 8) == PCI_CLASS_DISPLAY_VGA; |
| 207 | } |
| 208 | |
| 209 | static inline bool vfio_is_base_display(VFIOPCIDevice *vdev) |
| 210 | { |
| 211 | return (vdev->class_code >> 16) == PCI_BASE_CLASS_DISPLAY; |
| 212 | } |
| 213 | |
| 214 | /* MSI/MSI-X/INTx */ |
| 215 | void vfio_pci_vector_init(VFIOPCIDevice *vdev, int nr); |
| 216 | void vfio_pci_add_kvm_msi_virq(VFIOPCIDevice *vdev, VFIOMSIVector *vector, |
| 217 | int vector_n, bool msix); |
| 218 | void vfio_pci_prepare_kvm_msi_virq_batch(VFIOPCIDevice *vdev); |
| 219 | void vfio_pci_commit_kvm_msi_virq_batch(VFIOPCIDevice *vdev); |
| 220 | bool vfio_pci_intx_enable(VFIOPCIDevice *vdev, Error **errp); |
| 221 | void vfio_pci_intx_set_handler(VFIOPCIDevice *vdev, bool enable); |
| 222 | void vfio_pci_msix_set_notifiers(VFIOPCIDevice *vdev); |
| 223 | void vfio_pci_msi_set_handler(VFIOPCIDevice *vdev, int nr, bool enable); |
| 224 | |
| 225 | uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len); |
| 226 | void vfio_pci_write_config(PCIDevice *pdev, |
| 227 | uint32_t addr, uint32_t val, int len); |
| 228 | |
| 229 | uint64_t vfio_vga_read(void *opaque, hwaddr addr, unsigned size); |
| 230 | void vfio_vga_write(void *opaque, hwaddr addr, uint64_t data, unsigned size); |
| 231 | |
| 232 | /** |
| 233 | * vfio_pci_from_vfio_device: Transform from VFIODevice to |
| 234 | * VFIOPCIDevice |
| 235 | * |
| 236 | * This function checks if the given @vbasedev is a VFIO PCI device. |
| 237 | * If it is, it returns the containing VFIOPCIDevice. |
| 238 | * |
| 239 | * @vbasedev: The VFIODevice to transform |
| 240 | * |
| 241 | * Return: The VFIOPCIDevice on success, NULL on failure. |
| 242 | */ |
| 243 | VFIOPCIDevice *vfio_pci_from_vfio_device(VFIODevice *vbasedev); |
| 244 | void vfio_sub_page_bar_update_mappings(VFIOPCIDevice *vdev); |
| 245 | bool vfio_opt_rom_in_denylist(VFIOPCIDevice *vdev); |
| 246 | bool vfio_config_quirk_setup(VFIOPCIDevice *vdev, Error **errp); |
| 247 | void vfio_vga_quirk_setup(VFIOPCIDevice *vdev); |
| 248 | void vfio_vga_quirk_exit(VFIOPCIDevice *vdev); |
| 249 | void vfio_vga_quirk_finalize(VFIOPCIDevice *vdev); |
| 250 | void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr); |
| 251 | void vfio_bar_quirk_exit(VFIOPCIDevice *vdev, int nr); |
| 252 | void vfio_bar_quirk_finalize(VFIOPCIDevice *vdev, int nr); |
| 253 | void vfio_setup_resetfn_quirk(VFIOPCIDevice *vdev); |
| 254 | bool vfio_add_virt_caps(VFIOPCIDevice *vdev, Error **errp); |
| 255 | void vfio_rom_quirk_setup(VFIOPCIDevice *vdev); |
| 256 | void vfio_quirk_reset(VFIOPCIDevice *vdev); |
| 257 | VFIOQuirk *vfio_quirk_alloc(int nr_mem); |
| 258 | |
| 259 | void vfio_probe_igd_bar0_quirk(VFIOPCIDevice *vdev, int nr); |
| 260 | bool vfio_probe_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp); |
| 261 | void vfio_igd_legacy_rom_quirk(VFIOPCIDevice *vdev); |
| 262 | |
| 263 | extern const PropertyInfo qdev_prop_nv_gpudirect_clique; |
| 264 | |
| 265 | struct vfio_pci_hot_reset_info; |
| 266 | |
| 267 | void vfio_pci_pre_reset(VFIOPCIDevice *vdev); |
| 268 | void vfio_pci_post_reset(VFIOPCIDevice *vdev); |
| 269 | bool vfio_pci_host_match(PCIHostDeviceAddress *addr, const char *name); |
| 270 | int vfio_pci_get_pci_hot_reset_info(VFIOPCIDevice *vdev, |
| 271 | struct vfio_pci_hot_reset_info **info_p); |
| 272 | |
| 273 | bool vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp); |
| 274 | |
| 275 | void vfio_display_reset(VFIOPCIDevice *vdev); |
| 276 | bool vfio_display_probe(VFIOPCIDevice *vdev, Error **errp); |
| 277 | void vfio_display_exit(VFIOPCIDevice *vdev); |
| 278 | void vfio_display_finalize(VFIOPCIDevice *vdev); |
| 279 | |
| 280 | extern const VMStateDescription vfio_display_vmstate; |
| 281 | |
| 282 | void vfio_pci_bars_exit(VFIOPCIDevice *vdev); |
| 283 | bool vfio_pci_add_capabilities(VFIOPCIDevice *vdev, Error **errp); |
| 284 | void vfio_pci_config_register_vga(VFIOPCIDevice *vdev); |
| 285 | bool vfio_pci_config_setup(VFIOPCIDevice *vdev, Error **errp); |
| 286 | bool vfio_pci_interrupt_setup(VFIOPCIDevice *vdev, Error **errp); |
| 287 | void vfio_pci_intx_eoi(VFIODevice *vbasedev); |
| 288 | void vfio_pci_put_device(VFIOPCIDevice *vdev); |
| 289 | bool vfio_pci_populate_device(VFIOPCIDevice *vdev, Error **errp); |
| 290 | void vfio_pci_register_err_notifier(VFIOPCIDevice *vdev); |
| 291 | void vfio_pci_register_req_notifier(VFIOPCIDevice *vdev); |
| 292 | void vfio_pci_teardown_msi(VFIOPCIDevice *vdev); |
| 293 | |
| 294 | #endif /* HW_VFIO_VFIO_PCI_H */ |