RCU fixes and cleanup (Paolo Bonzini)
Switch to v2 IOMMU interface (Alex Williamson) DEBUG build fix (Alexey Kardashevskiy) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJU2kHCAAoJECObm247sIsiqEgP/j+b8PHknblPJ91t3NoG/S71 cORhqKPZpsWMEDrzpAUNX/EZ6G7RR6ZD7UsV6BQ1FkxXGiPnA6cnrlhm9uhWwiDb GOiYdA9hFBuxZw8Wc1l6HXRWk/xn3hWFnV+JxxVskS0/tC1OvBPkDoTbCsGgKLbG A9S1c981bt7VCDxemo0Z4shTlmpUXtlyFpdqRNj1ATAKPbm2K5jT2ZHLIguJAv6y x9gBfB2swmI56afmpS2cU2j2MPjovJSRrkmvUhjHOMbYMhhs/gvDuwQpVxCNfW+2 w+8NnKxjnOKnCcYvPI+NXziFMpx6FitshYwfCgw8rpmDJvYuweDkXtz08U8I7ECW GuDpRuJayyadG8a/JqnLrG0Ekcw35WCje4OLdbCBwxfpdCn/xFKYGCZTazI1KLAx tt8iKp4N8tHc/Iptw2ZE4Ow7Bw6/73mX/tcm7D5RNjUpktXDT4EIV22Hq5aTM2Kp zuWgizBtQuTgTrMuGPaUG915iyfeemFsOPdzX+z/2Dxl+Cd0qrJhE/aS2wdKB6F7 eMXcRED+tkXuqk+PxiHQv82eUiMrTgmGbkByjUTJo4xS0/9SxUa8F8n1tAfIS0Di X9MZbpajk0udFLpz8BxYaWO4H+1VVYnvPBGwA/7O586UB20ouSeqn6jRBHAHvgGF bDIdLQgBK9wthjj0uxd3 =ol6u -----END PGP SIGNATURE----- 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: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
449008f864
6
exec.c
6
exec.c
@ -2059,11 +2059,15 @@ void address_space_init_dispatch(AddressSpace *as)
|
|||||||
memory_listener_register(&as->dispatch_listener, 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)
|
void address_space_destroy_dispatch(AddressSpace *as)
|
||||||
{
|
{
|
||||||
AddressSpaceDispatch *d = as->dispatch;
|
AddressSpaceDispatch *d = as->dispatch;
|
||||||
|
|
||||||
memory_listener_unregister(&as->dispatch_listener);
|
|
||||||
g_free(d);
|
g_free(d);
|
||||||
as->dispatch = NULL;
|
as->dispatch = NULL;
|
||||||
}
|
}
|
||||||
|
@ -662,7 +662,10 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as)
|
|||||||
container = g_malloc0(sizeof(*container));
|
container = g_malloc0(sizeof(*container));
|
||||||
container->space = space;
|
container->space = space;
|
||||||
container->fd = fd;
|
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);
|
ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
error_report("vfio: failed to set group container: %m");
|
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;
|
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) {
|
if (ret) {
|
||||||
error_report("vfio: failed to set iommu for container: %m");
|
error_report("vfio: failed to set iommu for container: %m");
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
@ -847,7 +851,7 @@ free_group_exit:
|
|||||||
|
|
||||||
void vfio_put_group(VFIOGroup *group)
|
void vfio_put_group(VFIOGroup *group)
|
||||||
{
|
{
|
||||||
if (!QLIST_EMPTY(&group->device_list)) {
|
if (!group || !QLIST_EMPTY(&group->device_list)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -867,27 +871,28 @@ int vfio_get_device(VFIOGroup *group, const char *name,
|
|||||||
VFIODevice *vbasedev)
|
VFIODevice *vbasedev)
|
||||||
{
|
{
|
||||||
struct vfio_device_info dev_info = { .argsz = sizeof(dev_info) };
|
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);
|
fd = ioctl(group->fd, VFIO_GROUP_GET_DEVICE_FD, name);
|
||||||
if (ret < 0) {
|
if (fd < 0) {
|
||||||
error_report("vfio: error getting device %s from group %d: %m",
|
error_report("vfio: error getting device %s from group %d: %m",
|
||||||
name, group->groupid);
|
name, group->groupid);
|
||||||
error_printf("Verify all devices in group %d are bound to vfio-<bus> "
|
error_printf("Verify all devices in group %d are bound to vfio-<bus> "
|
||||||
"or pci-stub and not already in use\n", group->groupid);
|
"or pci-stub and not already in use\n", group->groupid);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ioctl(fd, VFIO_DEVICE_GET_INFO, &dev_info);
|
||||||
|
if (ret) {
|
||||||
|
error_report("vfio: error getting device info: %m");
|
||||||
|
close(fd);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
vbasedev->fd = ret;
|
vbasedev->fd = fd;
|
||||||
vbasedev->group = group;
|
vbasedev->group = group;
|
||||||
QLIST_INSERT_HEAD(&group->device_list, vbasedev, next);
|
QLIST_INSERT_HEAD(&group->device_list, vbasedev, next);
|
||||||
|
|
||||||
ret = ioctl(vbasedev->fd, VFIO_DEVICE_GET_INFO, &dev_info);
|
|
||||||
if (ret) {
|
|
||||||
error_report("vfio: error getting device info: %m");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
vbasedev->num_irqs = dev_info.num_irqs;
|
vbasedev->num_irqs = dev_info.num_irqs;
|
||||||
vbasedev->num_regions = dev_info.num_regions;
|
vbasedev->num_regions = dev_info.num_regions;
|
||||||
vbasedev->flags = dev_info.flags;
|
vbasedev->flags = dev_info.flags;
|
||||||
@ -896,18 +901,14 @@ int vfio_get_device(VFIOGroup *group, const char *name,
|
|||||||
dev_info.num_irqs);
|
dev_info.num_irqs);
|
||||||
|
|
||||||
vbasedev->reset_works = !!(dev_info.flags & VFIO_DEVICE_FLAGS_RESET);
|
vbasedev->reset_works = !!(dev_info.flags & VFIO_DEVICE_FLAGS_RESET);
|
||||||
|
return 0;
|
||||||
ret = vbasedev->ops->vfio_populate_device(vbasedev);
|
|
||||||
|
|
||||||
error:
|
|
||||||
if (ret) {
|
|
||||||
vfio_put_base_device(vbasedev);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vfio_put_base_device(VFIODevice *vbasedev)
|
void vfio_put_base_device(VFIODevice *vbasedev)
|
||||||
{
|
{
|
||||||
|
if (!vbasedev->group) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
QLIST_REMOVE(vbasedev, next);
|
QLIST_REMOVE(vbasedev, next);
|
||||||
vbasedev->group = NULL;
|
vbasedev->group = NULL;
|
||||||
trace_vfio_put_base_device(vbasedev->fd);
|
trace_vfio_put_base_device(vbasedev->fd);
|
||||||
|
@ -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,
|
static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
|
||||||
uint32_t val, int len);
|
uint32_t val, int len);
|
||||||
static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev, bool enabled);
|
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
|
* Disabling BAR mmaping can be slow, but toggling it around INTx can
|
||||||
@ -517,7 +516,7 @@ static void vfio_msi_interrupt(void *opaque)
|
|||||||
abort();
|
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
|
#endif
|
||||||
|
|
||||||
if (vdev->interrupt == VFIO_INT_MSIX) {
|
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)
|
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;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(vdev->vga.region); i++) {
|
for (i = 0; i < ARRAY_SIZE(vdev->vga.region); i++) {
|
||||||
while (!QLIST_EMPTY(&vdev->vga.region[i].quirks)) {
|
while (!QLIST_EMPTY(&vdev->vga.region[i].quirks)) {
|
||||||
VFIOQuirk *quirk = QLIST_FIRST(&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));
|
object_unparent(OBJECT(&quirk->mem));
|
||||||
QLIST_REMOVE(quirk, next);
|
QLIST_REMOVE(quirk, next);
|
||||||
g_free(quirk);
|
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)
|
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];
|
VFIOBAR *bar = &vdev->bars[nr];
|
||||||
|
|
||||||
while (!QLIST_EMPTY(&bar->quirks)) {
|
while (!QLIST_EMPTY(&bar->quirks)) {
|
||||||
VFIOQuirk *quirk = QLIST_FIRST(&bar->quirks);
|
VFIOQuirk *quirk = QLIST_FIRST(&bar->quirks);
|
||||||
memory_region_del_subregion(&bar->region.mem, &quirk->mem);
|
|
||||||
object_unparent(OBJECT(&quirk->mem));
|
object_unparent(OBJECT(&quirk->mem));
|
||||||
QLIST_REMOVE(quirk, next);
|
QLIST_REMOVE(quirk, next);
|
||||||
g_free(quirk);
|
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];
|
VFIOBAR *bar = &vdev->bars[nr];
|
||||||
|
|
||||||
@ -2293,10 +2312,25 @@ static void vfio_unmap_bar(VFIOPCIDevice *vdev, int nr)
|
|||||||
vfio_bar_quirk_teardown(vdev, nr);
|
vfio_bar_quirk_teardown(vdev, nr);
|
||||||
|
|
||||||
memory_region_del_subregion(&bar->region.mem, &bar->region.mmap_mem);
|
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) {
|
if (vdev->msix && vdev->msix->table_bar == nr) {
|
||||||
memory_region_del_subregion(&bar->region.mem, &vdev->msix->mmap_mem);
|
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));
|
munmap(vdev->msix->mmap, memory_region_size(&vdev->msix->mmap_mem));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2404,6 +2438,20 @@ static void vfio_map_bars(VFIOPCIDevice *vdev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vfio_unregister_bars(VFIOPCIDevice *vdev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < PCI_ROM_SLOT; i++) {
|
||||||
|
vfio_unregister_bar(vdev, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vdev->has_vga) {
|
||||||
|
vfio_vga_quirk_teardown(vdev);
|
||||||
|
pci_unregister_vga(&vdev->pdev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void vfio_unmap_bars(VFIOPCIDevice *vdev)
|
static void vfio_unmap_bars(VFIOPCIDevice *vdev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -2413,8 +2461,7 @@ static void vfio_unmap_bars(VFIOPCIDevice *vdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (vdev->has_vga) {
|
if (vdev->has_vga) {
|
||||||
vfio_vga_quirk_teardown(vdev);
|
vfio_vga_quirk_free(vdev);
|
||||||
pci_unregister_vga(&vdev->pdev);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2934,12 +2981,11 @@ static VFIODeviceOps vfio_pci_ops = {
|
|||||||
.vfio_compute_needs_reset = vfio_pci_compute_needs_reset,
|
.vfio_compute_needs_reset = vfio_pci_compute_needs_reset,
|
||||||
.vfio_hot_reset_multi = vfio_pci_hot_reset_multi,
|
.vfio_hot_reset_multi = vfio_pci_hot_reset_multi,
|
||||||
.vfio_eoi = vfio_eoi,
|
.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_region_info reg_info = { .argsz = sizeof(reg_info) };
|
||||||
struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info) };
|
struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info) };
|
||||||
int i, ret = -1;
|
int i, ret = -1;
|
||||||
@ -3248,6 +3294,11 @@ static int vfio_initfn(PCIDevice *pdev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = vfio_populate_device(vdev);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get a copy of config space */
|
/* Get a copy of config space */
|
||||||
ret = pread(vdev->vbasedev.fd, vdev->pdev.config,
|
ret = pread(vdev->vbasedev.fd, vdev->pdev.config,
|
||||||
MIN(pci_config_size(&vdev->pdev), vdev->config_size),
|
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)) {
|
if (ret < (int)MIN(pci_config_size(&vdev->pdev), vdev->config_size)) {
|
||||||
ret = ret < 0 ? -errno : -EFAULT;
|
ret = ret < 0 ? -errno : -EFAULT;
|
||||||
error_report("vfio: Failed to read device config space");
|
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 */
|
/* 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);
|
ret = vfio_early_setup_msix(vdev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
goto out_put;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
vfio_map_bars(vdev);
|
vfio_map_bars(vdev);
|
||||||
@ -3325,18 +3376,26 @@ static int vfio_initfn(PCIDevice *pdev)
|
|||||||
out_teardown:
|
out_teardown:
|
||||||
pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
|
pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
|
||||||
vfio_teardown_msi(vdev);
|
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);
|
vfio_unmap_bars(vdev);
|
||||||
out_put:
|
|
||||||
g_free(vdev->emulated_config_bits);
|
g_free(vdev->emulated_config_bits);
|
||||||
|
g_free(vdev->rom);
|
||||||
vfio_put_device(vdev);
|
vfio_put_device(vdev);
|
||||||
vfio_put_group(group);
|
vfio_put_group(group);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vfio_exitfn(PCIDevice *pdev)
|
static void vfio_exitfn(PCIDevice *pdev)
|
||||||
{
|
{
|
||||||
VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev);
|
VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev);
|
||||||
VFIOGroup *group = vdev->vbasedev.group;
|
|
||||||
|
|
||||||
vfio_unregister_err_notifier(vdev);
|
vfio_unregister_err_notifier(vdev);
|
||||||
pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
|
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);
|
timer_free(vdev->intx.mmap_timer);
|
||||||
}
|
}
|
||||||
vfio_teardown_msi(vdev);
|
vfio_teardown_msi(vdev);
|
||||||
vfio_unmap_bars(vdev);
|
vfio_unregister_bars(vdev);
|
||||||
g_free(vdev->emulated_config_bits);
|
|
||||||
g_free(vdev->rom);
|
|
||||||
vfio_put_device(vdev);
|
|
||||||
vfio_put_group(group);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vfio_pci_reset(DeviceState *dev)
|
static void vfio_pci_reset(DeviceState *dev)
|
||||||
@ -3437,6 +3492,7 @@ static const TypeInfo vfio_pci_dev_info = {
|
|||||||
.instance_size = sizeof(VFIOPCIDevice),
|
.instance_size = sizeof(VFIOPCIDevice),
|
||||||
.class_init = vfio_pci_dev_class_init,
|
.class_init = vfio_pci_dev_class_init,
|
||||||
.instance_init = vfio_instance_init,
|
.instance_init = vfio_instance_init,
|
||||||
|
.instance_finalize = vfio_instance_finalize,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void register_vfio_pci_dev_type(void)
|
static void register_vfio_pci_dev_type(void)
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
typedef struct AddressSpaceDispatch AddressSpaceDispatch;
|
typedef struct AddressSpaceDispatch AddressSpaceDispatch;
|
||||||
|
|
||||||
void address_space_init_dispatch(AddressSpace *as);
|
void address_space_init_dispatch(AddressSpace *as);
|
||||||
|
void address_space_unregister(AddressSpace *as);
|
||||||
void address_space_destroy_dispatch(AddressSpace *as);
|
void address_space_destroy_dispatch(AddressSpace *as);
|
||||||
|
|
||||||
extern const MemoryRegionOps unassigned_mem_ops;
|
extern const MemoryRegionOps unassigned_mem_ops;
|
||||||
|
@ -112,7 +112,6 @@ struct VFIODeviceOps {
|
|||||||
void (*vfio_compute_needs_reset)(VFIODevice *vdev);
|
void (*vfio_compute_needs_reset)(VFIODevice *vdev);
|
||||||
int (*vfio_hot_reset_multi)(VFIODevice *vdev);
|
int (*vfio_hot_reset_multi)(VFIODevice *vdev);
|
||||||
void (*vfio_eoi)(VFIODevice *vdev);
|
void (*vfio_eoi)(VFIODevice *vdev);
|
||||||
int (*vfio_populate_device)(VFIODevice *vdev);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct VFIOGroup {
|
typedef struct VFIOGroup {
|
||||||
|
1
memory.c
1
memory.c
@ -1978,6 +1978,7 @@ void address_space_destroy(AddressSpace *as)
|
|||||||
as->root = NULL;
|
as->root = NULL;
|
||||||
memory_region_transaction_commit();
|
memory_region_transaction_commit();
|
||||||
QTAILQ_REMOVE(&address_spaces, as, address_spaces_link);
|
QTAILQ_REMOVE(&address_spaces, as, address_spaces_link);
|
||||||
|
address_space_unregister(as);
|
||||||
|
|
||||||
/* At this point, as->dispatch and as->current_map are dummy
|
/* At this point, as->dispatch and as->current_map are dummy
|
||||||
* entries that the guest should never use. Wait for the old
|
* entries that the guest should never use. Wait for the old
|
||||||
|
Loading…
Reference in New Issue
Block a user