mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 02:03:56 -06:00
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>
This commit is contained in:
parent
a11e3a1582
commit
14192307ef
10 changed files with 98 additions and 2 deletions
|
@ -102,6 +102,33 @@ void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val)
|
||||||
|
|
||||||
ppc_maybe_interrupt(env);
|
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
|
#endif
|
||||||
|
|
||||||
static inline void fpscr_set_rounding_mode(CPUPPCState *env)
|
static inline void fpscr_set_rounding_mode(CPUPPCState *env)
|
||||||
|
|
|
@ -1137,6 +1137,7 @@ struct CPUArchState {
|
||||||
/* MMU context, only relevant for full system emulation */
|
/* MMU context, only relevant for full system emulation */
|
||||||
#if defined(TARGET_PPC64)
|
#if defined(TARGET_PPC64)
|
||||||
ppc_slb_t slb[MAX_SLB_ENTRIES]; /* PowerPC 64 SLB area */
|
ppc_slb_t slb[MAX_SLB_ENTRIES]; /* PowerPC 64 SLB area */
|
||||||
|
struct CPUBreakpoint *ciabr_breakpoint;
|
||||||
#endif
|
#endif
|
||||||
target_ulong sr[32]; /* segment registers */
|
target_ulong sr[32]; /* segment registers */
|
||||||
uint32_t nb_BATs; /* number of BATs */
|
uint32_t nb_BATs; /* number of BATs */
|
||||||
|
@ -1403,6 +1404,8 @@ void ppc_translate_init(void);
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
void ppc_store_sdr1(CPUPPCState *env, target_ulong value);
|
void ppc_store_sdr1(CPUPPCState *env, target_ulong value);
|
||||||
void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val);
|
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) */
|
#endif /* !defined(CONFIG_USER_ONLY) */
|
||||||
void ppc_store_msr(CPUPPCState *env, target_ulong value);
|
void ppc_store_msr(CPUPPCState *env, target_ulong value);
|
||||||
|
|
||||||
|
|
|
@ -5127,7 +5127,7 @@ static void register_book3s_207_dbg_sprs(CPUPPCState *env)
|
||||||
spr_register_kvm_hv(env, SPR_CIABR, "CIABR",
|
spr_register_kvm_hv(env, SPR_CIABR, "CIABR",
|
||||||
SPR_NOACCESS, SPR_NOACCESS,
|
SPR_NOACCESS, SPR_NOACCESS,
|
||||||
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);
|
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;
|
env->nip = env->hreset_vector | env->excp_prefix;
|
||||||
|
|
||||||
if (tcg_enabled()) {
|
if (tcg_enabled()) {
|
||||||
|
cpu_breakpoint_remove_all(s, BP_CPU);
|
||||||
if (env->mmu_model != POWERPC_MMU_REAL) {
|
if (env->mmu_model != POWERPC_MMU_REAL) {
|
||||||
ppc_tlb_invalidate_all(env);
|
ppc_tlb_invalidate_all(env);
|
||||||
}
|
}
|
||||||
|
@ -7346,6 +7347,8 @@ static const struct TCGCPUOps ppc_tcg_ops = {
|
||||||
.cpu_exec_exit = ppc_cpu_exec_exit,
|
.cpu_exec_exit = ppc_cpu_exec_exit,
|
||||||
.do_unaligned_access = ppc_cpu_do_unaligned_access,
|
.do_unaligned_access = ppc_cpu_do_unaligned_access,
|
||||||
.do_transaction_failed = ppc_cpu_do_transaction_failed,
|
.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_USER_ONLY */
|
||||||
};
|
};
|
||||||
#endif /* CONFIG_TCG */
|
#endif /* CONFIG_TCG */
|
||||||
|
|
|
@ -3257,5 +3257,47 @@ void ppc_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
|
||||||
cs->exception_index = POWERPC_EXCP_MCHECK;
|
cs->exception_index = POWERPC_EXCP_MCHECK;
|
||||||
cpu_loop_exit_restore(cs, retaddr);
|
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_TCG */
|
||||||
#endif /* !CONFIG_USER_ONLY */
|
#endif /* !CONFIG_USER_ONLY */
|
||||||
|
|
|
@ -25,6 +25,7 @@ DEF_HELPER_1(hrfid, void, env)
|
||||||
DEF_HELPER_2(rfebb, void, env, tl)
|
DEF_HELPER_2(rfebb, void, env, tl)
|
||||||
DEF_HELPER_2(store_lpcr, void, env, tl)
|
DEF_HELPER_2(store_lpcr, void, env, tl)
|
||||||
DEF_HELPER_2(store_pcr, 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_mmcr0, void, env, tl)
|
||||||
DEF_HELPER_2(store_mmcr1, void, env, tl)
|
DEF_HELPER_2(store_mmcr1, void, env, tl)
|
||||||
DEF_HELPER_3(store_pmc, void, env, i32, i64)
|
DEF_HELPER_3(store_pmc, void, env, i32, i64)
|
||||||
|
|
|
@ -301,6 +301,8 @@ void ppc_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
|
||||||
MMUAccessType access_type,
|
MMUAccessType access_type,
|
||||||
int mmu_idx, MemTxAttrs attrs,
|
int mmu_idx, MemTxAttrs attrs,
|
||||||
MemTxResult response, uintptr_t retaddr);
|
MemTxResult response, uintptr_t retaddr);
|
||||||
|
void ppc_cpu_debug_excp_handler(CPUState *cs);
|
||||||
|
bool ppc_cpu_debug_check_breakpoint(CPUState *cs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FIELD(GER_MSK, XMSK, 0, 4)
|
FIELD(GER_MSK, XMSK, 0, 4)
|
||||||
|
|
|
@ -313,6 +313,10 @@ static int cpu_post_load(void *opaque, int version_id)
|
||||||
post_load_update_msr(env);
|
post_load_update_msr(env);
|
||||||
|
|
||||||
if (tcg_enabled()) {
|
if (tcg_enabled()) {
|
||||||
|
/* Re-set breaks based on regs */
|
||||||
|
#if defined(TARGET_PPC64)
|
||||||
|
ppc_update_ciabr(env);
|
||||||
|
#endif
|
||||||
pmu_mmcr01_updated(env);
|
pmu_mmcr01_updated(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -199,6 +199,11 @@ void helper_store_pcr(CPUPPCState *env, target_ulong value)
|
||||||
env->spr[SPR_PCR] = value & pcc->pcr_mask;
|
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
|
* DPDES register is shared. Each bit reflects the state of the
|
||||||
* doorbell interrupt of a thread of the same core.
|
* doorbell interrupt of a thread of the same core.
|
||||||
|
|
|
@ -159,6 +159,7 @@ void spr_read_mas73(DisasContext *ctx, int gprn, int sprn);
|
||||||
#ifdef TARGET_PPC64
|
#ifdef TARGET_PPC64
|
||||||
void spr_read_cfar(DisasContext *ctx, int gprn, int sprn);
|
void spr_read_cfar(DisasContext *ctx, int gprn, int sprn);
|
||||||
void spr_write_cfar(DisasContext *ctx, int sprn, int gprn);
|
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_write_ureg(DisasContext *ctx, int sprn, int gprn);
|
||||||
void spr_read_purr(DisasContext *ctx, int gprn, int sprn);
|
void spr_read_purr(DisasContext *ctx, int gprn, int sprn);
|
||||||
void spr_write_purr(DisasContext *ctx, int sprn, int gprn);
|
void spr_write_purr(DisasContext *ctx, int sprn, int gprn);
|
||||||
|
|
|
@ -557,8 +557,9 @@ void spr_write_lr(DisasContext *ctx, int sprn, int gprn)
|
||||||
tcg_gen_mov_tl(cpu_lr, cpu_gpr[gprn]);
|
tcg_gen_mov_tl(cpu_lr, cpu_gpr[gprn]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CFAR */
|
|
||||||
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
|
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
|
||||||
|
/* Debug facilities */
|
||||||
|
/* CFAR */
|
||||||
void spr_read_cfar(DisasContext *ctx, int gprn, int sprn)
|
void spr_read_cfar(DisasContext *ctx, int gprn, int sprn)
|
||||||
{
|
{
|
||||||
tcg_gen_mov_tl(cpu_gpr[gprn], cpu_cfar);
|
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]);
|
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) */
|
#endif /* defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) */
|
||||||
|
|
||||||
/* CTR */
|
/* CTR */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue