spapr: Clean up handling of LPCR power-saving exit bits
To prevent spurious wakeups on cpus that are supposed to be disabled, we need to clear the LPCR bits which control certain wakeup events. spapr_cpu_reset() has separate cases here for boot and non-boot (initially inactive) cpus. rtas_start_cpu() then turns the LPCR bits on when the non-boot cpus are activated. But explicit checks against first_cpu are not how we usually do things: instead spapr_cpu_reset() generally sets things up for non-boot (inactive) cpus, then spapr_machine_reset() and/or rtas_start_cpu() override as necessary. So, do that instead. Because the LPCR activation is identical for boot cpus and non-boot cpus just activated with rtas_start_cpu() we can put the code common in spapr_cpu_set_entry_state(). Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Reviewed-by: Cédric Le Goater <clg@kaod.org> Tested-by: Cédric Le Goater <clg@kaod.org>
This commit is contained in:
parent
da20aed12a
commit
47a9b55154
@ -54,28 +54,17 @@ static void spapr_cpu_reset(void *opaque)
|
||||
* Clearing VPM0 will also cause us to use RMOR in mmu-hash64.c for
|
||||
* real mode accesses, which thankfully defaults to 0 and isn't
|
||||
* accessible in guest mode.
|
||||
*
|
||||
* Disable Power-saving mode Exit Cause exceptions for the CPU, so
|
||||
* we don't get spurious wakups before an RTAS start-cpu call.
|
||||
*/
|
||||
lpcr &= ~(LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV);
|
||||
lpcr &= ~(LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV | pcc->lpcr_pm);
|
||||
lpcr |= LPCR_LPES0 | LPCR_LPES1;
|
||||
|
||||
/* Set RMLS to the max (ie, 16G) */
|
||||
lpcr &= ~LPCR_RMLS;
|
||||
lpcr |= 1ull << LPCR_RMLS_SHIFT;
|
||||
|
||||
/* Only enable Power-saving mode Exit Cause exceptions on the boot
|
||||
* CPU. The RTAS command start-cpu will enable them on secondaries.
|
||||
*/
|
||||
if (cs == first_cpu) {
|
||||
lpcr |= pcc->lpcr_pm;
|
||||
}
|
||||
|
||||
/* Disable Power-saving mode Exit Cause exceptions for the CPU.
|
||||
* This can cause issues when rebooting the guest if a secondary
|
||||
* is awaken */
|
||||
if (cs != first_cpu) {
|
||||
lpcr &= ~pcc->lpcr_pm;
|
||||
}
|
||||
|
||||
ppc_store_lpcr(cpu, lpcr);
|
||||
|
||||
/* Set a full AMOR so guest can use the AMR as it sees fit */
|
||||
@ -84,11 +73,14 @@ static void spapr_cpu_reset(void *opaque)
|
||||
|
||||
void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip, target_ulong r3)
|
||||
{
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
env->nip = nip;
|
||||
env->gpr[3] = r3;
|
||||
CPU(cpu)->halted = 0;
|
||||
/* Enable Power-saving mode Exit Cause exceptions */
|
||||
ppc_store_lpcr(cpu, env->spr[SPR_LPCR] | pcc->lpcr_pm);
|
||||
}
|
||||
|
||||
static void spapr_cpu_destroy(PowerPCCPU *cpu)
|
||||
|
@ -162,7 +162,7 @@ static void rtas_start_cpu(PowerPCCPU *callcpu, sPAPRMachineState *spapr,
|
||||
env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
|
||||
|
||||
/* Enable Power-saving mode Exit Cause exceptions for the new CPU */
|
||||
lpcr = env->spr[SPR_LPCR] | pcc->lpcr_pm;
|
||||
lpcr = env->spr[SPR_LPCR];
|
||||
if (!pcc->interrupts_big_endian(callcpu)) {
|
||||
lpcr |= LPCR_ILE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user