Hi Nick, > powerpc ifetch endianness depends on MSR[LE] so it has to byteswap > after cpu_ldl_code(). This corrects DSISR bits in alignment > interrupts when running in little endian mode. >
Just a thought, we have these tests that perhaps could have caught this: https://github.com/legoater/pnv-test Despite the name they do have (some) support to pseries as well. Not sure how the P8 support is these days though. > Signed-off-by: Nicholas Piggin <npig...@gmail.com> > --- > target/ppc/excp_helper.c | 27 ++++++++++++++++++++++++++- > 1 file changed, 26 insertions(+), 1 deletion(-) > > diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c > index 287659c74d..5f0e363363 100644 > --- a/target/ppc/excp_helper.c > +++ b/target/ppc/excp_helper.c > @@ -133,6 +133,31 @@ static void dump_hcall(CPUPPCState *env) > env->nip); > } > > +/* Return true iff byteswap is needed in a scalar memop */ > +static inline bool need_byteswap(CPUArchState *env) > +{ > +#if TARGET_BIG_ENDIAN TARGET_BIG_ENDIAN is always set for softmmu mode. See configs/targets/ppc64-softmmu.mak > + return !!(env->msr & ((target_ulong)1 << MSR_LE)); > +#else > + return !(env->msr & ((target_ulong)1 << MSR_LE)); > +#endif > +} > + > +static uint32_t ppc_ldl_code(CPUArchState *env, abi_ptr addr) > +{ > + uint32_t insn = cpu_ldl_code(env, addr); > +#if TARGET_BIG_ENDIAN > + if (env->msr & ((target_ulong)1 << MSR_LE)) { > + insn = bswap32(insn); > + } > +#else > + if (!(env->msr & ((target_ulong)1 << MSR_LE))) { > + insn = bswap32(insn); > + } > +#endif > + return insn; > +} > + > static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp) > { > const char *es; > @@ -3097,7 +3122,7 @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr > vaddr, > > /* Restore state and reload the insn we executed, for filling in DSISR. > */ > cpu_restore_state(cs, retaddr); > - insn = cpu_ldl_code(env, env->nip); > + insn = ppc_ldl_code(env, env->nip); > > switch (env->mmu_model) { > case POWERPC_MMU_SOFT_4xx: