Skip to content

Commit

Permalink
target/ppc: Implement breakpoint debug facility for v2.07S
Browse files Browse the repository at this point in the history
ISA v2.07S introduced the breakpoint facility based on the CIABR SPR.
Implement this in TCG.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
  • Loading branch information
npiggin authored and legoater committed Sep 6, 2023
1 parent a11e3a1 commit 1419230
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 2 deletions.
27 changes: 27 additions & 0 deletions target/ppc/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,33 @@ void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val)

ppc_maybe_interrupt(env);
}

#if defined(TARGET_PPC64)
void ppc_update_ciabr(CPUPPCState *env)
{
CPUState *cs = env_cpu(env);
target_ulong ciabr = env->spr[SPR_CIABR];
target_ulong ciea, priv;

ciea = ciabr & PPC_BITMASK(0, 61);
priv = ciabr & PPC_BITMASK(62, 63);

if (env->ciabr_breakpoint) {
cpu_breakpoint_remove_by_ref(cs, env->ciabr_breakpoint);
env->ciabr_breakpoint = NULL;
}

if (priv) {
cpu_breakpoint_insert(cs, ciea, BP_CPU, &env->ciabr_breakpoint);
}
}

void ppc_store_ciabr(CPUPPCState *env, target_ulong val)
{
env->spr[SPR_CIABR] = val;
ppc_update_ciabr(env);
}
#endif
#endif

static inline void fpscr_set_rounding_mode(CPUPPCState *env)
Expand Down
3 changes: 3 additions & 0 deletions target/ppc/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -1137,6 +1137,7 @@ struct CPUArchState {
/* MMU context, only relevant for full system emulation */
#if defined(TARGET_PPC64)
ppc_slb_t slb[MAX_SLB_ENTRIES]; /* PowerPC 64 SLB area */
struct CPUBreakpoint *ciabr_breakpoint;
#endif
target_ulong sr[32]; /* segment registers */
uint32_t nb_BATs; /* number of BATs */
Expand Down Expand Up @@ -1403,6 +1404,8 @@ void ppc_translate_init(void);
#if !defined(CONFIG_USER_ONLY)
void ppc_store_sdr1(CPUPPCState *env, target_ulong value);
void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val);
void ppc_update_ciabr(CPUPPCState *env);
void ppc_store_ciabr(CPUPPCState *env, target_ulong value);
#endif /* !defined(CONFIG_USER_ONLY) */
void ppc_store_msr(CPUPPCState *env, target_ulong value);

Expand Down
5 changes: 4 additions & 1 deletion target/ppc/cpu_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -5127,7 +5127,7 @@ static void register_book3s_207_dbg_sprs(CPUPPCState *env)
spr_register_kvm_hv(env, SPR_CIABR, "CIABR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
&spr_read_generic, &spr_write_ciabr,
KVM_REG_PPC_CIABR, 0x00000000);
}

Expand Down Expand Up @@ -7159,6 +7159,7 @@ static void ppc_cpu_reset_hold(Object *obj)
env->nip = env->hreset_vector | env->excp_prefix;

if (tcg_enabled()) {
cpu_breakpoint_remove_all(s, BP_CPU);
if (env->mmu_model != POWERPC_MMU_REAL) {
ppc_tlb_invalidate_all(env);
}
Expand Down Expand Up @@ -7346,6 +7347,8 @@ static const struct TCGCPUOps ppc_tcg_ops = {
.cpu_exec_exit = ppc_cpu_exec_exit,
.do_unaligned_access = ppc_cpu_do_unaligned_access,
.do_transaction_failed = ppc_cpu_do_transaction_failed,
.debug_excp_handler = ppc_cpu_debug_excp_handler,
.debug_check_breakpoint = ppc_cpu_debug_check_breakpoint,
#endif /* !CONFIG_USER_ONLY */
};
#endif /* CONFIG_TCG */
Expand Down
42 changes: 42 additions & 0 deletions target/ppc/excp_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -3257,5 +3257,47 @@ void ppc_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
cs->exception_index = POWERPC_EXCP_MCHECK;
cpu_loop_exit_restore(cs, retaddr);
}

void ppc_cpu_debug_excp_handler(CPUState *cs)
{
#if defined(TARGET_PPC64)
CPUPPCState *env = cs->env_ptr;

if (env->insns_flags2 & PPC2_ISA207S) {
if (cpu_breakpoint_test(cs, env->nip, BP_CPU)) {
raise_exception_err(env, POWERPC_EXCP_TRACE,
PPC_BIT(33) | PPC_BIT(43));
}
}
#endif
}

