Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/awilliam/tags/vfio-update-20150…
Browse files Browse the repository at this point in the history
…210.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 <[email protected]>"
# gpg:                 aka "Alex Williamson <[email protected]>"
# gpg:                 aka "Alex Williamson <[email protected]>"
# gpg:                 aka "Alex Williamson <[email protected]>"

* 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: Peter Maydell <[email protected]>
  • Loading branch information
pm215 committed Feb 11, 2015
2 parents 5c697ae + bc5baff commit 449008f
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 44 deletions.
6 changes: 5 additions & 1 deletion exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
43 changes: 22 additions & 21 deletions hw/vfio/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,15 +662,19 @@ 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");
ret = -errno;
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;
Expand Down Expand Up @@ -847,7 +851,7 @@ VFIOGroup *vfio_get_group(int groupid, AddressSpace *as)

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

Expand All @@ -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;
Expand All @@ -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);
Expand Down
98 changes: 77 additions & 21 deletions hw/vfio/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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];

Expand All @@ -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));
}
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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
*/
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -3248,14 +3294,19 @@ 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),
vdev->config_offset);
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 */
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions include/exec/memory-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion include/hw/vfio/vfio-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -1978,6 +1978,7 @@ void address_space_destroy(AddressSpace *as)
as->root = NULL;
memory_region_transaction_commit();
QTAILQ_REMOVE(&address_spaces, as, address_spaces_link);
address_space_unregister(as);

/* At this point, as->dispatch and as->current_map are dummy
* entries that the guest should never use. Wait for the old
Expand Down

0 comments on commit 449008f

Please sign in to comment.