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
 | 
					     * 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
 | 
					     * real mode accesses, which thankfully defaults to 0 and isn't
 | 
				
			||||||
     * accessible in guest mode.
 | 
					     * 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;
 | 
					    lpcr |= LPCR_LPES0 | LPCR_LPES1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Set RMLS to the max (ie, 16G) */
 | 
					    /* Set RMLS to the max (ie, 16G) */
 | 
				
			||||||
    lpcr &= ~LPCR_RMLS;
 | 
					    lpcr &= ~LPCR_RMLS;
 | 
				
			||||||
    lpcr |= 1ull << LPCR_RMLS_SHIFT;
 | 
					    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);
 | 
					    ppc_store_lpcr(cpu, lpcr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Set a full AMOR so guest can use the AMR as it sees fit */
 | 
					    /* 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)
 | 
					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;
 | 
					    CPUPPCState *env = &cpu->env;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    env->nip = nip;
 | 
					    env->nip = nip;
 | 
				
			||||||
    env->gpr[3] = r3;
 | 
					    env->gpr[3] = r3;
 | 
				
			||||||
    CPU(cpu)->halted = 0;
 | 
					    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)
 | 
					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);
 | 
					    env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Enable Power-saving mode Exit Cause exceptions for the new CPU */
 | 
					    /* 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)) {
 | 
					    if (!pcc->interrupts_big_endian(callcpu)) {
 | 
				
			||||||
        lpcr |= LPCR_ILE;
 | 
					        lpcr |= LPCR_ILE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user