aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/intc/spapr_xive.c17
-rw-r--r--hw/ppc/spapr.c6
-rw-r--r--hw/ppc/spapr_irq.c31
3 files changed, 53 insertions, 1 deletions
diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index 682c192268..0e39c90cbd 100644
--- a/hw/intc/spapr_xive.c
+++ b/hw/intc/spapr_xive.c
@@ -179,6 +179,23 @@ static void spapr_xive_map_mmio(sPAPRXive *xive)
sysbus_mmio_map(SYS_BUS_DEVICE(xive), 2, xive->tm_base);
}
+/*
+ * When a Virtual Processor is scheduled to run on a HW thread, the
+ * hypervisor pushes its identifier in the OS CAM line. Emulate the
+ * same behavior under QEMU.
+ */
+void spapr_xive_set_tctx_os_cam(XiveTCTX *tctx)
+{
+ uint8_t nvt_blk;
+ uint32_t nvt_idx;
+ uint32_t nvt_cam;
+
+ spapr_xive_cpu_to_nvt(POWERPC_CPU(tctx->cs), &nvt_blk, &nvt_idx);
+
+ nvt_cam = cpu_to_be32(TM_QW1W2_VO | xive_nvt_cam_line(nvt_blk, nvt_idx));
+ memcpy(&tctx->regs[TM_QW1_OS + TM_WORD2], &nvt_cam, 4);
+}
+
static void spapr_xive_end_reset(XiveEND *end)
{
memset(end, 0, sizeof(*end));
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 0b09a88753..487f80e940 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1619,6 +1619,12 @@ static void spapr_machine_reset(void)
qemu_devices_reset();
+ /*
+ * This is fixing some of the default configuration of the XIVE
+ * devices. To be called after the reset of the machine devices.
+ */
+ spapr_irq_reset(spapr, &error_fatal);
+
/* DRC reset may cause a device to be unplugged. This will cause troubles
* if this device is used by another device (eg, a running vhost backend
* will crash QEMU if the DIMM holding the vring goes away). To avoid such
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 292c448a15..9ecbf47329 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -305,7 +305,14 @@ static void spapr_irq_print_info_xive(sPAPRMachineState *spapr,
static Object *spapr_irq_cpu_intc_create_xive(sPAPRMachineState *spapr,
Object *cpu, Error **errp)
{
- return xive_tctx_create(cpu, XIVE_ROUTER(spapr->xive), errp);
+ Object *obj = xive_tctx_create(cpu, XIVE_ROUTER(spapr->xive), errp);
+
+ /*
+ * (TCG) Early setting the OS CAM line for hotplugged CPUs as they
+ * don't benificiate from the reset of the XIVE IRQ backend
+ */
+ spapr_xive_set_tctx_os_cam(XIVE_TCTX(obj));
+ return obj;
}
static int spapr_irq_post_load_xive(sPAPRMachineState *spapr, int version_id)
@@ -313,6 +320,18 @@ static int spapr_irq_post_load_xive(sPAPRMachineState *spapr, int version_id)
return 0;
}
+static void spapr_irq_reset_xive(sPAPRMachineState *spapr, Error **errp)
+{
+ CPUState *cs;
+
+ CPU_FOREACH(cs) {
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+
+ /* (TCG) Set the OS CAM line of the thread interrupt context. */
+ spapr_xive_set_tctx_os_cam(XIVE_TCTX(cpu->intc));
+ }
+}
+
/*
* XIVE uses the full IRQ number space. Set it to 8K to be compatible
* with XICS.
@@ -333,6 +352,7 @@ sPAPRIrq spapr_irq_xive = {
.dt_populate = spapr_dt_xive,
.cpu_intc_create = spapr_irq_cpu_intc_create_xive,
.post_load = spapr_irq_post_load_xive,
+ .reset = spapr_irq_reset_xive,
};
/*
@@ -378,6 +398,15 @@ int spapr_irq_post_load(sPAPRMachineState *spapr, int version_id)
return smc->irq->post_load(spapr, version_id);
}
+void spapr_irq_reset(sPAPRMachineState *spapr, Error **errp)
+{
+ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+
+ if (smc->irq->reset) {
+ smc->irq->reset(spapr, errp);
+ }
+}
+
/*
* XICS legacy routines - to deprecate one day
*/