summaryrefslogtreecommitdiffstats
path: root/target-ppc/excp_helper.c
diff options
context:
space:
mode:
authorPeter Maydell2016-07-01 14:31:48 +0200
committerPeter Maydell2016-07-01 14:31:48 +0200
commit1b756f1abfb68130dc79e998fc501a032b2ca29d (patch)
treed11f8698655e2ae07afdb9b7259d550e44f50614 /target-ppc/excp_helper.c
parentMerge remote-tracking branch 'remotes/awilliam/tags/vfio-update-20160630.0' i... (diff)
parentqmp: fix spapr example of query-hotpluggable-cpus (diff)
downloadqemu-1b756f1abfb68130dc79e998fc501a032b2ca29d.tar.gz
qemu-1b756f1abfb68130dc79e998fc501a032b2ca29d.tar.xz
qemu-1b756f1abfb68130dc79e998fc501a032b2ca29d.zip
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.7-20160701' into staging
ppc patch queue 2016-07-01 Here's the current ppc patch queue. This is a fairly large batch, containing: * A number of further preliminary patches towards full hypervisor mode emulation * Some further fixes / cleanups for the recently merged device_add based CPU hotplug * Preliminary patches towards supporting a native (rather than paravirtualized) XICS device. This will be needed to emulate a physical Power machine, including hypervisor capabilities * Assorted bug fixes # gpg: Signature made Fri 01 Jul 2016 06:56:35 BST # gpg: using RSA key 0x6C38CACA20D9B392 # gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" # gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" # gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392 * remotes/dgibson/tags/ppc-for-2.7-20160701: (23 commits) qmp: fix spapr example of query-hotpluggable-cpus spapr: drop duplicate variable in spapr_core_release() spapr: do proper error propagation in spapr_cpu_core_realize_child() spapr: drop reference on child object during core realization spapr: Restore support for 970MP and POWER8NVL CPU cores target-ppc: gen_pause for instructions: yield, mdoio, mdoom, miso ppc/xics: Replace "icp" with "xics" in most places ppc/xics: Implement H_IPOLL using an accessor ppc/xics: Move SPAPR specific code to a separate file ppc/xics: Rename existing xics to xics_spapr ppc: Fix 64K pages support in full emulation target-ppc: Eliminate redundant and incorrect function booke206_page_size_to_tlb spapr: Restore support for older PowerPC CPU cores spapr: fix write-past-end-of-array error in cpu core device init code hw/ppc/spapr: Add some missing hcall function set strings ppc: Print HSRR0/HSRR1 in "info registers" ppc: LPCR is a HV resource ppc: Initial HDEC support ppc: Enforce setting MSR:EE,IR and DR when MSR:PR is set ppc: Fix conditions for delivering external interrupts to a guest ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target-ppc/excp_helper.c')
-rw-r--r--target-ppc/excp_helper.c41
1 files changed, 20 insertions, 21 deletions
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 533866b87b..d6e1678a63 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -753,7 +753,6 @@ void ppc_cpu_do_interrupt(CPUState *cs)
static void ppc_hw_interrupt(CPUPPCState *env)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
- int hdice;
#if 0
CPUState *cs = CPU(cpu);
@@ -781,19 +780,25 @@ static void ppc_hw_interrupt(CPUPPCState *env)
return;
}
#endif
- if (0) {
- /* XXX: find a suitable condition to enable the hypervisor mode */
- hdice = env->spr[SPR_LPCR] & 1;
- } else {
- hdice = 0;
- }
- if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
- /* Hypervisor decrementer exception */
- if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
+ /* Hypervisor decrementer exception */
+ if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
+ /* LPCR will be clear when not supported so this will work */
+ bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
+ if ((msr_ee != 0 || msr_hv == 0) && hdice) {
+ /* HDEC clears on delivery */
+ env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
return;
}
}
+ /* Extermal interrupt can ignore MSR:EE under some circumstances */
+ if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
+ bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
+ if (msr_ee != 0 || (env->has_hv_mode && msr_hv == 0 && !lpes0)) {
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
+ return;
+ }
+ }
if (msr_ce != 0) {
/* External critical interrupt */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
@@ -839,17 +844,6 @@ static void ppc_hw_interrupt(CPUPPCState *env)
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
return;
}
- /* External interrupt */
- if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
- /* Taking an external interrupt does not clear the external
- * interrupt status
- */
-#if 0
- env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
-#endif
- powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
- return;
- }
if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
@@ -944,6 +938,11 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
cs->halted = 1;
env->in_pm_state = true;
+ /* The architecture specifies that HDEC interrupts are
+ * discarded in PM states
+ */
+ env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
+
/* Technically, nap doesn't set EE, but if we don't set it
* then ppc_hw_interrupt() won't deliver. We could add some
* other tests there based on LPCR but it's simpler to just