# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1216203408 -3600
# Node ID 3fe6df9afd5d42e655f0fa9ff009372fd8efa84d
# Parent cec304746b360d0fccb2ab3944787bfb912902cb
ioemu: Fix issues when passthrough device is hot-removed from HVM domain.
When passthrough device is hot removed from HVM domain by "xm
pci-detach" command, following issues occur. The patch fixes them.
- Allocated memory is not deallocated.
- Unbind interrupt with invalid interrupt pin.
- MSI-X memory mapped register area is not unmapped.
Signed-off-by: Yuji Shimada <shimada-yxb@xxxxxxxxxxxxxxx>
---
tools/ioemu/hw/pass-through.c | 33 ++++++++++++++++++++++++++++++++-
tools/ioemu/hw/pt-msi.c | 13 +++++++++++++
tools/ioemu/hw/pt-msi.h | 3 +++
3 files changed, 48 insertions(+), 1 deletion(-)
diff -r cec304746b36 -r 3fe6df9afd5d tools/ioemu/hw/pass-through.c
--- a/tools/ioemu/hw/pass-through.c Wed Jul 16 11:15:14 2008 +0100
+++ b/tools/ioemu/hw/pass-through.c Wed Jul 16 11:16:48 2008 +0100
@@ -1686,6 +1686,33 @@ out:
return err;
}
+/* delete all emulate register */
+static void pt_config_delete(struct pt_dev *ptdev)
+{
+ struct pt_reg_grp_tbl *reg_grp_entry = NULL;
+ struct pt_reg_tbl *reg_entry = NULL;
+
+ /* free MSI/MSI-X info table */
+ if (ptdev->msix)
+ pt_msix_delete(ptdev);
+ if (ptdev->msi)
+ free(ptdev->msi);
+
+ /* free all register group entry */
+ while ((reg_grp_entry = ptdev->reg_grp_tbl_head.lh_first) != NULL)
+ {
+ /* free all register entry */
+ while ((reg_entry = reg_grp_entry->reg_tbl_head.lh_first) != NULL)
+ {
+ QEMU_LIST_REMOVE(reg_entry, entries);
+ qemu_free(reg_entry);
+ }
+
+ QEMU_LIST_REMOVE(reg_grp_entry, entries);
+ qemu_free(reg_grp_entry);
+ }
+}
+
/* initialize common register value */
static uint32_t pt_common_reg_init(struct pt_dev *ptdev,
struct pt_reg_info_tbl *reg, uint32_t real_offset)
@@ -2821,7 +2848,8 @@ int unregister_real_device(int php_slot)
/* Unbind interrupt */
e_device = (assigned_device->dev.devfn >> 3) & 0x1f;
- e_intx = assigned_device->dev.config[0x3d]-1;
+ /* fix virtual interrupt pin to INTA# */
+ e_intx = 0;
machine_irq = pci_dev->irq;
if ( machine_irq != 0 ) {
@@ -2833,6 +2861,9 @@ int unregister_real_device(int php_slot)
PT_LOG("Error: Unbinding of interrupt failed! rc=%d\n", rc);
}
}
+
+ /* delete all emulated config registers */
+ pt_config_delete(assigned_device);
/* unregister real device's MMIO/PIO BARs */
pt_unregister_regions(assigned_device);
diff -r cec304746b36 -r 3fe6df9afd5d tools/ioemu/hw/pt-msi.c
--- a/tools/ioemu/hw/pt-msi.c Wed Jul 16 11:15:14 2008 +0100
+++ b/tools/ioemu/hw/pt-msi.c Wed Jul 16 11:16:48 2008 +0100
@@ -332,3 +332,16 @@ int pt_msix_init(struct pt_dev *dev, int
(unsigned long)dev->msix->phys_iomem_base);
return 0;
}
+
+void pt_msix_delete(struct pt_dev *dev)
+{
+ /* unmap the MSI-X memory mapped register area */
+ if (dev->msix->phys_iomem_base)
+ {
+ PT_LOG("unmapping physical MSI-X table from %lx\n",
+ (unsigned long)dev->msix->phys_iomem_base);
+ munmap(dev->msix->phys_iomem_base, dev->msix->total_entries * 16);
+ }
+
+ free(dev->msix);
+}
diff -r cec304746b36 -r 3fe6df9afd5d tools/ioemu/hw/pt-msi.h
--- a/tools/ioemu/hw/pt-msi.h Wed Jul 16 11:15:14 2008 +0100
+++ b/tools/ioemu/hw/pt-msi.h Wed Jul 16 11:16:48 2008 +0100
@@ -94,4 +94,7 @@ int
int
pt_msix_init(struct pt_dev *dev, int pos);
+void
+pt_msix_delete(struct pt_dev *dev);
+
#endif
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|