Commit 449008f8 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/awilliam/tags/vfio-update-20150210.0' into staging



RCU fixes and cleanup (Paolo Bonzini)
Switch to v2 IOMMU interface (Alex Williamson)
DEBUG build fix (Alexey Kardashevskiy)

# gpg: Signature made Tue 10 Feb 2015 17:37:06 GMT using RSA key ID 3BB08B22
# gpg: Good signature from "Alex Williamson <alex.williamson@redhat.com>"
# gpg:                 aka "Alex Williamson <alex@shazbot.org>"
# gpg:                 aka "Alex Williamson <alwillia@redhat.com>"
# gpg:                 aka "Alex Williamson <alex.l.williamson@gmail.com>"

* remotes/awilliam/tags/vfio-update-20150210.0:
  vfio: Fix debug message compile error
  vfio: Use vfio type1 v2 IOMMU interface
  vfio: unmap and free BAR data in instance_finalize
  vfio: free dynamically-allocated data in instance_finalize
  vfio: cleanup vfio_get_device error path, remove vfio_populate_device callback
  memory: unregister AddressSpace MemoryListener within BQL

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 5c697ae7 bc5baffa
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -2059,11 +2059,15 @@ void address_space_init_dispatch(AddressSpace *as)
    memory_listener_register(&as->dispatch_listener, as);
}

void address_space_unregister(AddressSpace *as)
{
    memory_listener_unregister(&as->dispatch_listener);
}

