Skip to content

Commit

Permalink
ppc: Rework POWER7 & POWER8 exception model
Browse files Browse the repository at this point in the history
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>

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 <benh@kernel.crashing.org>
[clg: Removed LPES0/1 handling for HV vs. !HV
      Fixed LPCR_ILE case for POWERPC_EXCP_POWER8 ]
Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
[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 <david@gibson.dropbear.id.au>
  • Loading branch information
Cédric Le Goater authored and dgibson committed Apr 5, 2016
1 parent 2e3a76a commit 5c94b2a
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 23 deletions.
16 changes: 1 addition & 15 deletions hw/ppc/spapr_hcall.c
Expand Up @@ -824,7 +824,6 @@ static target_ulong h_set_mode_resource_addr_trans_mode(PowerPCCPU *cpu,
{
CPUState *cs;
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
target_ulong prefix;

if (!(pcc->insns_flags2 & PPC2_ISA207S)) {
return H_P2;
Expand All @@ -836,25 +835,12 @@ static target_ulong h_set_mode_resource_addr_trans_mode(PowerPCCPU *cpu,
return H_P4;
}

switch (mflags) {
case H_SET_MODE_ADDR_TRANS_NONE:
prefix = 0;
break;
case H_SET_MODE_ADDR_TRANS_0001_8000:
prefix = 0x18000;
break;
case H_SET_MODE_ADDR_TRANS_C000_0000_0000_4000:
prefix = 0xC000000000004000ULL;
break;
default:
if (mflags == AIL_RESERVED) {
return H_UNSUPPORTED_FLAG;
}

CPU_FOREACH(cs) {
CPUPPCState *env = &POWERPC_CPU(cpu)->env;

set_spr(cs, SPR_LPCR, mflags << LPCR_AIL_SHIFT, LPCR_AIL);
env->excp_prefix = prefix;
}

return H_SUCCESS;
Expand Down
5 changes: 0 additions & 5 deletions include/hw/ppc/spapr.h
Expand Up @@ -204,11 +204,6 @@ struct sPAPRMachineState {
#define H_SET_MODE_ENDIAN_BIG 0
#define H_SET_MODE_ENDIAN_LITTLE 1

/* 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
Expand Down
10 changes: 10 additions & 0 deletions target-ppc/cpu.h
Expand Up @@ -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) */
};

Expand Down Expand Up @@ -2277,6 +2279,14 @@ enum {
HMER_XSCOM_STATUS_LSH = (63 - 23),
};

/* Alternate Interrupt Location (AIL) */
enum {
AIL_NONE = 0,
AIL_RESERVED = 1,
AIL_0001_8000 = 2,
AIL_C000_0000_0000_4000 = 3,
};

/*****************************************************************************/

static inline target_ulong cpu_read_xer(CPUPPCState *env)
Expand Down
49 changes: 47 additions & 2 deletions target-ppc/excp_helper.c
Expand Up @@ -77,7 +77,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
int srr0, srr1, asrr0, asrr1;
int lpes0, lpes1, lev;
int lpes0, lpes1, lev, ail;

if (0) {
/* XXX: find a suitable condition to enable the hypervisor mode */
Expand Down Expand Up @@ -108,6 +108,25 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
asrr0 = -1;
asrr1 = -1;

/* Exception targetting modifiers
*
* AIL is initialized here but can be cleared by
* selected exceptions
*/
#if defined(TARGET_PPC64)
if (excp_model == POWERPC_EXCP_POWER7 ||
excp_model == POWERPC_EXCP_POWER8) {
if (excp_model == POWERPC_EXCP_POWER8) {
ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
} else {
ail = 0;
}
} else
#endif /* defined(TARGET_PPC64) */
{
ail = 0;
}

switch (excp) {
case POWERPC_EXCP_NONE:
/* Should never happen */
Expand Down Expand Up @@ -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 mode */
new_msr |= (target_ulong)MSR_HVB;
}
ail = 0;

/* machine check exceptions don't have ME set */
new_msr &= ~((target_ulong)1 << MSR_ME);
Expand Down Expand Up @@ -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 mode */
new_msr |= (target_ulong)MSR_HVB;
}
ail = 0;
goto store_next;
case POWERPC_EXCP_DSEG: /* Data segment exception */
if (lpes1 == 0) {
Expand Down Expand Up @@ -630,7 +651,8 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
}

#ifdef TARGET_PPC64
if (excp_model == POWERPC_EXCP_POWER7) {
if (excp_model == POWERPC_EXCP_POWER7 ||
excp_model == POWERPC_EXCP_POWER8) {
if (env->spr[SPR_LPCR] & LPCR_ILE) {
new_msr |= (target_ulong)1 << MSR_LE;
}
Expand All @@ -650,6 +672,29 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
excp);
}
vector |= env->excp_prefix;

/* AIL only works if there is no HV transition and we are running with
* translations enabled
*/
if (!((msr >> MSR_IR) & 1) || !((msr >> MSR_DR) & 1)) {
ail = 0;
}
/* Handle AIL */
if (ail) {
new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
switch(ail) {
case AIL_0001_8000:
vector |= 0x18000;
break;
case AIL_C000_0000_0000_4000:
vector |= 0xc000000000004000ull;
break;
default:
cpu_abort(cs, "Invalid AIL combination %d\n", ail);
break;
}
}

#if defined(TARGET_PPC64)
if (excp_model == POWERPC_EXCP_BOOKE) {
if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
Expand Down
2 changes: 1 addition & 1 deletion target-ppc/translate_init.c
Expand Up @@ -8487,7 +8487,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
pcc->sps = &POWER7_POWER8_sps;
#endif
pcc->excp_model = POWERPC_EXCP_POWER7;
pcc->excp_model = POWERPC_EXCP_POWER8;
pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
pcc->bfd_mach = bfd_mach_ppc64;
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
Expand Down

0 comments on commit 5c94b2a

Please sign in to comment.