aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2018-04-05 16:02:51 +1000
committerDavid Gibson <david@gibson.dropbear.id.au>2018-05-04 15:00:37 +1000
commitda20aed12a983dcaa6ccef80c0175f438e2780e7 (patch)
tree5b1d3705225de09f378c013b793025f69c6f48ad /hw/ppc
parentf00bed9521cee4d67c4937b51de692e0bcf9efef (diff)
downloadqemu-da20aed12a983dcaa6ccef80c0175f438e2780e7.zip
qemu-da20aed12a983dcaa6ccef80c0175f438e2780e7.tar.gz
qemu-da20aed12a983dcaa6ccef80c0175f438e2780e7.tar.bz2
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>
Diffstat (limited to 'hw/ppc')
-rw-r--r--hw/ppc/spapr_cpu_core.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index a98c7b0..a52ddad 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -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);