aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/ppc/spapr_rtas.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index cdf0b60..858adb1 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -162,6 +162,7 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPRMachineState *spapr,
if (cpu != NULL) {
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
if (!cs->halted) {
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
@@ -174,6 +175,10 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPRMachineState *spapr,
kvm_cpu_synchronize_state(cs);
env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
+
+ /* Enable Power-saving mode Exit Cause exceptions for the new CPU */
+ env->spr[SPR_LPCR] |= pcc->lpcr_pm;
+
env->nip = start;
env->gpr[3] = r3;
cs->halted = 0;
@@ -197,6 +202,7 @@ static void rtas_stop_self(PowerPCCPU *cpu, sPAPRMachineState *spapr,
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
cs->halted = 1;
qemu_cpu_kick(cs);
@@ -210,6 +216,11 @@ static void rtas_stop_self(PowerPCCPU *cpu, sPAPRMachineState *spapr,
* no need to bother with specific bits, we just clear it.
*/
env->msr = 0;
+
+ /* Disable Power-saving mode Exit Cause exceptions for the CPU.
+ * This could deliver an interrupt on a dying CPU and crash the
+ * guest */
+ env->spr[SPR_LPCR] &= ~pcc->lpcr_pm;
}
static inline int sysparm_st(target_ulong addr, target_ulong len,