fix segmentation fault after hotplug pass-through device
PATCH 1/1 fix segmentation fault after hotplug pass-through device
This patch fixed the QEMU segmentation fault after hotplug pass-through devices with MSI-X for many times.
There is a wrong boundary check in cpu_register_io_memory that uses io_index rather than io_mem_nb. After many times of hotplug of MSI-X pass-through device, io_mem_read[] got extended to overwrite mmio_cnt, then cause QEMU segmentation fault.
This fix sync with upstream QEMU code in exec.c, and free unused io_mem_XXX element after hot removal.
tools/ioemu-remote/hw/pt-msi.c +6 -0
@@ -623,5 +623,11 @@ void pt_msix_delete(struct pt_dev *dev) dev->msix->table_offset_adjust); } +if (dev->msix->mmio_index >0 ) + { +cpu_unregister_io_memory (dev->msix->mmio_index); + } + +free (dev->msix);
}
tools/ioemu-remote/i386-dm/exec-dm.c +0 -0
@@ -125,7 +125,7 @@ unsigned long qemu_host_page_mask;
CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4]; CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; void *io_mem_opaque[IO_MEM_NB_ENTRIES]; -static int io_mem_nb = 1;
+char io_mem_used[IO_MEM_NB_ENTRIES];
/* log support */
FILE *logfile;
@@ -310,6 +310,20 @@ void cpu_register_physical_memory(target
mmio[mmio_cnt++].size = size; }
+static int get_free_io_mem_idx(void)
+{
+ int i;
+
+ /* Leave 1st element empty */
+ for (i = 1; i<IO_MEM_NB_ENTRIES; i++)
+ if (!io_mem_used[i]) {
+ io_mem_used[i] = 1;
+ return i;
+ }
+
+ return -1;
+}
+
/* mem_read and mem_write are arrays of functions containing the
function to access byte (index 0), word (index 1) and dword (index 2). All functions must be supplied. If io_index is non zero, the
@@ -324,9 +338,9 @@ int cpu_register_io_memory(int io_index,
int i;
if (io_index <= 0) {
- if (io_index >= IO_MEM_NB_ENTRIES)
- return -1;
- io_index = io_mem_nb++;
+ io_index = get_free_io_mem_idx();
+ if (io_index == -1)
+ return io_index;
} else {
if (io_index >= IO_MEM_NB_ENTRIES)
return -1;
@@ -357,6 +371,7 @@ void cpu_unregister_io_memory(int io_tab
io_mem_write[io_index][i] = NULL;
}
io_mem_opaque[io_index] = NULL;+ io_mem_used[io_index] = 0;
}
void cpu_physical_memory_set_dirty(ram_addr_t addr)
Signature · 2 lines
best rgds, edwin
tools/ioemu-remote/hw/pt-msi.c +6 -0
@@ -623,5 +623,11 @@ void pt_msix_delete(struct pt_dev *dev) dev->msix->table_offset_adjust); } +if (dev->msix->mmio_index >0 ) + { +cpu_unregister_io_memory (dev->msix->mmio_index); + } + +free (dev->msix); }
tools/ioemu-remote/i386-dm/exec-dm.c +19 -4
@@ -125,7 +125,7 @@ unsigned long qemu_host_page_mask;CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES ][4 ];CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES ][4 ];void *io_mem_opaque[IO_MEM_NB_ENTRIES ]; -static int io_mem_nb =1 ; +char io_mem_used[IO_MEM_NB_ENTRIES ];/* log support */ FILE *logfile;
@@ -310,6 +310,20 @@ void cpu_register_physical_memory(target mmio[mmio_cnt++].size = size; } +static int get_free_io_mem_idx (void ) +{ +int i; + +/* Leave 1st element empty */ +for (i =1 ; i<IO_MEM_NB_ENTRIES ; i++) +if (!io_mem_used[i]) { + io_mem_used[i] =1 ; +return i; + } + +return -1 ; +} +/* mem_read and mem_write are arrays of functions containing the function to access byte (index 0), word (index 1) and dword (index 2). All functions must be supplied. If io_index is non zero, the
@@ -324,9 +338,9 @@ int cpu_register_io_memory(int io_index,int i;if (io_index <=0 ) { -if (io_index >=IO_MEM_NB_ENTRIES ) -return -1 ; - io_index = io_mem_nb++; + io_index =get_free_io_mem_idx (); +if (io_index ==-1 ) +return io_index; }else {if (io_index >=IO_MEM_NB_ENTRIES )return -1 ;
@@ -357,6 +371,7 @@ void cpu_unregister_io_memory(int io_tab io_mem_write[io_index][i] =NULL ; } io_mem_opaque[io_index] =NULL ; + io_mem_used[io_index] =0 ; }void cpu_physical_memory_set_dirty (ram_addr_t addr)
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel