From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56121) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bCKNL-00014g-OG for qemu-devel@nongnu.org; Mon, 13 Jun 2016 01:25:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bCKNG-0001yY-LY for qemu-devel@nongnu.org; Mon, 13 Jun 2016 01:25:27 -0400 Received: from 7.mo178.mail-out.ovh.net ([46.105.58.91]:40860) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bCKNG-0001yN-7u for qemu-devel@nongnu.org; Mon, 13 Jun 2016 01:25:22 -0400 Received: from player791.ha.ovh.net (b9.ovh.net [213.186.33.59]) by mo178.mail-out.ovh.net (Postfix) with ESMTP id B535A1000E9C for ; Mon, 13 Jun 2016 07:25:21 +0200 (CEST) From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Mon, 13 Jun 2016 07:24:49 +0200 Message-Id: <1465795496-15071-4-git-send-email-clg@kaod.org> In-Reply-To: <1465795496-15071-1-git-send-email-clg@kaod.org> References: <1465795496-15071-1-git-send-email-clg@kaod.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PATCH 03/10] ppc: Rework POWER7 & POWER8 exception model (part 2) List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: David Gibson Cc: qemu-ppc@nongnu.org, qemu-devel@nongnu.org, Benjamin Herrenschmidt , Cedric Le Goater From: Benjamin Herrenschmidt Properly implement LPES0/1 handling for HV vs. !HV mode. Signed-off-by: Benjamin Herrenschmidt [clg: AIL implementation was fixed in commit 5c94b2a5e5ef fixed checkpatch.pl errors ] Signed-off-by: C=C3=A9dric Le Goater --- target-ppc/excp_helper.c | 134 ++++++++++++++++-------------------------= ------ 1 file changed, 45 insertions(+), 89 deletions(-) diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c index aa0b63f4b0de..7c44c102db39 100644 --- a/target-ppc/excp_helper.c +++ b/target-ppc/excp_helper.c @@ -77,18 +77,8 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int e= xcp_model, int excp) CPUState *cs =3D CPU(cpu); CPUPPCState *env =3D &cpu->env; target_ulong msr, new_msr, vector; - int srr0, srr1, asrr0, asrr1; - int lpes0, lpes1, lev, ail; - - if (0) { - /* XXX: find a suitable condition to enable the hypervisor mode = */ - lpes0 =3D (env->spr[SPR_LPCR] >> 1) & 1; - lpes1 =3D (env->spr[SPR_LPCR] >> 2) & 1; - } else { - /* Those values ensure we won't enter the hypervisor mode */ - lpes0 =3D 0; - lpes1 =3D 1; - } + int srr0, srr1, asrr0, asrr1, lev, ail; + bool lpes0; =20 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx " =3D> %08x (%02x)\n", env->nip, excp, env->error_code= ); @@ -100,8 +90,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int = excp_model, int excp) msr =3D env->msr & ~0x783f0000ULL; } =20 - /* new interrupt handler msr */ - new_msr =3D env->msr & ((target_ulong)1 << MSR_ME); + /* new interrupt handler msr preserves existing HV and ME unless + * explicitly overriden + */ + new_msr =3D env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB); =20 /* target registers */ srr0 =3D SPR_SRR0; @@ -111,12 +103,19 @@ static inline void powerpc_excp(PowerPCCPU *cpu, in= t excp_model, int excp) =20 /* Exception targetting modifiers * + * LPES0 is supported on POWER7/8 + * LPES1 is not supported (old iSeries mode) + * + * On anything else, we behave as if LPES0 is 1 + * (externals don't alter MSR:HV) + * * AIL is initialized here but can be cleared by * selected exceptions */ #if defined(TARGET_PPC64) if (excp_model =3D=3D POWERPC_EXCP_POWER7 || excp_model =3D=3D POWERPC_EXCP_POWER8) { + lpes0 =3D !!(env->spr[SPR_LPCR] & LPCR_LPES0); if (excp_model =3D=3D POWERPC_EXCP_POWER8) { ail =3D (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT; } else { @@ -125,6 +124,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int = excp_model, int excp) } else #endif /* defined(TARGET_PPC64) */ { + lpes0 =3D true; ail =3D 0; } =20 @@ -162,10 +162,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int= excp_model, int excp) cs->halted =3D 1; cs->interrupt_request |=3D CPU_INTERRUPT_EXITTB; } - if (0) { - /* XXX: find a suitable condition to enable the hypervisor m= ode */ - new_msr |=3D (target_ulong)MSR_HVB; - } + new_msr |=3D (target_ulong)MSR_HVB; ail =3D 0; =20 /* machine check exceptions don't have ME set */ @@ -191,23 +188,20 @@ static inline void powerpc_excp(PowerPCCPU *cpu, in= t excp_model, int excp) case POWERPC_EXCP_DSI: /* Data storage exception = */ LOG_EXCP("DSI exception: DSISR=3D" TARGET_FMT_lx" DAR=3D" TARGET= _FMT_lx "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]); - if (lpes1 =3D=3D 0) { - new_msr |=3D (target_ulong)MSR_HVB; - } goto store_next; case POWERPC_EXCP_ISI: /* Instruction storage exception = */ LOG_EXCP("ISI exception: msr=3D" TARGET_FMT_lx ", nip=3D" TARGET= _FMT_lx "\n", msr, env->nip); - if (lpes1 =3D=3D 0) { - new_msr |=3D (target_ulong)MSR_HVB; - } msr |=3D env->error_code; goto store_next; case POWERPC_EXCP_EXTERNAL: /* External input = */ cs =3D CPU(cpu); =20 - if (lpes0 =3D=3D 1) { + if (!lpes0) { new_msr |=3D (target_ulong)MSR_HVB; + new_msr |=3D env->msr & ((target_ulong)1 << MSR_RI); + srr0 =3D SPR_HSRR0; + srr1 =3D SPR_HSRR1; } if (env->mpic_proxy) { /* IACK the IRQ on delivery */ @@ -215,9 +209,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int = excp_model, int excp) } goto store_next; case POWERPC_EXCP_ALIGN: /* Alignment exception = */ - if (lpes1 =3D=3D 0) { - new_msr |=3D (target_ulong)MSR_HVB; - } /* XXX: this is false */ /* Get rS/rD and rA from faulting opcode */ env->spr[SPR_DSISR] |=3D (cpu_ldl_code(env, (env->nip - 4)) @@ -232,9 +223,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int = excp_model, int excp) env->error_code =3D 0; return; } - if (lpes1 =3D=3D 0) { - new_msr |=3D (target_ulong)MSR_HVB; - } msr |=3D 0x00100000; if (msr_fe0 =3D=3D msr_fe1) { goto store_next; @@ -243,23 +231,14 @@ static inline void powerpc_excp(PowerPCCPU *cpu, in= t excp_model, int excp) break; case POWERPC_EXCP_INVAL: LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->= nip); - if (lpes1 =3D=3D 0) { - new_msr |=3D (target_ulong)MSR_HVB; - } msr |=3D 0x00080000; env->spr[SPR_BOOKE_ESR] =3D ESR_PIL; break; case POWERPC_EXCP_PRIV: - if (lpes1 =3D=3D 0) { - new_msr |=3D (target_ulong)MSR_HVB; - } msr |=3D 0x00040000; env->spr[SPR_BOOKE_ESR] =3D ESR_PPR; break; case POWERPC_EXCP_TRAP: - if (lpes1 =3D=3D 0) { - new_msr |=3D (target_ulong)MSR_HVB; - } msr |=3D 0x00020000; env->spr[SPR_BOOKE_ESR] =3D ESR_PTR; break; @@ -271,27 +250,23 @@ static inline void powerpc_excp(PowerPCCPU *cpu, in= t excp_model, int excp) } goto store_current; case POWERPC_EXCP_FPU: /* Floating-point unavailable exception= */ - if (lpes1 =3D=3D 0) { - new_msr |=3D (target_ulong)MSR_HVB; - } goto store_current; case POWERPC_EXCP_SYSCALL: /* System call exception = */ dump_syscall(env); lev =3D env->error_code; + + /* "PAPR mode" built-in hypercall emulation */ if ((lev =3D=3D 1) && cpu_ppc_hypercall) { cpu_ppc_hypercall(cpu); return; } - if (lev =3D=3D 1 || (lpes0 =3D=3D 0 && lpes1 =3D=3D 0)) { + if (lev =3D=3D 1) { new_msr |=3D (target_ulong)MSR_HVB; } goto store_next; case POWERPC_EXCP_APU: /* Auxiliary processor unavailable = */ goto store_current; case POWERPC_EXCP_DECR: /* Decrementer exception = */ - if (lpes1 =3D=3D 0) { - new_msr |=3D (target_ulong)MSR_HVB; - } goto store_next; case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt = */ /* FIT on 4xx */ @@ -361,21 +336,12 @@ static inline void powerpc_excp(PowerPCCPU *cpu, in= t excp_model, int excp) new_msr &=3D ~((target_ulong)1 << MSR_ME); } =20 - if (0) { - /* XXX: find a suitable condition to enable the hypervisor m= ode */ - new_msr |=3D (target_ulong)MSR_HVB; - } + new_msr |=3D (target_ulong)MSR_HVB; ail =3D 0; goto store_next; case POWERPC_EXCP_DSEG: /* Data segment exception = */ - if (lpes1 =3D=3D 0) { - new_msr |=3D (target_ulong)MSR_HVB; - } goto store_next; case POWERPC_EXCP_ISEG: /* Instruction segment exception = */ - if (lpes1 =3D=3D 0) { - new_msr |=3D (target_ulong)MSR_HVB; - } goto store_next; case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception = */ srr0 =3D SPR_HSRR0; @@ -384,9 +350,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int = excp_model, int excp) new_msr |=3D env->msr & ((target_ulong)1 << MSR_RI); goto store_next; case POWERPC_EXCP_TRACE: /* Trace exception = */ - if (lpes1 =3D=3D 0) { - new_msr |=3D (target_ulong)MSR_HVB; - } goto store_next; case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception = */ srr0 =3D SPR_HSRR0; @@ -413,19 +376,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, in= t excp_model, int excp) new_msr |=3D env->msr & ((target_ulong)1 << MSR_RI); goto store_next; case POWERPC_EXCP_VPU: /* Vector unavailable exception = */ - if (lpes1 =3D=3D 0) { - new_msr |=3D (target_ulong)MSR_HVB; - } goto store_current; case POWERPC_EXCP_VSXU: /* VSX unavailable exception = */ - if (lpes1 =3D=3D 0) { - new_msr |=3D (target_ulong)MSR_HVB; - } goto store_current; case POWERPC_EXCP_FU: /* Facility unavailable exception = */ - if (lpes1 =3D=3D 0) { - new_msr |=3D (target_ulong)MSR_HVB; - } goto store_current; case POWERPC_EXCP_PIT: /* Programmable interval timer interrup= t */ LOG_EXCP("PIT exception\n"); @@ -444,9 +398,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int = excp_model, int excp) "is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error = */ - if (lpes1 =3D=3D 0) { /* XXX: check this */ - new_msr |=3D (target_ulong)MSR_HVB; - } switch (excp_model) { case POWERPC_EXCP_602: case POWERPC_EXCP_603: @@ -463,9 +414,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int = excp_model, int excp) } break; case POWERPC_EXCP_DLTLB: /* Data load TLB miss = */ - if (lpes1 =3D=3D 0) { /* XXX: check this */ - new_msr |=3D (target_ulong)MSR_HVB; - } switch (excp_model) { case POWERPC_EXCP_602: case POWERPC_EXCP_603: @@ -482,9 +430,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int = excp_model, int excp) } break; case POWERPC_EXCP_DSTLB: /* Data store TLB miss = */ - if (lpes1 =3D=3D 0) { /* XXX: check this */ - new_msr |=3D (target_ulong)MSR_HVB; - } switch (excp_model) { case POWERPC_EXCP_602: case POWERPC_EXCP_603: @@ -590,9 +535,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int = excp_model, int excp) "is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_PERFM: /* Embedded performance monitor interru= pt */ - if (lpes1 =3D=3D 0) { - new_msr |=3D (target_ulong)MSR_HVB; - } /* XXX: TODO */ cpu_abort(cs, "Performance counter exception is not implemented yet = !\n"); @@ -636,6 +578,13 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int= excp_model, int excp) } /* Save MSR */ env->spr[srr1] =3D msr; + + /* Sanity check */ + if (!(env->msr_mask & MSR_HVB) && (srr0 =3D=3D SPR_HSRR0)) { + cpu_abort(cs, "Trying to deliver HV exception %d with " + "no HV support\n", excp); + } + /* If any alternate SRR register are defined, duplicate saved values= */ if (asrr0 !=3D -1) { env->spr[asrr0] =3D env->spr[srr0]; @@ -644,14 +593,20 @@ static inline void powerpc_excp(PowerPCCPU *cpu, in= t excp_model, int excp) env->spr[asrr1] =3D env->spr[srr1]; } =20 - if (env->spr[SPR_LPCR] & LPCR_AIL) { - new_msr |=3D (1 << MSR_IR) | (1 << MSR_DR); - } - + /* Sort out endianness of interrupt, this differs depending on the + * CPU, the HV mode, etc... + */ #ifdef TARGET_PPC64 - if (excp_model =3D=3D POWERPC_EXCP_POWER7 || - excp_model =3D=3D POWERPC_EXCP_POWER8) { - if (env->spr[SPR_LPCR] & LPCR_ILE) { + if (excp_model =3D=3D POWERPC_EXCP_POWER7) { + if (!(new_msr & MSR_HVB) && (env->spr[SPR_LPCR] & LPCR_ILE)) { + new_msr |=3D (target_ulong)1 << MSR_LE; + } + } else if (excp_model =3D=3D POWERPC_EXCP_POWER8) { + if (new_msr & MSR_HVB) { + if (env->spr[SPR_HID0] & HID0_HILE) { + new_msr |=3D (target_ulong)1 << MSR_LE; + } + } else if (env->spr[SPR_LPCR] & LPCR_ILE) { new_msr |=3D (target_ulong)1 << MSR_LE; } } else if (msr_ile) { @@ -674,7 +629,8 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int = excp_model, int excp) /* AIL only works if there is no HV transition and we are running wi= th * translations enabled */ - if (!((msr >> MSR_IR) & 1) || !((msr >> MSR_DR) & 1)) { + if (!((msr >> MSR_IR) & 1) || !((msr >> MSR_DR) & 1) || + ((new_msr & MSR_HVB) && !(msr & MSR_HVB))) { ail =3D 0; } /* Handle AIL */ --=20 2.1.4