bool ppc_cpu_debug_check_breakpoint(CPUState *cs)
{
#if defined(TARGET_PPC64)
CPUPPCState *env = cs->env_ptr;

if (env->insns_flags2 & PPC2_ISA207S) {
target_ulong priv;

priv = env->spr[SPR_CIABR] & PPC_BITMASK(62, 63);
switch (priv) {
case 0x1: /* problem */
return env->msr & ((target_ulong)1 << MSR_PR);
case 0x2: /* supervisor */
return (!(env->msr & ((target_ulong)1 << MSR_PR)) &&
!(env->msr & ((target_ulong)1 << MSR_HV)));
case 0x3: /* hypervisor */
return (!(env->msr & ((target_ulong)1 << MSR_PR)) &&
(env->msr & ((target_ulong)1 << MSR_HV)));
default:
g_assert_not_reached();
}
}
#endif

return false;
}

#endif /* CONFIG_TCG */
#endif /* !CONFIG_USER_ONLY */
1 change: 1 addition & 0 deletions target/ppc/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ DEF_HELPER_1(hrfid, void, env)
DEF_HELPER_2(rfebb, void, env, tl)
DEF_HELPER_2(store_lpcr, void, env, tl)
DEF_HELPER_2(store_pcr, void, env, tl)
DEF_HELPER_2(store_ciabr, void, env, tl)
DEF_HELPER_2(store_mmcr0, void, env, tl)
DEF_HELPER_2(store_mmcr1, void, env, tl)
DEF_HELPER_3(store_pmc, void, env, i32, i64)
Expand Down
2 changes: 2 additions & 0 deletions target/ppc/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,8 @@ void ppc_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
MMUAccessType access_type,
int mmu_idx, MemTxAttrs attrs,
MemTxResult response, uintptr_t retaddr);
void ppc_cpu_debug_excp_handler(CPUState *cs);
bool ppc_cpu_debug_check_breakpoint(CPUState *cs);
#endif

FIELD(GER_MSK, XMSK, 0, 4)
Expand Down
4 changes: 4 additions & 0 deletions target/ppc/machine.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,10 @@ static int cpu_post_load(void *opaque, int version_id)
post_load_update_msr(env);

if (tcg_enabled()) {
/* Re-set breaks based on regs */
#if defined(TARGET_PPC64)
ppc_update_ciabr(env);
#endif
pmu_mmcr01_updated(env);
}

Expand Down
5 changes: 5 additions & 0 deletions target/ppc/misc_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ void helper_store_pcr(CPUPPCState *env, target_ulong value)
env->spr[SPR_PCR] = value & pcc->pcr_mask;
}

void helper_store_ciabr(CPUPPCState *env, target_ulong value)
{
ppc_store_ciabr(env, value);
}

/*
* DPDES register is shared. Each bit reflects the state of the
* doorbell interrupt of a thread of the same core.
Expand Down
1 change: 1 addition & 0 deletions target/ppc/spr_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ void spr_read_mas73(DisasContext *ctx, int gprn, int sprn);
#ifdef TARGET_PPC64
void spr_read_cfar(DisasContext *ctx, int gprn, int sprn);
void spr_write_cfar(DisasContext *ctx, int sprn, int gprn);
void spr_write_ciabr(DisasContext *ctx, int sprn, int gprn);
void spr_write_ureg(DisasContext *ctx, int sprn, int gprn);
void spr_read_purr(DisasContext *ctx, int gprn, int sprn);
void spr_write_purr(DisasContext *ctx, int sprn, int gprn);
Expand Down
10 changes: 9 additions & 1 deletion target/ppc/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -557,8 +557,9 @@ void spr_write_lr(DisasContext *ctx, int sprn, int gprn)
tcg_gen_mov_tl(cpu_lr, cpu_gpr[gprn]);
}

/* CFAR */
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
/* Debug facilities */
/* CFAR */
void spr_read_cfar(DisasContext *ctx, int gprn, int sprn)
{
tcg_gen_mov_tl(cpu_gpr[gprn], cpu_cfar);
Expand All @@ -568,6 +569,13 @@ void spr_write_cfar(DisasContext *ctx, int sprn, int gprn)
{
tcg_gen_mov_tl(cpu_cfar, cpu_gpr[gprn]);
}

/* Breakpoint */
void spr_write_ciabr(DisasContext *ctx, int sprn, int gprn)
{
translator_io_start(&ctx->base);
gen_helper_store_ciabr(cpu_env, cpu_gpr[gprn]);
}
#endif /* defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) */

/* CTR */
Expand Down

0 comments on commit 1419230

Please sign in to comment.