[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] Qemu-devel Digest, Vol 137, Issue 266
From: |
Fernando Oliveira |
Subject: |
Re: [Qemu-devel] Qemu-devel Digest, Vol 137, Issue 266 |
Date: |
Sat, 9 Aug 2014 10:52:54 -0400 |
On Aug 9, 2014 10:28 AM, <address@hidden> wrote:
>
> Send Qemu-devel mailing list submissions to
> address@hidden
>
> To subscribe or unsubscribe via the World Wide Web, visit
> https://lists.nongnu.orgl/mailman/listinfo/qemu-devel
> or, via email, send a message with subject or body 'help' to
> address@hidden
>
> You can reach the person managing the list at
> address@hidden
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of Qemu-devel digest..."
>
> Today's Topics:
>
> 1. [PATCH v5 03/10] hw/vfio/pci: introduce VFIODevice (Eric Auger)
>
>
> ---------- Forwarded message ----------
> From: Eric Auger <address@hidden>
> To: address@hidden, address@hidden, address@hidden, address@hidden, address@hidden
> Cc: address@hidden, address@hidden, address@hidden, address@hidden, address@hidden, address@hidden, address@hidden, address@hidden, address@hidden, address@hidden, address@hidden
> Date: Sat, 9 Aug 2014 15:25:42 +0100
> Subject: [Qemu-devel] [PATCH v5 03/10] hw/vfio/pci: introduce VFIODevice
> Introduce the VFIODevice struct that is going to be shared by
> VFIOPCIDevice and VFIOPlatformDevice.
>
> Additional fields will be added there later on for review
> convenience.
>
> the group's device_list becomes a list of VFIODevice
>
> This obliges to rework the reset_handler which becomes generic and
> calls VFIODevice ops that are specialized in each parent object.
> Also functions that iterate on this list must take care that the
> devices can be something else than VFIOPCIDevice. The type is used
> to discriminate them.
>
> we profit from this step to change the prototype of
> vfio_unmask_intx, vfio_mask_intx, vfio_disable_irqindex which now
> apply to VFIODevice. They are renamed as *_irqindex.
> The index is passed as parameter to anticipate their usage for
> platform IRQs
>
> Signed-off-by: Eric Auger <address@hidden>
>
> ---
>
> v4->v5:
> - fix style issues
> - in vfio_initfn, rework allocation of vdev->vbasedev.name and
> replace snprintf by g_strdup_printf
> ---
> hw/vfio/pci.c | 239 +++++++++++++++++++++++++++++++++++-----------------------
> 1 file changed, 146 insertions(+), 93 deletions(-)
>
> diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
> index c2cdd73..ae827c5 100644
> --- a/hw/vfio/pci.c
> +++ b/hw/vfio/pci.c
> @@ -56,6 +56,11 @@
> #define VFIO_ALLOW_KVM_MSI 1
> #define VFIO_ALLOW_KVM_MSIX 1
>
> +enum {
> + VFIO_DEVICE_TYPE_PCI = 0,
> + VFIO_DEVICE_TYPE_PLATFORM = 1,
> +};
> +
> struct VFIOPCIDevice;
>
> typedef struct VFIOQuirk {
> @@ -193,9 +198,27 @@ typedef struct VFIOMSIXInfo {
> void *mmap;
> } VFIOMSIXInfo;
>
> +typedef struct VFIODeviceOps VFIODeviceOps;
> +
> +typedef struct VFIODevice {
> + QLIST_ENTRY(VFIODevice) next;
> + struct VFIOGroup *group;
> + char *name;
> + int fd;
> + int type;
> + bool reset_works;
> + bool needs_reset;
> + VFIODeviceOps *ops;
> +} VFIODevice;
> +
> +struct VFIODeviceOps {
> + bool (*vfio_compute_needs_reset)(VFIODevice *vdev);
> + int (*vfio_hot_reset_multi)(VFIODevice *vdev);
> +};
> +
> typedef struct VFIOPCIDevice {
> PCIDevice pdev;
> - int fd;
> + VFIODevice vbasedev;
> VFIOINTx intx;
> unsigned int config_size;
> uint8_t *emulated_config_bits; /* QEMU emulated bits, little-endian */
> @@ -211,20 +234,16 @@ typedef struct VFIOPCIDevice {
> VFIOBAR bars[PCI_NUM_REGIONS - 1]; /* No ROM */
> VFIOVGA vga; /* 0xa0000, 0x3b0, 0x3c0 */
> PCIHostDeviceAddress host;
> - QLIST_ENTRY(VFIOPCIDevice) next;
> - struct VFIOGroup *group;
> EventNotifier err_notifier;
> uint32_t features;
> #define VFIO_FEATURE_ENABLE_VGA_BIT 0
> #define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT)
> int32_t bootindex;
> uint8_t pm_cap;
> - bool reset_works;
> bool has_vga;
> bool pci_aer;
> bool has_flr;
> bool has_pm_reset;
> - bool needs_reset;
> bool rom_read_failed;
> } VFIOPCIDevice;
>
> @@ -232,7 +251,7 @@ typedef struct VFIOGroup {
> int fd;
> int groupid;
> VFIOContainer *container;
> - QLIST_HEAD(, VFIOPCIDevice) device_list;
> + QLIST_HEAD(, VFIODevice) device_list;
> QLIST_ENTRY(VFIOGroup) next;
> QLIST_ENTRY(VFIOGroup) container_next;
> } VFIOGroup;
> @@ -285,7 +304,7 @@ static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev, bool enabled);
> /*
> * Common VFIO interrupt disable
> */
> -static void vfio_disable_irqindex(VFIOPCIDevice *vdev, int index)
> +static void vfio_disable_irqindex(VFIODevice *vbasedev, int index)
> {
> struct vfio_irq_set irq_set = {
> .argsz = sizeof(irq_set),
> @@ -295,37 +314,37 @@ static void vfio_disable_irqindex(VFIOPCIDevice *vdev, int index)
> .count = 0,
> };
>
> - ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
> + ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
> }
>
> /*
> * INTx
> */
> -static void vfio_unmask_intx(VFIOPCIDevice *vdev)
> +static void vfio_unmask_irqindex(VFIODevice *vbasedev, int index)
> {
> struct vfio_irq_set irq_set = {
> .argsz = sizeof(irq_set),
> .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_UNMASK,
> - .index = VFIO_PCI_INTX_IRQ_INDEX,
> + .index = index,
> .start = 0,
> .count = 1,
> };
>
> - ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
> + ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
> }
>
> #ifdef CONFIG_KVM /* Unused outside of CONFIG_KVM code */
> -static void vfio_mask_intx(VFIOPCIDevice *vdev)
> +static void vfio_mask_irqindex(VFIODevice *vbasedev, int index)
> {
> struct vfio_irq_set irq_set = {
> .argsz = sizeof(irq_set),
> .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_MASK,
> - .index = VFIO_PCI_INTX_IRQ_INDEX,
> + .index = index,
> .start = 0,
> .count = 1,
> };
>
> - ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
> + ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
> }
> #endif
>
> @@ -389,7 +408,7 @@ static void vfio_eoi(VFIOPCIDevice *vdev)
>
> vdev->intx.pending = false;
> pci_irq_deassert(&vdev->pdev);
> - vfio_unmask_intx(vdev);
> + vfio_unmask_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
> }
>
> static void vfio_enable_intx_kvm(VFIOPCIDevice *vdev)
> @@ -412,7 +431,7 @@ static void vfio_enable_intx_kvm(VFIOPCIDevice *vdev)
>
> /* Get to a known interrupt state */
> qemu_set_fd_handler(irqfd.fd, NULL, NULL, vdev);
> - vfio_mask_intx(vdev);
> + vfio_mask_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
> vdev->intx.pending = false;
> pci_irq_deassert(&vdev->pdev);
>
> @@ -442,7 +461,7 @@ static void vfio_enable_intx_kvm(VFIOPCIDevice *vdev)
>
> *pfd = irqfd.resamplefd;
>
> - ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
> + ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set);
> g_free(irq_set);
> if (ret) {
> error_report("vfio: Error: Failed to setup INTx unmask fd: %m");
> @@ -450,7 +469,7 @@ static void vfio_enable_intx_kvm(VFIOPCIDevice *vdev)
> }
>
> /* Let'em rip */
> - vfio_unmask_intx(vdev);
> + vfio_unmask_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
>
> vdev->intx.kvm_accel = true;
>
> @@ -467,7 +486,7 @@ fail_irqfd:
> event_notifier_cleanup(&vdev->intx.unmask);
> fail:
> qemu_set_fd_handler(irqfd.fd, vfio_intx_interrupt, NULL, vdev);
> - vfio_unmask_intx(vdev);
> + vfio_unmask_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
> #endif
> }
>
> @@ -488,7 +507,7 @@ static void vfio_disable_intx_kvm(VFIOPCIDevice *vdev)
> * Get to a known state, hardware masked, QEMU ready to accept new
> * interrupts, QEMU IRQ de-asserted.
> */
> - vfio_mask_intx(vdev);
> + vfio_mask_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
> vdev->intx.pending = false;
> pci_irq_deassert(&vdev->pdev);
>
> @@ -506,7 +525,7 @@ static void vfio_disable_intx_kvm(VFIOPCIDevice *vdev)
> vdev->intx.kvm_accel = false;
>
> /* If we've missed an event, let it re-fire through QEMU */
> - vfio_unmask_intx(vdev);
> + vfio_unmask_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
>
> DPRINTF("%s(%04x:%02x:%02x.%x) KVM INTx accel disabled\n",
> __func__, vdev->host.domain, vdev->host.bus,
> @@ -594,7 +613,7 @@ static int vfio_enable_intx(VFIOPCIDevice *vdev)
> *pfd = event_notifier_get_fd(&vdev->intx.interrupt);
> qemu_set_fd_handler(*pfd, vfio_intx_interrupt, NULL, vdev);
>
> - ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
> + ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set);
> g_free(irq_set);
> if (ret) {
> error_report("vfio: Error: Failed to setup INTx fd: %m");
> @@ -619,7 +638,7 @@ static void vfio_disable_intx(VFIOPCIDevice *vdev)
>
> timer_del(vdev->intx.mmap_timer);
> vfio_disable_intx_kvm(vdev);
> - vfio_disable_irqindex(vdev, VFIO_PCI_INTX_IRQ_INDEX);
> + vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
> vdev->intx.pending = false;
> pci_irq_deassert(&vdev->pdev);
> vfio_mmap_set_enabled(vdev, true);
> @@ -709,7 +728,7 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix)
> fds[i] = fd;
> }
>
> - ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
> + ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set);
>
> g_free(irq_set);
>
> @@ -806,7 +825,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
> * increase them as needed.
> */
> if (vdev->nr_vectors < nr + 1) {
> - vfio_disable_irqindex(vdev, VFIO_PCI_MSIX_IRQ_INDEX);
> + vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_MSIX_IRQ_INDEX);
> vdev->nr_vectors = nr + 1;
> ret = vfio_enable_vectors(vdev, true);
> if (ret) {
> @@ -834,7 +853,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
> *pfd = event_notifier_get_fd(&vector->interrupt);
> }
>
> - ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
> + ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set);
> g_free(irq_set);
> if (ret) {
> error_report("vfio: failed to modify vector, %d", ret);
> @@ -885,7 +904,7 @@ static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr)
>
> *pfd = event_notifier_get_fd(&vector->interrupt);
>
> - ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
> + ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set);
>
> g_free(irq_set);
> }
> @@ -1044,7 +1063,7 @@ static void vfio_disable_msix(VFIOPCIDevice *vdev)
> }
>
> if (vdev->nr_vectors) {
> - vfio_disable_irqindex(vdev, VFIO_PCI_MSIX_IRQ_INDEX);
> + vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_MSIX_IRQ_INDEX);
> }
>
> vfio_disable_msi_common(vdev);
> @@ -1055,7 +1074,7 @@ static void vfio_disable_msix(VFIOPCIDevice *vdev)
>
> static void vfio_disable_msi(VFIOPCIDevice *vdev)
> {
> - vfio_disable_irqindex(vdev, VFIO_PCI_MSI_IRQ_INDEX);
> + vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_MSI_IRQ_INDEX);
> vfio_disable_msi_common(vdev);
>
> DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain,
> @@ -1201,7 +1220,7 @@ static void vfio_pci_load_rom(VFIOPCIDevice *vdev)
> off_t off = 0;
> size_t bytes;
>
> - if (ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, ®_info)) {
> + if (ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_REGION_INFO, ®_info)) {
> error_report("vfio: Error getting ROM info: %m");
> return;
> }
> @@ -1231,7 +1250,8 @@ static void vfio_pci_load_rom(VFIOPCIDevice *vdev)
> memset(vdev->rom, 0xff, size);
>
> while (size) {
> - bytes = pread(vdev->fd, vdev->rom + off, size, vdev->rom_offset + off);
> + bytes = pread(vdev->vbasedev.fd, vdev->rom + off,
> + size, vdev->rom_offset + off);
> if (bytes == 0) {
> break;
> } else if (bytes > 0) {
> @@ -1325,6 +1345,7 @@ static void vfio_pci_size_rom(VFIOPCIDevice *vdev)
> off_t offset = vdev->config_offset + PCI_ROM_ADDRESS;
> DeviceState *dev = DEVICE(vdev);
> char name[32];
> + int fd = vdev->vbasedev.fd;
>
> if (vdev->pdev.romfile || !vdev->pdev.rom_bar) {
> /* Since pci handles romfile, just print a message and return */
> @@ -1343,10 +1364,10 @@ static void vfio_pci_size_rom(VFIOPCIDevice *vdev)
> * Use the same size ROM BAR as the physical device. The contents
> * will get filled in later when the guest tries to read it.
> */
> - if (pread(vdev->fd, &orig, 4, offset) != 4 ||
> - pwrite(vdev->fd, &size, 4, offset) != 4 ||
> - pread(vdev->fd, &size, 4, offset) != 4 ||
> - pwrite(vdev->fd, &orig, 4, offset) != 4) {
> + if (pread(fd, &orig, 4, offset) != 4 ||
> + pwrite(fd, &size, 4, offset) != 4 ||
> + pread(fd, &size, 4, offset) != 4 ||
> + pwrite(fd, &orig, 4, offset) != 4) {
> error_report("%s(%04x:%02x:%02x.%x) failed: %m",
> __func__, vdev->host.domain, vdev->host.bus,
> vdev->host.slot, vdev->host.function);
> @@ -2330,7 +2351,8 @@ static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len)
> if (~emu_bits & (0xffffffffU >> (32 - len * 8))) {
> ssize_t ret;
>
> - ret = pread(vdev->fd, &phys_val, len, vdev->config_offset + addr);
> + ret = pread(vdev->vbasedev.fd, &phys_val, len,
> + vdev->config_offset + addr);
> if (ret != len) {
> error_report("%s(%04x:%02x:%02x.%x, 0x%x, 0x%x) failed: %m",
> __func__, vdev->host.domain, vdev->host.bus,
> @@ -2360,7 +2382,8 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
> vdev->host.function, addr, val, len);
>
> /* Write everything to VFIO, let it filter out what we can't write */
> - if (pwrite(vdev->fd, &val_le, len, vdev->config_offset + addr) != len) {
> + if (pwrite(vdev->vbasedev.fd, &val_le, len, vdev->config_offset + addr)
> + != len) {
> error_report("%s(%04x:%02x:%02x.%x, 0x%x, 0x%x, 0x%x) failed: %m",
> __func__, vdev->host.domain, vdev->host.bus,
> vdev->host.slot, vdev->host.function, addr, val, len);
> @@ -2730,7 +2753,7 @@ static int vfio_setup_msi(VFIOPCIDevice *vdev, int pos)
> bool msi_64bit, msi_maskbit;
> int ret, entries;
>
> - if (pread(vdev->fd, &ctrl, sizeof(ctrl),
> + if (pread(vdev->vbasedev.fd, &ctrl, sizeof(ctrl),
> vdev->config_offset + pos + PCI_CAP_FLAGS) != sizeof(ctrl)) {
> return -errno;
> }
> @@ -2769,23 +2792,24 @@ static int vfio_early_setup_msix(VFIOPCIDevice *vdev)
> uint8_t pos;
> uint16_t ctrl;
> uint32_t table, pba;
> + int fd = vdev->vbasedev.fd;
>
> pos = pci_find_capability(&vdev->pdev, PCI_CAP_ID_MSIX);
> if (!pos) {
> return 0;
> }
>
> - if (pread(vdev->fd, &ctrl, sizeof(ctrl),
> + if (pread(fd, &ctrl, sizeof(ctrl),
> vdev->config_offset + pos + PCI_CAP_FLAGS) != sizeof(ctrl)) {
> return -errno;
> }
>
> - if (pread(vdev->fd, &table, sizeof(table),
> + if (pread(fd, &table, sizeof(table),
> vdev->config_offset + pos + PCI_MSIX_TABLE) != sizeof(table)) {
> return -errno;
> }
>
> - if (pread(vdev->fd, &pba, sizeof(pba),
> + if (pread(fd, &pba, sizeof(pba),
> vdev->config_offset + pos + PCI_MSIX_PBA) != sizeof(pba)) {
> return -errno;
> }
> @@ -2941,7 +2965,7 @@ static void vfio_map_bar(VFIOPCIDevice *vdev, int nr)
> vdev->host.function, nr);
>
> /* Determine what type of BAR this is for registration */
> - ret = pread(vdev->fd, &pci_bar, sizeof(pci_bar),
> + ret = pread(vdev->vbasedev.fd, &pci_bar, sizeof(pci_bar),
> vdev->config_offset + PCI_BASE_ADDRESS_0 + (4 * nr));
> if (ret != sizeof(pci_bar)) {
> error_report("vfio: Failed to read BAR %d (%m)", nr);
> @@ -3362,12 +3386,12 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
> single ? "one" : "multi");
>
> vfio_pci_pre_reset(vdev);
> - vdev->needs_reset = false;
> + vdev->vbasedev.needs_reset = false;
>
> info = g_malloc0(sizeof(*info));
> info->argsz = sizeof(*info);
>
> - ret = ioctl(vdev->fd, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, info);
> + ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, info);
> if (ret && errno != ENOSPC) {
> ret = -errno;
> if (!vdev->has_pm_reset) {
> @@ -3383,7 +3407,7 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
> info->argsz = sizeof(*info) + (count * sizeof(*devices));
> devices = &info->devices[0];
>
> - ret = ioctl(vdev->fd, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, info);
> + ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, info);
> if (ret) {
> ret = -errno;
> error_report("vfio: hot reset info failed: %m");
> @@ -3398,6 +3422,7 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
> for (i = 0; i < info->count; i++) {
> PCIHostDeviceAddress host;
> VFIOPCIDevice *tmp;
> + VFIODevice *vbasedev_iter;
>
> host.domain = devices[i].segment;
> host.bus = devices[i].bus;
> @@ -3429,7 +3454,11 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
> }
>
> /* Prep dependent devices for reset and clear our marker. */
> - QLIST_FOREACH(tmp, &group->device_list, next) {
> + QLIST_FOREACH(vbasedev_iter, &group->device_list, next) {
> + if (vbasedev_iter->type != VFIO_DEVICE_TYPE_PCI) {
> + continue;
> + }
> + tmp = container_of(vbasedev_iter, VFIOPCIDevice, vbasedev);
> if (vfio_pci_host_match(&host, &tmp->host)) {
> if (single) {
> DPRINTF("vfio: found another in-use device "
> @@ -3439,7 +3468,7 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
> goto out_single;
> }
> vfio_pci_pre_reset(tmp);
> - tmp->needs_reset = false;
> + tmp->vbasedev.needs_reset = false;
> multi = true;
> break;
> }
> @@ -3478,7 +3507,7 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
> }
>
> /* Bus reset! */
> - ret = ioctl(vdev->fd, VFIO_DEVICE_PCI_HOT_RESET, reset);
> + ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_PCI_HOT_RESET, reset);
> g_free(reset);
>
> DPRINTF("%04x:%02x:%02x.%x hot reset: %s\n", vdev->host.domain,
> @@ -3490,6 +3519,7 @@ out:
> for (i = 0; i < info->count; i++) {
> PCIHostDeviceAddress host;
> VFIOPCIDevice *tmp;
> + VFIODevice *vbasedev_iter;
>
> host.domain = devices[i].segment;
> host.bus = devices[i].bus;
> @@ -3510,7 +3540,11 @@ out:
> break;
> }
>
> - QLIST_FOREACH(tmp, &group->device_list, next) {
> + QLIST_FOREACH(vbasedev_iter, &group->device_list, next) {
> + if (vbasedev_iter->type != VFIO_DEVICE_TYPE_PCI) {
> + continue;
> + }
> + tmp = container_of(vbasedev_iter, VFIOPCIDevice, vbasedev);
> if (vfio_pci_host_match(&host, &tmp->host)) {
> vfio_pci_post_reset(tmp);
> break;
> @@ -3544,28 +3578,41 @@ static int vfio_pci_hot_reset_one(VFIOPCIDevice *vdev)
> return vfio_pci_hot_reset(vdev, true);
> }
>
> -static int vfio_pci_hot_reset_multi(VFIOPCIDevice *vdev)
> +static int vfio_pci_hot_reset_multi(VFIODevice *vbasedev)
> {
> + VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev);
> return vfio_pci_hot_reset(vdev, false);
> }
>
> -static void vfio_pci_reset_handler(void *opaque)
> +static bool vfio_pci_compute_needs_reset(VFIODevice *vbasedev)
> +{
> + VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev);
> + if (!vbasedev->reset_works || (!vdev->has_flr && vdev->has_pm_reset)) {
> + vbasedev->needs_reset = true;
> + }
> + return vbasedev->needs_reset;
> +}
> +
> +static VFIODeviceOps vfio_pci_ops = {
> + .vfio_compute_needs_reset = vfio_pci_compute_needs_reset,
> + .vfio_hot_reset_multi = vfio_pci_hot_reset_multi,
> +};
> +
> +static void vfio_reset_handler(void *opaque)
> {
> VFIOGroup *group;
> - VFIOPCIDevice *vdev;
> + VFIODevice *vbasedev;
>
> QLIST_FOREACH(group, &group_list, next) {
> - QLIST_FOREACH(vdev, &group->device_list, next) {
> - if (!vdev->reset_works || (!vdev->has_flr && vdev->has_pm_reset)) {
> - vdev->needs_reset = true;
> - }
> + QLIST_FOREACH(vbasedev, &group->device_list, next) {
> + vbasedev->ops->vfio_compute_needs_reset(vbasedev);
> }
> }
>
> QLIST_FOREACH(group, &group_list, next) {
> - QLIST_FOREACH(vdev, &group->device_list, next) {
> - if (vdev->needs_reset) {
> - vfio_pci_hot_reset_multi(vdev);
> + QLIST_FOREACH(vbasedev, &group->device_list, next) {
> + if (vbasedev->needs_reset) {
> + vbasedev->ops->vfio_hot_reset_multi(vbasedev);
> }
> }
> }
> @@ -3854,7 +3901,7 @@ static VFIOGroup *vfio_get_group(int groupid, AddressSpace *as)
> }
>
> if (QLIST_EMPTY(&group_list)) {
> - qemu_register_reset(vfio_pci_reset_handler, NULL);
> + qemu_register_reset(vfio_reset_handler, NULL);
> }
>
> QLIST_INSERT_HEAD(&group_list, group, next);
> @@ -3886,7 +3933,7 @@ static void vfio_put_group(VFIOGroup *group)
> g_free(group);
>
> if (QLIST_EMPTY(&group_list)) {
> - qemu_unregister_reset(vfio_pci_reset_handler, NULL);
> + qemu_unregister_reset(vfio_reset_handler, NULL);
> }
> }
>
> @@ -3907,12 +3954,12 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
> return ret;
> }
>
> - vdev->fd = ret;
> - vdev->group = group;
> - QLIST_INSERT_HEAD(&group->device_list, vdev, next);
> + vdev->vbasedev.fd = ret;
> + vdev->vbasedev.group = group;
> + QLIST_INSERT_HEAD(&group->device_list, &vdev->vbasedev, next);
>
> /* Sanity check device */
> - ret = ioctl(vdev->fd, VFIO_DEVICE_GET_INFO, &dev_info);
> + ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_INFO, &dev_info);
> if (ret) {
> error_report("vfio: error getting device info: %m");
> goto error;
> @@ -3926,7 +3973,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
> goto error;
> }
>
> - vdev->reset_works = !!(dev_info.flags & VFIO_DEVICE_FLAGS_RESET);
> + vdev->vbasedev.reset_works = !!(dev_info.flags & VFIO_DEVICE_FLAGS_RESET);
>
> if (dev_info.num_regions < VFIO_PCI_CONFIG_REGION_INDEX + 1) {
> error_report("vfio: unexpected number of io regions %u",
> @@ -3942,7 +3989,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
> for (i = VFIO_PCI_BAR0_REGION_INDEX; i < VFIO_PCI_ROM_REGION_INDEX; i++) {
> reg_info.index = i;
>
> - ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, ®_info);
> + ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_REGION_INFO, ®_info);
> if (ret) {
> error_report("vfio: Error getting region %d info: %m", i);
> goto error;
> @@ -3956,14 +4003,14 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
> vdev->bars[i].flags = reg_info.flags;
> vdev->bars[i].size = reg_info.size;
> vdev->bars[i].fd_offset = reg_info.offset;
> - vdev->bars[i].fd = vdev->fd;
> + vdev->bars[i].fd = vdev->vbasedev.fd;
> vdev->bars[i].nr = i;
> QLIST_INIT(&vdev->bars[i].quirks);
> }
>
> reg_info.index = VFIO_PCI_CONFIG_REGION_INDEX;
>
> - ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, ®_info);
> + ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_REGION_INFO, ®_info);
> if (ret) {
> error_report("vfio: Error getting config info: %m");
> goto error;
> @@ -3987,7 +4034,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
> .index = VFIO_PCI_VGA_REGION_INDEX,
> };
>
> - ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, &vga_info);
> + ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_REGION_INFO, &vga_info);
> if (ret) {
> error_report(
> "vfio: Device does not support requested feature x-vga");
> @@ -4004,7 +4051,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
> }
>
> vdev->vga.fd_offset = vga_info.offset;
> - vdev->vga.fd = vdev->fd;
> + vdev->vga.fd = vdev->vbasedev.fd;
>
> vdev->vga.region[QEMU_PCI_VGA_MEM].offset = QEMU_PCI_VGA_MEM_BASE;
> vdev->vga.region[QEMU_PCI_VGA_MEM].nr = QEMU_PCI_VGA_MEM;
> @@ -4022,7 +4069,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
> }
> irq_info.index = VFIO_PCI_ERR_IRQ_INDEX;
>
> - ret = ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info);
> + ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info);
> if (ret) {
> /* This can fail for an old kernel or legacy PCI dev */
> DPRINTF("VFIO_DEVICE_GET_IRQ_INFO failure: %m\n");
> @@ -4038,19 +4085,20 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
>
> error:
> if (ret) {
> - QLIST_REMOVE(vdev, next);
> - vdev->group = NULL;
> - close(vdev->fd);
> + QLIST_REMOVE(&vdev->vbasedev, next);
> + vdev->vbasedev.group = NULL;
> + close(vdev->vbasedev.fd);
> }
> return ret;
> }
>
> static void vfio_put_device(VFIOPCIDevice *vdev)
> {
> - QLIST_REMOVE(vdev, next);
> - vdev->group = NULL;
> + QLIST_REMOVE(&vdev->vbasedev, next);
> + vdev->vbasedev.group = NULL;
> DPRINTF("vfio_put_device: close vdev->fd\n");
> - close(vdev->fd);
> + close(vdev->vbasedev.fd);
> + g_free(vdev->vbasedev.name);
> if (vdev->msix) {
> g_free(vdev->msix);
> vdev->msix = NULL;
> @@ -4119,7 +4167,7 @@ static void vfio_register_err_notifier(VFIOPCIDevice *vdev)
> *pfd = event_notifier_get_fd(&vdev->err_notifier);
> qemu_set_fd_handler(*pfd, vfio_err_notifier_handler, NULL, vdev);
>
> - ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
> + ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set);
> if (ret) {
> error_report("vfio: Failed to set up error notification");
> qemu_set_fd_handler(*pfd, NULL, NULL, vdev);
> @@ -4152,7 +4200,7 @@ static void vfio_unregister_err_notifier(VFIOPCIDevice *vdev)
> pfd = (int32_t *)&irq_set->data;
> *pfd = -1;
>
> - ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
> + ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set);
> if (ret) {
> error_report("vfio: Failed to de-assign error fd: %m");
> }
> @@ -4164,7 +4212,8 @@ static void vfio_unregister_err_notifier(VFIOPCIDevice *vdev)
>
> static int vfio_initfn(PCIDevice *pdev)
> {
> - VFIOPCIDevice *pvdev, *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev);
> + VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev);
> + VFIODevice *vbasedev_iter;
> VFIOGroup *group;
> char path[PATH_MAX], iommu_group_path[PATH_MAX], *group_name;
> ssize_t len;
> @@ -4182,6 +4231,13 @@ static int vfio_initfn(PCIDevice *pdev)
> return -errno;
> }
>
> + vdev->vbasedev.ops = &vfio_pci_ops;
> +
> + vdev->vbasedev.type = VFIO_DEVICE_TYPE_PCI;
> + g_strdup_printf(vdev->vbasedev.name, "%04x:%02x:%02x.%01x",
> + vdev->host.domain, vdev->host.bus, vdev->host.slot,
> + vdev->host.function);
> +
> strncat(path, "iommu_group", sizeof(path) - strlen(path) - 1);
>
> len = readlink(path, iommu_group_path, sizeof(path));
> @@ -4211,12 +4267,8 @@ static int vfio_initfn(PCIDevice *pdev)
> vdev->host.domain, vdev->host.bus, vdev->host.slot,
> vdev->host.function);
>
> - QLIST_FOREACH(pvdev, &group->device_list, next) {
> - if (pvdev->host.domain == vdev->host.domain &&
> - pvdev->host.bus == vdev->host.bus &&
> - pvdev->host.slot == vdev->host.slot &&
> - pvdev->host.function == vdev->host.function) {
> -
> + QLIST_FOREACH(vbasedev_iter, &group->device_list, next) {
> + if (strcmp(vbasedev_iter->name, vdev->vbasedev.name) == 0) {
> error_report("vfio: error: device %s is already attached", path);
> vfio_put_group(group);
> return -EBUSY;
> @@ -4231,7 +4283,7 @@ static int vfio_initfn(PCIDevice *pdev)
> }
>
> /* Get a copy of config space */
> - ret = pread(vdev->fd, vdev->pdev.config,
> + ret = pread(vdev->vbasedev.fd, vdev->pdev.config,
> MIN(pci_config_size(&vdev->pdev), vdev->config_size),
> vdev->config_offset);
> if (ret < (int)MIN(pci_config_size(&vdev->pdev), vdev->config_size)) {
> @@ -4319,7 +4371,7 @@ out_put:
> static void vfio_exitfn(PCIDevice *pdev)
> {
> VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev);
> - VFIOGroup *group = vdev->group;
> + VFIOGroup *group = vdev->vbasedev.group;
>
> vfio_unregister_err_notifier(vdev);
> pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
> @@ -4345,8 +4397,9 @@ static void vfio_pci_reset(DeviceState *dev)
>
> vfio_pci_pre_reset(vdev);
>
> - if (vdev->reset_works && (vdev->has_flr || !vdev->has_pm_reset) &&
> - !ioctl(vdev->fd, VFIO_DEVICE_RESET)) {
> + if (vdev->vbasedev.reset_works &&
> + (vdev->has_flr || !vdev->has_pm_reset) &&
> + !ioctl(vdev->vbasedev.fd, VFIO_DEVICE_RESET)) {
> DPRINTF("%04x:%02x:%02x.%x FLR/VFIO_DEVICE_RESET\n", vdev->host.domain,
> vdev->host.bus, vdev->host.slot, vdev->host.function);
> goto post_reset;
> @@ -4358,8 +4411,8 @@ static void vfio_pci_reset(DeviceState *dev)
> }
>
> /* If nothing else works and the device supports PM reset, use it */
> - if (vdev->reset_works && vdev->has_pm_reset &&
> - !ioctl(vdev->fd, VFIO_DEVICE_RESET)) {
> + if (vdev->vbasedev.reset_works && vdev->has_pm_reset &&
> + !ioctl(vdev->vbasedev.fd, VFIO_DEVICE_RESET)) {
> DPRINTF("%04x:%02x:%02x.%x PCI PM Reset\n", vdev->host.domain,
> vdev->host.bus, vdev->host.slot, vdev->host.function);
> goto post_reset;
> --
> 1.8.3.2
>
>
>
>
> _______________________________________________
> Qemu-devel mailing list
> address@hidden
> https://lists.nongnu.org/mailman/listinfo/qemu-devel
>
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: [Qemu-devel] Qemu-devel Digest, Vol 137, Issue 266,
Fernando Oliveira <=