mirror of
https://github.com/mii443/qemu.git
synced 2025-09-01 14:49:23 +00:00
exec.c: Don't reallocate IOMMUNotifiers that are in use
The tcg_register_iommu_notifier() code has a GArray of TCGIOMMUNotifier structs which it has registered by passing memory_region_register_iommu_notifier() a pointer to the embedded IOMMUNotifier field. Unfortunately, if we need to enlarge the array via g_array_set_size() this can cause a realloc(), which invalidates the pointer that memory_region_register_iommu_notifier() put into the MemoryRegion's iommu_notify list. This can result in segfaults. Switch the GArray to holding pointers to the TCGIOMMUNotifier structs, so that we can individually allocate and free them. Cc: qemu-stable@nongnu.org Fixes:1f871c5e6b
("exec.c: Handle IOMMUs in address_space_translate_for_iotlb()") Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20190128174241.5860-1-peter.maydell@linaro.org (cherry picked from commit5601be3b01
) Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
This commit is contained in:
committed by
Michael Roth
parent
2e5502300e
commit
00d0932e0b
10
exec.c
10
exec.c
@ -664,7 +664,7 @@ static void tcg_register_iommu_notifier(CPUState *cpu,
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < cpu->iommu_notifiers->len; i++) {
|
for (i = 0; i < cpu->iommu_notifiers->len; i++) {
|
||||||
notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
|
notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i);
|
||||||
if (notifier->mr == mr && notifier->iommu_idx == iommu_idx) {
|
if (notifier->mr == mr && notifier->iommu_idx == iommu_idx) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -672,7 +672,8 @@ static void tcg_register_iommu_notifier(CPUState *cpu,
|
|||||||
if (i == cpu->iommu_notifiers->len) {
|
if (i == cpu->iommu_notifiers->len) {
|
||||||
/* Not found, add a new entry at the end of the array */
|
/* Not found, add a new entry at the end of the array */
|
||||||
cpu->iommu_notifiers = g_array_set_size(cpu->iommu_notifiers, i + 1);
|
cpu->iommu_notifiers = g_array_set_size(cpu->iommu_notifiers, i + 1);
|
||||||
notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
|
notifier = g_new0(TCGIOMMUNotifier, 1);
|
||||||
|
g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i) = notifier;
|
||||||
|
|
||||||
notifier->mr = mr;
|
notifier->mr = mr;
|
||||||
notifier->iommu_idx = iommu_idx;
|
notifier->iommu_idx = iommu_idx;
|
||||||
@ -704,8 +705,9 @@ static void tcg_iommu_free_notifier_list(CPUState *cpu)
|
|||||||
TCGIOMMUNotifier *notifier;
|
TCGIOMMUNotifier *notifier;
|
||||||
|
|
||||||
for (i = 0; i < cpu->iommu_notifiers->len; i++) {
|
for (i = 0; i < cpu->iommu_notifiers->len; i++) {
|
||||||
notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
|
notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i);
|
||||||
memory_region_unregister_iommu_notifier(notifier->mr, ¬ifier->n);
|
memory_region_unregister_iommu_notifier(notifier->mr, ¬ifier->n);
|
||||||
|
g_free(notifier);
|
||||||
}
|
}
|
||||||
g_array_free(cpu->iommu_notifiers, true);
|
g_array_free(cpu->iommu_notifiers, true);
|
||||||
}
|
}
|
||||||
@ -975,7 +977,7 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
|
|||||||
vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu);
|
vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier));
|
cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier *));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user