From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43191) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1anGXT-0007Vw-0c for qemu-devel@nongnu.org; Mon, 04 Apr 2016 22:16:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1anGXL-0002BN-Ed for qemu-devel@nongnu.org; Mon, 04 Apr 2016 22:16:15 -0400 From: David Gibson Date: Tue, 5 Apr 2016 12:17:21 +1000 Message-Id: <1459822643-4770-2-git-send-email-david@gibson.dropbear.id.au> In-Reply-To: <1459822643-4770-1-git-send-email-david@gibson.dropbear.id.au> References: <1459822643-4770-1-git-send-email-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PULL 1/3] ppc: Rework POWER7 & POWER8 exception model List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: peter.maydell@linaro.org Cc: qemu-devel@nongnu.org, aik@ozlabs.ru, agraf@suse.de, mdroth@linux.vnet.ibm.com, clg@fr.ibm.com, qemu-ppc@nongnu.org, pbonzini@redhat.com, David Gibson From: C=C3=A9dric Le Goater From: Benjamin Herrenschmidt This patch fixes the current AIL implementation for POWER8. The interrupt vector address can be calculated directly from LPCR when the exception is handled. The excp_prefix update becomes useless and we can cleanup the H_SET_MODE hcall. Signed-off-by: Benjamin Herrenschmidt [clg: Removed LPES0/1 handling for HV vs. !HV Fixed LPCR_ILE case for POWERPC_EXCP_POWER8 ] Signed-off-by: C=C3=A9dric Le Goater [dwg: This was written as a cleanup, but it also fixes a real bug where setting an alternative interrupt location would not be correctly migrated] Signed-off-by: David Gibson --- hw/ppc/spapr_hcall.c | 16 +-------------- include/hw/ppc/spapr.h | 5 ----- target-ppc/cpu.h | 10 +++++++++ target-ppc/excp_helper.c | 49 +++++++++++++++++++++++++++++++++++++++= ++++-- target-ppc/translate_init.c | 2 +- 5 files changed, 59 insertions(+), 23 deletions(-) diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 2dcb676..8f40602 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -824,7 +824,6 @@ static target_ulong h_set_mode_resource_addr_trans_mo= de(PowerPCCPU *cpu, { CPUState *cs; PowerPCCPUClass *pcc =3D POWERPC_CPU_GET_CLASS(cpu); - target_ulong prefix; =20 if (!(pcc->insns_flags2 & PPC2_ISA207S)) { return H_P2; @@ -836,25 +835,12 @@ static target_ulong h_set_mode_resource_addr_trans_= mode(PowerPCCPU *cpu, return H_P4; } =20 - switch (mflags) { - case H_SET_MODE_ADDR_TRANS_NONE: - prefix =3D 0; - break; - case H_SET_MODE_ADDR_TRANS_0001_8000: - prefix =3D 0x18000; - break; - case H_SET_MODE_ADDR_TRANS_C000_0000_0000_4000: - prefix =3D 0xC000000000004000ULL; - break; - default: + if (mflags =3D=3D AIL_RESERVED) { return H_UNSUPPORTED_FLAG; } =20 CPU_FOREACH(cs) { - CPUPPCState *env =3D &POWERPC_CPU(cpu)->env; - set_spr(cs, SPR_LPCR, mflags << LPCR_AIL_SHIFT, LPCR_AIL); - env->excp_prefix =3D prefix; } =20 return H_SUCCESS; diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 098d85d..815d5ee 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -204,11 +204,6 @@ struct sPAPRMachineState { #define H_SET_MODE_ENDIAN_BIG 0 #define H_SET_MODE_ENDIAN_LITTLE 1 =20 -/* Flags for H_SET_MODE_RESOURCE_ADDR_TRANS_MODE */ -#define H_SET_MODE_ADDR_TRANS_NONE 0 -#define H_SET_MODE_ADDR_TRANS_0001_8000 2 -#define H_SET_MODE_ADDR_TRANS_C000_0000_0000_4000 3 - /* VASI States */ #define H_VASI_INVALID 0 #define H_VASI_ENABLED 1 diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 676081e..9d4e43c 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -167,6 +167,8 @@ enum powerpc_excp_t { POWERPC_EXCP_970, /* POWER7 exception model */ POWERPC_EXCP_POWER7, + /* POWER8 exception model */ + POWERPC_EXCP_POWER8, #endif /* defined(TARGET_PPC64) */ }; =20 @@ -2277,6 +2279,14 @@ enum { HMER_XSCOM_STATUS_LSH =3D (63 - 23), }; =20 +/* Alternate Interrupt Location (AIL) */ +enum { + AIL_NONE =3D 0, + AIL_RESERVED =3D 1, + AIL_0001_8000 =3D 2, + AIL_C000_0000_0000_4000 =3D 3, +}; + /***********************************************************************= ******/ =20 static inline target_ulong cpu_read_xer(CPUPPCState *env) diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c index c890853..ca4ffe8 100644 --- a/target-ppc/excp_helper.c +++ b/target-ppc/excp_helper.c @@ -77,7 +77,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int ex= cp_model, int excp) CPUPPCState *env =3D &cpu->env; target_ulong msr, new_msr, vector; int srr0, srr1, asrr0, asrr1; - int lpes0, lpes1, lev; + int lpes0, lpes1, lev, ail; =20 if (0) { /* XXX: find a suitable condition to enable the hypervisor mode = */ @@ -108,6 +108,25 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int= excp_model, int excp) asrr0 =3D -1; asrr1 =3D -1; =20 + /* Exception targetting modifiers + * + * 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) { + if (excp_model =3D=3D POWERPC_EXCP_POWER8) { + ail =3D (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT; + } else { + ail =3D 0; + } + } else +#endif /* defined(TARGET_PPC64) */ + { + ail =3D 0; + } + switch (excp) { case POWERPC_EXCP_NONE: /* Should never happen */ @@ -146,6 +165,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int = excp_model, int excp) /* XXX: find a suitable condition to enable the hypervisor m= ode */ new_msr |=3D (target_ulong)MSR_HVB; } + ail =3D 0; =20 /* machine check exceptions don't have ME set */ new_msr &=3D ~((target_ulong)1 << MSR_ME); @@ -344,6 +364,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int = excp_model, int excp) /* XXX: find a suitable condition to enable the hypervisor m= ode */ 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) { @@ -630,7 +651,8 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int = excp_model, int excp) } =20 #ifdef TARGET_PPC64 - if (excp_model =3D=3D POWERPC_EXCP_POWER7) { + if (excp_model =3D=3D POWERPC_EXCP_POWER7 || + excp_model =3D=3D POWERPC_EXCP_POWER8) { if (env->spr[SPR_LPCR] & LPCR_ILE) { new_msr |=3D (target_ulong)1 << MSR_LE; } @@ -650,6 +672,29 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int= excp_model, int excp) excp); } vector |=3D env->excp_prefix; + + /* 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)) { + ail =3D 0; + } + /* Handle AIL */ + if (ail) { + new_msr |=3D (1 << MSR_IR) | (1 << MSR_DR); + switch(ail) { + case AIL_0001_8000: + vector |=3D 0x18000; + break; + case AIL_C000_0000_0000_4000: + vector |=3D 0xc000000000004000ull; + break; + default: + cpu_abort(cs, "Invalid AIL combination %d\n", ail); + break; + } + } + #if defined(TARGET_PPC64) if (excp_model =3D=3D POWERPC_EXCP_BOOKE) { if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 0a33597..f515725 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -8487,7 +8487,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data) pcc->handle_mmu_fault =3D ppc_hash64_handle_mmu_fault; pcc->sps =3D &POWER7_POWER8_sps; #endif - pcc->excp_model =3D POWERPC_EXCP_POWER7; + pcc->excp_model =3D POWERPC_EXCP_POWER8; pcc->bus_model =3D PPC_FLAGS_INPUT_POWER7; pcc->bfd_mach =3D bfd_mach_ppc64; pcc->flags =3D POWERPC_FLAG_VRE | POWERPC_FLAG_SE | --=20 2.5.5