void address_space_destroy_dispatch(AddressSpace *as)
{
    AddressSpaceDispatch *d = as->dispatch;

    memory_listener_unregister(&as->dispatch_listener);
    g_free(d);
    as->dispatch = NULL;
}
+22 −21
Original line number Diff line number Diff line
@@ -662,7 +662,10 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as)
    container = g_malloc0(sizeof(*container));
    container->space = space;
    container->fd = fd;
    if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU)) {
    if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU) ||
        ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU)) {
        bool v2 = !!ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU);

        ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd);
        if (ret) {
            error_report("vfio: failed to set group container: %m");
@@ -670,7 +673,8 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as)
            goto free_container_exit;
        }

        ret = ioctl(fd, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU);
        ret = ioctl(fd, VFIO_SET_IOMMU,
                    v2 ? VFIO_TYPE1v2_IOMMU : VFIO_TYPE1_IOMMU);
        if (ret) {
            error_report("vfio: failed to set iommu for container: %m");
            ret = -errno;
@@ -847,7 +851,7 @@ free_group_exit:

void vfio_put_group(VFIOGroup *group)
{
    if (!QLIST_EMPTY(&group->device_list)) {
    if (!group || !QLIST_EMPTY(&group->device_list)) {
        return;
    }

@@ -867,27 +871,28 @@ int vfio_get_device(VFIOGroup *group, const char *name,
                       VFIODevice *vbasedev)
{
    struct vfio_device_info dev_info = { .argsz = sizeof(dev_info) };
    int ret;
    int ret, fd;

    ret = ioctl(group->fd, VFIO_GROUP_GET_DEVICE_FD, name);
    if (ret < 0) {
    fd = ioctl(group->fd, VFIO_GROUP_GET_DEVICE_FD, name);
    if (fd < 0) {
        error_report("vfio: error getting device %s from group %d: %m",
                     name, group->groupid);
        error_printf("Verify all devices in group %d are bound to vfio-<bus> "
                     "or pci-stub and not already in use\n", group->groupid);
        return ret;
        return fd;
    }

    vbasedev->fd = ret;
    vbasedev->group = group;
    QLIST_INSERT_HEAD(&group->device_list, vbasedev, next);

    ret = ioctl(vbasedev->fd, VFIO_DEVICE_GET_INFO, &dev_info);
    ret = ioctl(fd, VFIO_DEVICE_GET_INFO, &dev_info);
    if (ret) {
        error_report("vfio: error getting device info: %m");
        goto error;
        close(fd);
        return ret;
    }

    vbasedev->fd = fd;
    vbasedev->group = group;
    QLIST_INSERT_HEAD(&group->device_list, vbasedev, next);

    vbasedev->num_irqs = dev_info.num_irqs;
    vbasedev->num_regions = dev_info.num_regions;
    vbasedev->flags = dev_info.flags;
@@ -896,18 +901,14 @@ int vfio_get_device(VFIOGroup *group, const char *name,
                          dev_info.num_irqs);

    vbasedev->reset_works = !!(dev_info.flags & VFIO_DEVICE_FLAGS_RESET);

    ret = vbasedev->ops->vfio_populate_device(vbasedev);

error:
    if (ret) {
        vfio_put_base_device(vbasedev);
    }
    return ret;
    return 0;
}

void vfio_put_base_device(VFIODevice *vbasedev)
{
    if (!vbasedev->group) {
        return;
    }
    QLIST_REMOVE(vbasedev, next);
    vbasedev->group = NULL;
    trace_vfio_put_base_device(vbasedev->fd);
+77 −21
Original line number Diff line number Diff line
@@ -195,7 +195,6 @@ 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);
static int vfio_populate_device(VFIODevice *vbasedev);

/*
 * Disabling BAR mmaping can be slow, but toggling it around INTx can
@@ -517,7 +516,7 @@ static void vfio_msi_interrupt(void *opaque)
        abort();
    }

    trace_vfio_msi_interrupt(vbasedev->name, nr, msg.address, msg.data);
    trace_vfio_msi_interrupt(vdev->vbasedev.name, nr, msg.address, msg.data);
#endif

    if (vdev->interrupt == VFIO_INT_MSIX) {
@@ -1996,13 +1995,24 @@ static void vfio_vga_quirk_setup(VFIOPCIDevice *vdev)
}

static void vfio_vga_quirk_teardown(VFIOPCIDevice *vdev)
{
    VFIOQuirk *quirk;
    int i;

    for (i = 0; i < ARRAY_SIZE(vdev->vga.region); i++) {
        QLIST_FOREACH(quirk, &vdev->vga.region[i].quirks, next) {
            memory_region_del_subregion(&vdev->vga.region[i].mem, &quirk->mem);
        }
    }
}

static void vfio_vga_quirk_free(VFIOPCIDevice *vdev)
{
    int i;

    for (i = 0; i < ARRAY_SIZE(vdev->vga.region); i++) {
        while (!QLIST_EMPTY(&vdev->vga.region[i].quirks)) {
            VFIOQuirk *quirk = QLIST_FIRST(&vdev->vga.region[i].quirks);
            memory_region_del_subregion(&vdev->vga.region[i].mem, &quirk->mem);
            object_unparent(OBJECT(&quirk->mem));
            QLIST_REMOVE(quirk, next);
            g_free(quirk);
@@ -2021,12 +2031,21 @@ static void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr)
}

static void vfio_bar_quirk_teardown(VFIOPCIDevice *vdev, int nr)
{
    VFIOBAR *bar = &vdev->bars[nr];
    VFIOQuirk *quirk;

    QLIST_FOREACH(quirk, &bar->quirks, next) {
        memory_region_del_subregion(&bar->region.mem, &quirk->mem);
    }
}

static void vfio_bar_quirk_free(VFIOPCIDevice *vdev, int nr)
{
    VFIOBAR *bar = &vdev->bars[nr];

    while (!QLIST_EMPTY(&bar->quirks)) {
        VFIOQuirk *quirk = QLIST_FIRST(&bar->quirks);
        memory_region_del_subregion(&bar->region.mem, &quirk->mem);
        object_unparent(OBJECT(&quirk->mem));
        QLIST_REMOVE(quirk, next);
        g_free(quirk);
@@ -2282,7 +2301,7 @@ static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev, bool enabled)
    }
}

static void vfio_unmap_bar(VFIOPCIDevice *vdev, int nr)
static void vfio_unregister_bar(VFIOPCIDevice *vdev, int nr)
{
    VFIOBAR *bar = &vdev->bars[nr];

@@ -2293,10 +2312,25 @@ static void vfio_unmap_bar(VFIOPCIDevice *vdev, int nr)
    vfio_bar_quirk_teardown(vdev, nr);

    memory_region_del_subregion(&bar->region.mem, &bar->region.mmap_mem);
    munmap(bar->region.mmap, memory_region_size(&bar->region.mmap_mem));

    if (vdev->msix && vdev->msix->table_bar == nr) {
        memory_region_del_subregion(&bar->region.mem, &vdev->msix->mmap_mem);
    }
}

static void vfio_unmap_bar(VFIOPCIDevice *vdev, int nr)
{
    VFIOBAR *bar = &vdev->bars[nr];

    if (!bar->region.size) {
        return;
    }

    vfio_bar_quirk_free(vdev, nr);

    munmap(bar->region.mmap, memory_region_size(&bar->region.mmap_mem));

    if (vdev->msix && vdev->msix->table_bar == nr) {
        munmap(vdev->msix->mmap, memory_region_size(&vdev->msix->mmap_mem));
    }
}
@@ -2404,12 +2438,12 @@ static void vfio_map_bars(VFIOPCIDevice *vdev)
    }
}

static void vfio_unmap_bars(VFIOPCIDevice *vdev)
static void vfio_unregister_bars(VFIOPCIDevice *vdev)
{
    int i;

    for (i = 0; i < PCI_ROM_SLOT; i++) {
        vfio_unmap_bar(vdev, i);
        vfio_unregister_bar(vdev, i);
    }

    if (vdev->has_vga) {
@@ -2418,6 +2452,19 @@ static void vfio_unmap_bars(VFIOPCIDevice *vdev)
    }
}

static void vfio_unmap_bars(VFIOPCIDevice *vdev)
{
    int i;

    for (i = 0; i < PCI_ROM_SLOT; i++) {
        vfio_unmap_bar(vdev, i);
    }

    if (vdev->has_vga) {
        vfio_vga_quirk_free(vdev);
    }
}

/*
 * General setup
 */
@@ -2934,12 +2981,11 @@ static VFIODeviceOps vfio_pci_ops = {
    .vfio_compute_needs_reset = vfio_pci_compute_needs_reset,
    .vfio_hot_reset_multi = vfio_pci_hot_reset_multi,
    .vfio_eoi = vfio_eoi,
    .vfio_populate_device = vfio_populate_device,
};

static int vfio_populate_device(VFIODevice *vbasedev)
static int vfio_populate_device(VFIOPCIDevice *vdev)
{
    VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev);
    VFIODevice *vbasedev = &vdev->vbasedev;
    struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) };
    struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info) };
    int i, ret = -1;
