aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/intc/spapr_xive_kvm.c19
-rw-r--r--hw/intc/xive.c21
-rw-r--r--include/hw/ppc/xive.h1
3 files changed, 38 insertions, 3 deletions
diff --git a/hw/intc/spapr_xive_kvm.c b/hw/intc/spapr_xive_kvm.c
index 3bf8e7a..8898615 100644
--- a/hw/intc/spapr_xive_kvm.c
+++ b/hw/intc/spapr_xive_kvm.c
@@ -72,11 +72,17 @@ static void kvm_cpu_disable_all(void)
* XIVE Thread Interrupt Management context (KVM)
*/
-static void kvmppc_xive_cpu_set_state(XiveTCTX *tctx, Error **errp)
+void kvmppc_xive_cpu_set_state(XiveTCTX *tctx, Error **errp)
{
+ SpaprXive *xive = SPAPR_MACHINE(qdev_get_machine())->xive;
uint64_t state[2];
int ret;
+ /* The KVM XIVE device is not in use yet */
+ if (xive->fd == -1) {
+ return;
+ }
+
/* word0 and word1 of the OS ring. */
state[0] = *((uint64_t *) &tctx->regs[TM_QW1_OS]);
@@ -655,7 +661,16 @@ int kvmppc_xive_post_load(SpaprXive *xive, int version_id)
}
}
- /* Restore the thread interrupt contexts */
+ /*
+ * Restore the thread interrupt contexts of initial CPUs.
+ *
+ * The context of hotplugged CPUs is restored later, by the
+ * 'post_load' handler of the XiveTCTX model because they are not
+ * available at the time the SpaprXive 'post_load' method is
+ * called. We can not restore the context of all CPUs in the
+ * 'post_load' handler of XiveTCTX because the machine is not
+ * necessarily connected to the KVM device at that time.
+ */
CPU_FOREACH(cs) {
PowerPCCPU *cpu = POWERPC_CPU(cs);
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index cf77bdb..da148e9 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -615,12 +615,31 @@ static int vmstate_xive_tctx_pre_save(void *opaque)
return 0;
}
+static int vmstate_xive_tctx_post_load(void *opaque, int version_id)
+{
+ Error *local_err = NULL;
+
+ if (kvm_irqchip_in_kernel()) {
+ /*
+ * Required for hotplugged CPU, for which the state comes
+ * after all states of the machine.
+ */
+ kvmppc_xive_cpu_set_state(XIVE_TCTX(opaque), &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
static const VMStateDescription vmstate_xive_tctx = {
.name = TYPE_XIVE_TCTX,
.version_id = 1,
.minimum_version_id = 1,
.pre_save = vmstate_xive_tctx_pre_save,
- .post_load = NULL, /* handled by the sPAPRxive model */
+ .post_load = vmstate_xive_tctx_post_load,
.fields = (VMStateField[]) {
VMSTATE_BUFFER(regs, XiveTCTX),
VMSTATE_END_OF_LIST()
diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
index 55c53c7..7363351 100644
--- a/include/hw/ppc/xive.h
+++ b/include/hw/ppc/xive.h
@@ -438,5 +438,6 @@ void kvmppc_xive_source_set_irq(void *opaque, int srcno, int val);
void kvmppc_xive_cpu_connect(XiveTCTX *tctx, Error **errp);
void kvmppc_xive_cpu_synchronize_state(XiveTCTX *tctx, Error **errp);
void kvmppc_xive_cpu_get_state(XiveTCTX *tctx, Error **errp);
+void kvmppc_xive_cpu_set_state(XiveTCTX *tctx, Error **errp);
#endif /* PPC_XIVE_H */