spapr: Move PAPR mode cpu setup fully to spapr code

cpu_ppc_set_papr() does several things:
    1) it sets up the virtual hypervisor interface
    2) it prevents the cpu from ever entering hypervisor mode
    3) it tells KVM that we're emulating a cpu in PAPR mode
and 4) it configures the LPCR and AMOR (hypervisor privileged registers)
       so that TCG will behave correctly for PAPR guests, without
       attempting to emulate the cpu in hypervisor mode

(1) & (2) make sense for any virtual hypervisor (if another one ever
exists).

(3) belongs more properly in the machine type specific to a PAPR guest, so
move it to spapr_cpu_init().  While we're at it, remove an ugly test on
kvm_enabled() by making kvmppc_set_papr() a safe no-op on non-KVM.

(4) also belongs more properly in the machine type specific code.  (4) is
done by mangling the default values of the SPRs, so that they will be set
correctly at reset time.  Manipulating usually-static parameters of the cpu
model like this is kind of ugly, especially since the values used really
have more to do with the platform than the cpu.

The spapr code already has places for PAPR specific initializations of
register state in spapr_cpu_reset(), so move this handling there.

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:
David Gibson 2018-04-05 16:02:51 +10:00
parent f00bed9521
commit da20aed12a
4 changed files with 39 additions and 45 deletions

View File

@ -28,6 +28,7 @@ static void spapr_cpu_reset(void *opaque)
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
target_ulong lpcr;
cpu_reset(cs);
@ -43,13 +44,42 @@ static void spapr_cpu_reset(void *opaque)
env->spr[SPR_HIOR] = 0;
lpcr = env->spr[SPR_LPCR];
/* Set emulated LPCR to not send interrupts to hypervisor. Note that
* under KVM, the actual HW LPCR will be set differently by KVM itself,
* the settings below ensure proper operations with TCG in absence of
* a real hypervisor.
*
* 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.
*/
lpcr &= ~(LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV);
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) {
env->spr[SPR_LPCR] &= ~pcc->lpcr_pm;
lpcr &= ~pcc->lpcr_pm;
}
ppc_store_lpcr(cpu, lpcr);
/* Set a full AMOR so guest can use the AMR as it sees fit */
env->spr[SPR_AMOR] = 0xffffffffffffffffull;
}
void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip, target_ulong r3)
@ -74,8 +104,8 @@ static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu,
/* Set time-base frequency to 512 MHz */
cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ);
/* Enable PAPR mode in TCG or KVM */
cpu_ppc_set_papr(cpu, PPC_VIRTUAL_HYPERVISOR(spapr));
cpu_ppc_set_vhyp(cpu, PPC_VIRTUAL_HYPERVISOR(spapr));
kvmppc_set_papr(cpu);
qemu_register_reset(spapr_cpu_reset, cpu);
spapr_cpu_reset(cpu);

View File

@ -1332,7 +1332,7 @@ void store_booke_tcr (CPUPPCState *env, target_ulong val);
void store_booke_tsr (CPUPPCState *env, target_ulong val);
void ppc_tlb_invalidate_all (CPUPPCState *env);
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr);
void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp);
void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp);
#endif
#endif

View File

@ -2088,6 +2088,10 @@ void kvmppc_set_papr(PowerPCCPU *cpu)
CPUState *cs = CPU(cpu);
int ret;
if (!kvm_enabled()) {
return;
}
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_PAPR, 0);
if (ret) {
error_report("This vCPU type or KVM version does not support PAPR");

View File

@ -8882,13 +8882,9 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
}
#if !defined(CONFIG_USER_ONLY)
void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
{
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
CPUPPCState *env = &cpu->env;
ppc_spr_t *lpcr = &env->spr_cb[SPR_LPCR];
ppc_spr_t *amor = &env->spr_cb[SPR_AMOR];
CPUState *cs = CPU(cpu);
cpu->vhyp = vhyp;
@ -8897,42 +8893,6 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
* hypervisor mode itself
*/
env->msr_mask &= ~MSR_HVB;
/* Set emulated LPCR to not send interrupts to hypervisor. Note that
* under KVM, the actual HW LPCR will be set differently by KVM itself,
* the settings below ensure proper operations with TCG in absence of
* a real hypervisor.
*
* 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.
*/
lpcr->default_value &= ~(LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV);
lpcr->default_value |= LPCR_LPES0 | LPCR_LPES1;
/* Set RMLS to the max (ie, 16G) */
lpcr->default_value &= ~LPCR_RMLS;
lpcr->default_value |= 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->default_value |= pcc->lpcr_pm;
}
/* We should be followed by a CPU reset but update the active value
* just in case...
*/
ppc_store_lpcr(cpu, lpcr->default_value);
/* Set a full AMOR so guest can use the AMR as it sees fit */
env->spr[SPR_AMOR] = amor->default_value = 0xffffffffffffffffull;
/* Tell KVM that we're in PAPR mode */
if (kvm_enabled()) {
kvmppc_set_papr(cpu);
}
}
#endif /* !defined(CONFIG_USER_ONLY) */