Signed-off-by: Lan Tianyu <tianyu.lan@xxxxxxxxx> --- hw/vfio/pci.c | 137 +------------------------------------------------- hw/vfio/pci.h | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 136 deletions(-) create mode 100644 hw/vfio/pci.h diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index e0e339a..5c3f8a7 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -42,138 +42,7 @@ #include "trace.h" #include "hw/vfio/vfio.h" #include "hw/vfio/vfio-common.h" - -struct VFIOPCIDevice; - -typedef struct VFIOQuirk { - MemoryRegion mem; - struct VFIOPCIDevice *vdev; - QLIST_ENTRY(VFIOQuirk) next; - struct { - uint32_t base_offset:TARGET_PAGE_BITS; - uint32_t address_offset:TARGET_PAGE_BITS; - uint32_t address_size:3; - uint32_t bar:3; - - uint32_t address_match; - uint32_t address_mask; - - uint32_t address_val:TARGET_PAGE_BITS; - uint32_t data_offset:TARGET_PAGE_BITS; - uint32_t data_size:3; - - uint8_t flags; - uint8_t read_flags; - uint8_t write_flags; - } data; -} VFIOQuirk; - -typedef struct VFIOBAR { - VFIORegion region; - bool ioport; - bool mem64; - QLIST_HEAD(, VFIOQuirk) quirks; -} VFIOBAR; - -typedef struct VFIOVGARegion { - MemoryRegion mem; - off_t offset; - int nr; - QLIST_HEAD(, VFIOQuirk) quirks; -} VFIOVGARegion; - -typedef struct VFIOVGA { - off_t fd_offset; - int fd; - VFIOVGARegion region[QEMU_PCI_VGA_NUM_REGIONS]; -} VFIOVGA; - -typedef struct VFIOINTx { - bool pending; /* interrupt pending */ - bool kvm_accel; /* set when QEMU bypass through KVM enabled */ - uint8_t pin; /* which pin to pull for qemu_set_irq */ - EventNotifier interrupt; /* eventfd triggered on interrupt */ - EventNotifier unmask; /* eventfd for unmask on QEMU bypass */ - PCIINTxRoute route; /* routing info for QEMU bypass */ - uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */ - QEMUTimer *mmap_timer; /* enable mmaps after periods w/o interrupts */ -} VFIOINTx; - -typedef struct VFIOMSIVector { - /* - * Two interrupt paths are configured per vector. The first, is only used - * for interrupts injected via QEMU. This is typically the non-accel path, - * but may also be used when we want QEMU to handle masking and pending - * bits. The KVM path bypasses QEMU and is therefore higher performance, - * but requires masking at the device. virq is used to track the MSI route - * through KVM, thus kvm_interrupt is only available when virq is set to a - * valid (>= 0) value. - */ - EventNotifier interrupt; - EventNotifier kvm_interrupt; - struct VFIOPCIDevice *vdev; /* back pointer to device */ - int virq; - bool use; -} VFIOMSIVector; - -enum { - VFIO_INT_NONE = 0, - VFIO_INT_INTx = 1, - VFIO_INT_MSI = 2, - VFIO_INT_MSIX = 3, -}; - -/* Cache of MSI-X setup plus extra mmap and memory region for split BAR map */ -typedef struct VFIOMSIXInfo { - uint8_t table_bar; - uint8_t pba_bar; - uint16_t entries; - uint32_t table_offset; - uint32_t pba_offset; - MemoryRegion mmap_mem; - void *mmap; -} VFIOMSIXInfo; - -typedef struct VFIOPCIDevice { - PCIDevice pdev; - VFIODevice vbasedev; - VFIOINTx intx; - unsigned int config_size; - uint8_t *emulated_config_bits; /* QEMU emulated bits, little-endian */ - off_t config_offset; /* Offset of config space region within device fd */ - unsigned int rom_size; - off_t rom_offset; /* Offset of ROM region within device fd */ - void *rom; - int msi_cap_size; - VFIOMSIVector *msi_vectors; - VFIOMSIXInfo *msix; - int nr_vectors; /* Number of MSI/MSIX vectors currently in use */ - int interrupt; /* Current interrupt type */ - VFIOBAR bars[PCI_NUM_REGIONS - 1]; /* No ROM */ - VFIOVGA vga; /* 0xa0000, 0x3b0, 0x3c0 */ - PCIHostDeviceAddress host; - EventNotifier err_notifier; - EventNotifier req_notifier; - int (*resetfn)(struct VFIOPCIDevice *); - uint32_t features; -#define VFIO_FEATURE_ENABLE_VGA_BIT 0 -#define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT) -#define VFIO_FEATURE_ENABLE_REQ_BIT 1 -#define VFIO_FEATURE_ENABLE_REQ (1 << VFIO_FEATURE_ENABLE_REQ_BIT) - int32_t bootindex; - uint8_t pm_cap; - bool has_vga; - bool pci_aer; - bool req_enabled; - bool has_flr; - bool has_pm_reset; - bool rom_read_failed; -} VFIOPCIDevice; - -typedef struct VFIORomBlacklistEntry { - uint16_t vendor_id; - uint16_t device_id; -} VFIORomBlacklistEntry; +#include "hw/vfio/pci.h" /* * List of device ids/vendor ids for which to disable @@ -193,12 +62,8 @@ static const VFIORomBlacklistEntry romblacklist[] = { { 0x14e4, 0x168e } }; -#define MSIX_CAP_LENGTH 12 static void vfio_disable_interrupts(VFIOPCIDevice *vdev); -static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len); -static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr, - uint32_t val, int len); static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev, bool enabled); /* diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h new file mode 100644 index 0000000..9f360bf --- /dev/null +++ b/hw/vfio/pci.h @@ -0,0 +1,158 @@ +#include <dirent.h> +#include <linux/vfio.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "config.h" +#include "exec/address-spaces.h" +#include "exec/memory.h" +#include "hw/pci/msi.h" +#include "hw/pci/msix.h" +#include "hw/pci/pci.h" +#include "qemu-common.h" +#include "qemu/error-report.h" +#include "qemu/event_notifier.h" +#include "qemu/queue.h" +#include "qemu/range.h" +#include "sysemu/kvm.h" +#include "sysemu/sysemu.h" +#include "trace.h" +#include "hw/vfio/vfio.h" +#include "hw/vfio/vfio-common.h" + +struct VFIOPCIDevice; + +typedef struct VFIOQuirk { + MemoryRegion mem; + struct VFIOPCIDevice *vdev; + QLIST_ENTRY(VFIOQuirk) next; + struct { + uint32_t base_offset:TARGET_PAGE_BITS; + uint32_t address_offset:TARGET_PAGE_BITS; + uint32_t address_size:3; + uint32_t bar:3; + + uint32_t address_match; + uint32_t address_mask; + + uint32_t address_val:TARGET_PAGE_BITS; + uint32_t data_offset:TARGET_PAGE_BITS; + uint32_t data_size:3; + + uint8_t flags; + uint8_t read_flags; + uint8_t write_flags; + } data; +} VFIOQuirk; + +typedef struct VFIOBAR { + VFIORegion region; + bool ioport; + bool mem64; + QLIST_HEAD(, VFIOQuirk) quirks; +} VFIOBAR; + +typedef struct VFIOVGARegion { + MemoryRegion mem; + off_t offset; + int nr; + QLIST_HEAD(, VFIOQuirk) quirks; +} VFIOVGARegion; + +typedef struct VFIOVGA { + off_t fd_offset; + int fd; + VFIOVGARegion region[QEMU_PCI_VGA_NUM_REGIONS]; +} VFIOVGA; + +typedef struct VFIOINTx { + bool pending; /* interrupt pending */ + bool kvm_accel; /* set when QEMU bypass through KVM enabled */ + uint8_t pin; /* which pin to pull for qemu_set_irq */ + EventNotifier interrupt; /* eventfd triggered on interrupt */ + EventNotifier unmask; /* eventfd for unmask on QEMU bypass */ + PCIINTxRoute route; /* routing info for QEMU bypass */ + uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */ + QEMUTimer *mmap_timer; /* enable mmaps after periods w/o interrupts */ +} VFIOINTx; + +typedef struct VFIOMSIVector { + /* + * Two interrupt paths are configured per vector. The first, is only used + * for interrupts injected via QEMU. This is typically the non-accel path, + * but may also be used when we want QEMU to handle masking and pending + * bits. The KVM path bypasses QEMU and is therefore higher performance, + * but requires masking at the device. virq is used to track the MSI route + * through KVM, thus kvm_interrupt is only available when virq is set to a + * valid (>= 0) value. + */ + EventNotifier interrupt; + EventNotifier kvm_interrupt; + struct VFIOPCIDevice *vdev; /* back pointer to device */ + int virq; + bool use; +} VFIOMSIVector; + +enum { + VFIO_INT_NONE = 0, + VFIO_INT_INTx = 1, + VFIO_INT_MSI = 2, + VFIO_INT_MSIX = 3, +}; + +/* Cache of MSI-X setup plus extra mmap and memory region for split BAR map */ +typedef struct VFIOMSIXInfo { + uint8_t table_bar; + uint8_t pba_bar; + uint16_t entries; + uint32_t table_offset; + uint32_t pba_offset; + MemoryRegion mmap_mem; + void *mmap; +} VFIOMSIXInfo; + +typedef struct VFIOPCIDevice { + PCIDevice pdev; + VFIODevice vbasedev; + VFIOINTx intx; + unsigned int config_size; + uint8_t *emulated_config_bits; /* QEMU emulated bits, little-endian */ + off_t config_offset; /* Offset of config space region within device fd */ + unsigned int rom_size; + off_t rom_offset; /* Offset of ROM region within device fd */ + void *rom; + int msi_cap_size; + VFIOMSIVector *msi_vectors; + VFIOMSIXInfo *msix; + int nr_vectors; /* Number of MSI/MSIX vectors currently in use */ + int interrupt; /* Current interrupt type */ + VFIOBAR bars[PCI_NUM_REGIONS - 1]; /* No ROM */ + VFIOVGA vga; /* 0xa0000, 0x3b0, 0x3c0 */ + PCIHostDeviceAddress host; + EventNotifier err_notifier; + EventNotifier req_notifier; + int (*resetfn)(struct VFIOPCIDevice *); + uint32_t features; +#define VFIO_FEATURE_ENABLE_VGA_BIT 0 +#define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT) +#define VFIO_FEATURE_ENABLE_REQ_BIT 1 +#define VFIO_FEATURE_ENABLE_REQ (1 << VFIO_FEATURE_ENABLE_REQ_BIT) + int32_t bootindex; + uint8_t pm_cap; + bool has_vga; + bool pci_aer; + bool req_enabled; + bool has_flr; + bool has_pm_reset; + bool rom_read_failed; +} VFIOPCIDevice; + +typedef struct VFIORomBlacklistEntry { + uint16_t vendor_id; + uint16_t device_id; +} VFIORomBlacklistEntry; + +#define MSIX_CAP_LENGTH 12 -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html