target/ppc: Improve book3s branch trace interrupt for v2.07S

Improve the emulation accuracy of the single step and branch trace
interrupts for v2.07S. Set SRR1[33]=1, and set SIAR to completed
instruction address.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
This commit is contained in:
Nicholas Piggin 2023-08-08 13:11:12 +10:00 committed by Cédric Le Goater
parent 98a18f4d11
commit 148953849d
3 changed files with 27 additions and 11 deletions

View File

@ -1571,9 +1571,11 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
}
}
break;
case POWERPC_EXCP_TRACE: /* Trace exception */
msr |= env->error_code;
/* fall through */
case POWERPC_EXCP_DSEG: /* Data segment exception */
case POWERPC_EXCP_ISEG: /* Instruction segment exception */
case POWERPC_EXCP_TRACE: /* Trace exception */
case POWERPC_EXCP_SDOOR: /* Doorbell interrupt */
case POWERPC_EXCP_PERFM: /* Performance monitor interrupt */
break;
@ -3168,6 +3170,18 @@ void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb)
}
#endif /* TARGET_PPC64 */
/* Single-step tracing */
void helper_book3s_trace(CPUPPCState *env, target_ulong prev_ip)
{
uint32_t error_code = 0;
if (env->insns_flags2 & PPC2_ISA207S) {
/* Load/store reporting, SRR1[35, 36] and SDAR, are not implemented. */
env->spr[SPR_POWER_SIAR] = prev_ip;
error_code = PPC_BIT(33);
}
raise_exception_err(env, POWERPC_EXCP_TRACE, error_code);
}
void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
MMUAccessType access_type,
int mmu_idx, uintptr_t retaddr)

View File

@ -32,6 +32,7 @@ DEF_HELPER_2(read_pmc, tl, env, i32)
DEF_HELPER_2(insns_inc, void, env, i32)
DEF_HELPER_1(handle_pmc5_overflow, void, env)
#endif
DEF_HELPER_2(book3s_trace, void, env, tl)
DEF_HELPER_1(check_tlb_flush_local, void, env)
DEF_HELPER_1(check_tlb_flush_global, void, env)
#endif

View File

@ -336,8 +336,9 @@ static void gen_ppc_maybe_interrupt(DisasContext *ctx)
* The exception can be either POWERPC_EXCP_TRACE (on most PowerPCs) or
* POWERPC_EXCP_DEBUG (on BookE).
*/
static uint32_t gen_prep_dbgex(DisasContext *ctx)
static void gen_debug_exception(DisasContext *ctx)
{
#if !defined(CONFIG_USER_ONLY)
if (ctx->flags & POWERPC_FLAG_DE) {
target_ulong dbsr = 0;
if (ctx->singlestep_enabled & CPU_SINGLE_STEP) {
@ -350,16 +351,16 @@ static uint32_t gen_prep_dbgex(DisasContext *ctx)
gen_load_spr(t0, SPR_BOOKE_DBSR);
tcg_gen_ori_tl(t0, t0, dbsr);
gen_store_spr(SPR_BOOKE_DBSR, t0);
return POWERPC_EXCP_DEBUG;
gen_helper_raise_exception(cpu_env,
tcg_constant_i32(POWERPC_EXCP_DEBUG));
ctx->base.is_jmp = DISAS_NORETURN;
} else {
return POWERPC_EXCP_TRACE;
TCGv t0 = tcg_temp_new();
tcg_gen_movi_tl(t0, ctx->cia);
gen_helper_book3s_trace(cpu_env, t0);
ctx->base.is_jmp = DISAS_NORETURN;
}
}
static void gen_debug_exception(DisasContext *ctx)
{
gen_helper_raise_exception(cpu_env, tcg_constant_i32(gen_prep_dbgex(ctx)));
ctx->base.is_jmp = DISAS_NORETURN;
#endif
}
static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
@ -4182,7 +4183,7 @@ static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
static void gen_lookup_and_goto_ptr(DisasContext *ctx)
{
if (unlikely(ctx->singlestep_enabled)) {
gen_debug_exception(ctx);
gen_debug_exception(ctx, false);
} else {
/*
* tcg_gen_lookup_and_goto_ptr will exit the TB if