spapr/xive: Add proper rollback to kvmppc_xive_connect()

Make kvmppc_xive_disconnect() able to undo the changes of a partial
execution of kvmppc_xive_connect() and use it to perform rollback.

Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Message-Id: <156198735673.293938.7313195993600841641.stgit@bahia>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
Greg Kurz 2019-07-01 15:22:36 +02:00 committed by David Gibson
parent aaa450300e
commit 1c3d4a8f4b
1 changed files with 29 additions and 19 deletions

View File

@ -724,8 +724,7 @@ void kvmppc_xive_connect(SpaprXive *xive, Error **errp)
xsrc->esb_mmap = kvmppc_xive_mmap(xive, KVM_XIVE_ESB_PAGE_OFFSET, esb_len,
&local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
goto fail;
}
memory_region_init_ram_device_ptr(&xsrc->esb_mmio_kvm, OBJECT(xsrc),
@ -743,8 +742,7 @@ void kvmppc_xive_connect(SpaprXive *xive, Error **errp)
xive->tm_mmap = kvmppc_xive_mmap(xive, KVM_XIVE_TIMA_PAGE_OFFSET, tima_len,
&local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
goto fail;
}
memory_region_init_ram_device_ptr(&xive->tm_mmio_kvm, OBJECT(xive),
"xive.tima", tima_len, xive->tm_mmap);
@ -760,21 +758,24 @@ void kvmppc_xive_connect(SpaprXive *xive, Error **errp)
kvmppc_xive_cpu_connect(spapr_cpu_state(cpu)->tctx, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
goto fail;
}
}
/* Update the KVM sources */
kvmppc_xive_source_reset(xsrc, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
goto fail;
}
kvm_kernel_irqchip = true;
kvm_msi_via_irqfd_allowed = true;
kvm_gsi_direct_mapping = true;
return;
fail:
error_propagate(errp, local_err);
kvmppc_xive_disconnect(xive, NULL);
}
void kvmppc_xive_disconnect(SpaprXive *xive, Error **errp)
@ -796,23 +797,29 @@ void kvmppc_xive_disconnect(SpaprXive *xive, Error **errp)
xsrc = &xive->source;
esb_len = (1ull << xsrc->esb_shift) * xsrc->nr_irqs;
memory_region_del_subregion(&xsrc->esb_mmio, &xsrc->esb_mmio_kvm);
object_unparent(OBJECT(&xsrc->esb_mmio_kvm));
munmap(xsrc->esb_mmap, esb_len);
xsrc->esb_mmap = NULL;
if (xsrc->esb_mmap) {
memory_region_del_subregion(&xsrc->esb_mmio, &xsrc->esb_mmio_kvm);
object_unparent(OBJECT(&xsrc->esb_mmio_kvm));
munmap(xsrc->esb_mmap, esb_len);
xsrc->esb_mmap = NULL;
}
memory_region_del_subregion(&xive->tm_mmio, &xive->tm_mmio_kvm);
object_unparent(OBJECT(&xive->tm_mmio_kvm));
munmap(xive->tm_mmap, 4ull << TM_SHIFT);
xive->tm_mmap = NULL;
if (xive->tm_mmap) {
memory_region_del_subregion(&xive->tm_mmio, &xive->tm_mmio_kvm);
object_unparent(OBJECT(&xive->tm_mmio_kvm));
munmap(xive->tm_mmap, 4ull << TM_SHIFT);
xive->tm_mmap = NULL;
}
/*
* When the KVM device fd is closed, the KVM device is destroyed
* and removed from the list of devices of the VM. The VCPU
* presenters are also detached from the device.
*/
close(xive->fd);
xive->fd = -1;
if (xive->fd != -1) {
close(xive->fd);
xive->fd = -1;
}
kvm_kernel_irqchip = false;
kvm_msi_via_irqfd_allowed = false;
@ -822,5 +829,8 @@ void kvmppc_xive_disconnect(SpaprXive *xive, Error **errp)
kvm_cpu_disable_all();
/* VM Change state handler is not needed anymore */
qemu_del_vm_change_state_handler(xive->change);
if (xive->change) {
qemu_del_vm_change_state_handler(xive->change);
xive->change = NULL;
}
}