@@ -3248,6 +3294,11 @@ static int vfio_initfn(PCIDevice *pdev)
        return ret;
    }

    ret = vfio_populate_device(vdev);
    if (ret) {
        return ret;
    }

    /* Get a copy of config space */
    ret = pread(vdev->vbasedev.fd, vdev->pdev.config,
                MIN(pci_config_size(&vdev->pdev), vdev->config_size),
@@ -3255,7 +3306,7 @@ static int vfio_initfn(PCIDevice *pdev)
    if (ret < (int)MIN(pci_config_size(&vdev->pdev), vdev->config_size)) {
        ret = ret < 0 ? -errno : -EFAULT;
        error_report("vfio: Failed to read device config space");
        goto out_put;
        return ret;
    }

    /* vfio emulates a lot for us, but some bits need extra love */
@@ -3287,7 +3338,7 @@ static int vfio_initfn(PCIDevice *pdev)

    ret = vfio_early_setup_msix(vdev);
    if (ret) {
        goto out_put;
        return ret;
    }

    vfio_map_bars(vdev);
@@ -3325,18 +3376,26 @@ static int vfio_initfn(PCIDevice *pdev)
out_teardown:
    pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
    vfio_teardown_msi(vdev);
    vfio_unregister_bars(vdev);
    return ret;
}

static void vfio_instance_finalize(Object *obj)
{
    PCIDevice *pci_dev = PCI_DEVICE(obj);
    VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pci_dev);
    VFIOGroup *group = vdev->vbasedev.group;

    vfio_unmap_bars(vdev);
out_put:
    g_free(vdev->emulated_config_bits);
    g_free(vdev->rom);
    vfio_put_device(vdev);
    vfio_put_group(group);
    return ret;
}

static void vfio_exitfn(PCIDevice *pdev)
{
    VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev);
    VFIOGroup *group = vdev->vbasedev.group;

    vfio_unregister_err_notifier(vdev);
    pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
@@ -3345,11 +3404,7 @@ static void vfio_exitfn(PCIDevice *pdev)
        timer_free(vdev->intx.mmap_timer);
    }
    vfio_teardown_msi(vdev);
    vfio_unmap_bars(vdev);
    g_free(vdev->emulated_config_bits);
    g_free(vdev->rom);
    vfio_put_device(vdev);
    vfio_put_group(group);
    vfio_unregister_bars(vdev);
}

static void vfio_pci_reset(DeviceState *dev)
@@ -3437,6 +3492,7 @@ static const TypeInfo vfio_pci_dev_info = {
    .instance_size = sizeof(VFIOPCIDevice),
    .class_init = vfio_pci_dev_class_init,
    .instance_init = vfio_instance_init,
    .instance_finalize = vfio_instance_finalize,
};

static void register_vfio_pci_dev_type(void)
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
typedef struct AddressSpaceDispatch AddressSpaceDispatch;

void address_space_init_dispatch(AddressSpace *as);
void address_space_unregister(AddressSpace *as);
void address_space_destroy_dispatch(AddressSpace *as);

extern const MemoryRegionOps unassigned_mem_ops;
+0 −1
Original line number Diff line number Diff line
@@ -112,7 +112,6 @@ struct VFIODeviceOps {
    void (*vfio_compute_needs_reset)(VFIODevice *vdev);
    int (*vfio_hot_reset_multi)(VFIODevice *vdev);
    void (*vfio_eoi)(VFIODevice *vdev);
    int (*vfio_populate_device)(VFIODevice *vdev);
};

typedef struct VFIOGroup {
Loading