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; break;
case POWERPC_EXCP_TRACE: /* Trace exception */
msr |= env->error_code;
/* fall through */
case POWERPC_EXCP_DSEG: /* Data segment exception */ case POWERPC_EXCP_DSEG: /* Data segment exception */
case POWERPC_EXCP_ISEG: /* Instruction segment exception */ case POWERPC_EXCP_ISEG: /* Instruction segment exception */
case POWERPC_EXCP_TRACE: /* Trace exception */
case POWERPC_EXCP_SDOOR: /* Doorbell interrupt */ case POWERPC_EXCP_SDOOR: /* Doorbell interrupt */
case POWERPC_EXCP_PERFM: /* Performance monitor interrupt */ case POWERPC_EXCP_PERFM: /* Performance monitor interrupt */
break; break;
@ -3168,6 +3170,18 @@ void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb)
} }
#endif /* TARGET_PPC64 */ #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, void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
MMUAccessType access_type, MMUAccessType access_type,
int mmu_idx, uintptr_t retaddr) 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_2(insns_inc, void, env, i32)
DEF_HELPER_1(handle_pmc5_overflow, void, env) DEF_HELPER_1(handle_pmc5_overflow, void, env)
#endif #endif
DEF_HELPER_2(book3s_trace, void, env, tl)
DEF_HELPER_1(check_tlb_flush_local, void, env) DEF_HELPER_1(check_tlb_flush_local, void, env)
DEF_HELPER_1(check_tlb_flush_global, void, env) DEF_HELPER_1(check_tlb_flush_global, void, env)
#endif #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 * The exception can be either POWERPC_EXCP_TRACE (on most PowerPCs) or
* POWERPC_EXCP_DEBUG (on BookE). * 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) { if (ctx->flags & POWERPC_FLAG_DE) {
target_ulong dbsr = 0; target_ulong dbsr = 0;
if (ctx->singlestep_enabled & CPU_SINGLE_STEP) { 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); gen_load_spr(t0, SPR_BOOKE_DBSR);
tcg_gen_ori_tl(t0, t0, dbsr); tcg_gen_ori_tl(t0, t0, dbsr);
gen_store_spr(SPR_BOOKE_DBSR, t0); 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 { } 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;
} }
} #endif
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;
} }
static inline void gen_inval_exception(DisasContext *ctx, uint32_t error) 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) static void gen_lookup_and_goto_ptr(DisasContext *ctx)
{ {
if (unlikely(ctx->singlestep_enabled)) { if (unlikely(ctx->singlestep_enabled)) {
gen_debug_exception(ctx); gen_debug_exception(ctx, false);
} else { } else {
/* /*
* tcg_gen_lookup_and_goto_ptr will exit the TB if * tcg_gen_lookup_and_goto_ptr will exit the TB if