aboutsummaryrefslogtreecommitdiff
path: root/target/ppc
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2023-08-08 13:11:14 +1000
committerCédric Le Goater <clg@kaod.org>2023-09-06 11:19:32 +0200
commit14192307ef6e63c9a0f3c7fe937e26bee95bc6a9 (patch)
tree5d7a00b3ab95fd16528de5a8b0139b50d470f193 /target/ppc
parenta11e3a1582b8c0d62ae3ef0323526baf2303e44a (diff)
target/ppc: Implement breakpoint debug facility for v2.07S
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>
Diffstat (limited to 'target/ppc')
-rw-r--r--target/ppc/cpu.c27
-rw-r--r--target/ppc/cpu.h3
-rw-r--r--target/ppc/cpu_init.c5
-rw-r--r--target/ppc/excp_helper.c42
-rw-r--r--target/ppc/helper.h1
-rw-r--r--target/ppc/internal.h2
-rw-r--r--target/ppc/machine.c4
-rw-r--r--target/ppc/misc_helper.c5
-rw-r--r--target/ppc/spr_common.h1
-rw-r--r--target/ppc/translate.c10
10 files changed, 98 insertions, 2 deletions
diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c
index 424f2e1741..d9c665ce18 100644
--- a/target/ppc/cpu.c
+++ b/target/ppc/cpu.c
@@ -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)
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 6826702ea6..264a915ad9 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -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 */
@@ -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);
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 3b6ccb5ea4..18b4757faa 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -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);
}
@@ -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);
}
@@ -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 */
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 2d6aef5e66..9c9881ae19 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -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 */
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index f4db32ee1a..83d5deec07 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -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)
diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 57acb3212c..16f02fd9c4 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -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)
diff --git a/target/ppc/machine.c b/target/ppc/machine.c
index 1270a1f7fc..890b7ea7af 100644
--- a/target/ppc/machine.c
+++ b/target/ppc/machine.c
@@ -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);
}
diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index 692d058665..0b0f2e59a7 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -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.
diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h
index 5995070eaf..b7bedd9ef1 100644
--- a/target/ppc/spr_common.h
+++ b/target/ppc/spr_common.h
@@ -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);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index ed6fc8f29e..8b22f7accd 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -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);
@@ -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 */