- Fix generic single step problem in vl.c * Overwriting the ret code when there was and interrupt pending causes the debugger to miss exceptions - For ppc, split run-time single stepping from the debugger stub single stepping * This fixes the hang problems when using single stepping via the msr_se Signed-off-by: Jason Wessel --- target-ppc/translate.c | 14 ++++++++++++-- vl.c | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -150,6 +150,7 @@ typedef struct DisasContext { int spe_enabled; ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */ int singlestep_enabled; + int sys_sstep_enabled; int dcache_line_size; } DisasContext; @@ -2802,8 +2803,10 @@ static always_inline void gen_goto_tb (D else #endif gen_op_b_T1(); - if (ctx->singlestep_enabled) + if (unlikely(ctx->sys_sstep_enabled)) { + gen_update_nip(ctx, ctx->nip); gen_op_debug(); + } tcg_gen_exit_tb(0); } } @@ -2984,8 +2987,10 @@ static always_inline void gen_bcond (Dis #endif gen_op_btest_T1(ctx->nip); no_test: - if (ctx->singlestep_enabled) + if (ctx->sys_sstep_enabled) { + gen_update_nip(ctx, ctx->nip); gen_op_debug(); + } tcg_gen_exit_tb(0); } out: @@ -6190,6 +6195,7 @@ static always_inline int gen_intermediat branch_step = 1; else branch_step = 0; + ctx.sys_sstep_enabled = env->singlestep_enabled; ctx.singlestep_enabled = env->singlestep_enabled || single_step == 1; #if defined (DO_SINGLE_STEP) && 0 /* Single step trace mode */ @@ -6306,6 +6312,10 @@ static always_inline int gen_intermediat if (ctx.exception == POWERPC_EXCP_NONE) { gen_goto_tb(&ctx, 0, ctx.nip); } else if (ctx.exception != POWERPC_EXCP_BRANCH) { + if (unlikely(ctx.sys_sstep_enabled)) { + gen_update_nip(&ctx, ctx.nip); + gen_op_debug(); + } /* Generate the return instruction */ tcg_gen_exit_tb(0); } --- a/vl.c +++ b/vl.c @@ -7523,7 +7523,7 @@ static int main_loop(void) qemu_time += profile_getclock() - ti; #endif next_cpu = env->next_cpu ?: first_cpu; - if (event_pending) { + if (event_pending && likely(ret != EXCP_DEBUG)) { ret = EXCP_INTERRUPT; event_pending = 0; break; @@ -7555,7 +7555,7 @@ static int main_loop(void) qemu_system_powerdown(); ret = EXCP_INTERRUPT; } - if (ret == EXCP_DEBUG) { + if (unlikely(ret == EXCP_DEBUG)) { vm_stop(EXCP_DEBUG); } /* If all cpus are halted then wait until the next IRQ */