Commit 8cbcb4fa2c6d5fb84552ab141c6e35d33323aa18
1 parent
33759846
Fix broken PPC user space single stepping
(Jason Wessel) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4421 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
39 additions
and
23 deletions
target-ppc/translate.c
| ... | ... | @@ -29,6 +29,10 @@ |
| 29 | 29 | #include "tcg-op.h" |
| 30 | 30 | #include "qemu-common.h" |
| 31 | 31 | |
| 32 | +#define CPU_SINGLE_STEP 0x1 | |
| 33 | +#define CPU_BRANCH_STEP 0x2 | |
| 34 | +#define GDBSTUB_SINGLE_STEP 0x4 | |
| 35 | + | |
| 32 | 36 | /* Include definitions for instructions classes and implementations flags */ |
| 33 | 37 | //#define DO_SINGLE_STEP |
| 34 | 38 | //#define PPC_DEBUG_DISAS |
| ... | ... | @@ -2785,7 +2789,7 @@ static always_inline void gen_goto_tb (DisasContext *ctx, int n, |
| 2785 | 2789 | TranslationBlock *tb; |
| 2786 | 2790 | tb = ctx->tb; |
| 2787 | 2791 | if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) && |
| 2788 | - !ctx->singlestep_enabled) { | |
| 2792 | + likely(!ctx->singlestep_enabled)) { | |
| 2789 | 2793 | tcg_gen_goto_tb(n); |
| 2790 | 2794 | gen_set_T1(dest); |
| 2791 | 2795 | #if defined(TARGET_PPC64) |
| ... | ... | @@ -2803,8 +2807,20 @@ static always_inline void gen_goto_tb (DisasContext *ctx, int n, |
| 2803 | 2807 | else |
| 2804 | 2808 | #endif |
| 2805 | 2809 | gen_op_b_T1(); |
| 2806 | - if (ctx->singlestep_enabled) | |
| 2807 | - gen_op_debug(); | |
| 2810 | + if (unlikely(ctx->singlestep_enabled)) { | |
| 2811 | + if ((ctx->singlestep_enabled & | |
| 2812 | + (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) && | |
| 2813 | + ctx->exception == POWERPC_EXCP_BRANCH) { | |
| 2814 | + target_ulong tmp = ctx->nip; | |
| 2815 | + ctx->nip = dest; | |
| 2816 | + GEN_EXCP(ctx, POWERPC_EXCP_TRACE, 0); | |
| 2817 | + ctx->nip = tmp; | |
| 2818 | + } | |
| 2819 | + if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) { | |
| 2820 | + gen_update_nip(ctx, dest); | |
| 2821 | + gen_op_debug(); | |
| 2822 | + } | |
| 2823 | + } | |
| 2808 | 2824 | tcg_gen_exit_tb(0); |
| 2809 | 2825 | } |
| 2810 | 2826 | } |
| ... | ... | @@ -2824,6 +2840,7 @@ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW) |
| 2824 | 2840 | { |
| 2825 | 2841 | target_ulong li, target; |
| 2826 | 2842 | |
| 2843 | + ctx->exception = POWERPC_EXCP_BRANCH; | |
| 2827 | 2844 | /* sign extend LI */ |
| 2828 | 2845 | #if defined(TARGET_PPC64) |
| 2829 | 2846 | if (ctx->sf_mode) |
| ... | ... | @@ -2842,7 +2859,6 @@ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW) |
| 2842 | 2859 | if (LK(ctx->opcode)) |
| 2843 | 2860 | gen_setlr(ctx, ctx->nip); |
| 2844 | 2861 | gen_goto_tb(ctx, 0, target); |
| 2845 | - ctx->exception = POWERPC_EXCP_BRANCH; | |
| 2846 | 2862 | } |
| 2847 | 2863 | |
| 2848 | 2864 | #define BCOND_IM 0 |
| ... | ... | @@ -2857,6 +2873,7 @@ static always_inline void gen_bcond (DisasContext *ctx, int type) |
| 2857 | 2873 | uint32_t bi = BI(ctx->opcode); |
| 2858 | 2874 | uint32_t mask; |
| 2859 | 2875 | |
| 2876 | + ctx->exception = POWERPC_EXCP_BRANCH; | |
| 2860 | 2877 | if ((bo & 0x4) == 0) |
| 2861 | 2878 | gen_op_dec_ctr(); |
| 2862 | 2879 | switch(type) { |
| ... | ... | @@ -2906,7 +2923,7 @@ static always_inline void gen_bcond (DisasContext *ctx, int type) |
| 2906 | 2923 | case 6: |
| 2907 | 2924 | if (type == BCOND_IM) { |
| 2908 | 2925 | gen_goto_tb(ctx, 0, target); |
| 2909 | - goto out; | |
| 2926 | + return; | |
| 2910 | 2927 | } else { |
| 2911 | 2928 | #if defined(TARGET_PPC64) |
| 2912 | 2929 | if (ctx->sf_mode) |
| ... | ... | @@ -2985,12 +3002,12 @@ static always_inline void gen_bcond (DisasContext *ctx, int type) |
| 2985 | 3002 | #endif |
| 2986 | 3003 | gen_op_btest_T1(ctx->nip); |
| 2987 | 3004 | no_test: |
| 2988 | - if (ctx->singlestep_enabled) | |
| 3005 | + if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) { | |
| 3006 | + gen_update_nip(ctx, ctx->nip); | |
| 2989 | 3007 | gen_op_debug(); |
| 3008 | + } | |
| 2990 | 3009 | tcg_gen_exit_tb(0); |
| 2991 | 3010 | } |
| 2992 | - out: | |
| 2993 | - ctx->exception = POWERPC_EXCP_BRANCH; | |
| 2994 | 3011 | } |
| 2995 | 3012 | |
| 2996 | 3013 | GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW) |
| ... | ... | @@ -6150,7 +6167,6 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, |
| 6150 | 6167 | target_ulong pc_start; |
| 6151 | 6168 | uint16_t *gen_opc_end; |
| 6152 | 6169 | int supervisor, little_endian; |
| 6153 | - int single_step, branch_step; | |
| 6154 | 6170 | int j, lj = -1; |
| 6155 | 6171 | |
| 6156 | 6172 | pc_start = tb->pc; |
| ... | ... | @@ -6184,14 +6200,13 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, |
| 6184 | 6200 | else |
| 6185 | 6201 | ctx.altivec_enabled = 0; |
| 6186 | 6202 | if ((env->flags & POWERPC_FLAG_SE) && msr_se) |
| 6187 | - single_step = 1; | |
| 6203 | + ctx.singlestep_enabled = CPU_SINGLE_STEP; | |
| 6188 | 6204 | else |
| 6189 | - single_step = 0; | |
| 6205 | + ctx.singlestep_enabled = 0; | |
| 6190 | 6206 | if ((env->flags & POWERPC_FLAG_BE) && msr_be) |
| 6191 | - branch_step = 1; | |
| 6192 | - else | |
| 6193 | - branch_step = 0; | |
| 6194 | - ctx.singlestep_enabled = env->singlestep_enabled || single_step == 1; | |
| 6207 | + ctx.singlestep_enabled |= CPU_BRANCH_STEP; | |
| 6208 | + if (unlikely(env->singlestep_enabled)) | |
| 6209 | + ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP; | |
| 6195 | 6210 | #if defined (DO_SINGLE_STEP) && 0 |
| 6196 | 6211 | /* Single step trace mode */ |
| 6197 | 6212 | msr_se = 1; |
| ... | ... | @@ -6284,14 +6299,11 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, |
| 6284 | 6299 | handler->count++; |
| 6285 | 6300 | #endif |
| 6286 | 6301 | /* Check trace mode exceptions */ |
| 6287 | - if (unlikely(branch_step != 0 && | |
| 6288 | - ctx.exception == POWERPC_EXCP_BRANCH)) { | |
| 6289 | - GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0); | |
| 6290 | - } else if (unlikely(single_step != 0 && | |
| 6291 | - (ctx.nip <= 0x100 || ctx.nip > 0xF00 || | |
| 6292 | - (ctx.nip & 0xFC) != 0x04) && | |
| 6293 | - ctx.exception != POWERPC_SYSCALL && | |
| 6294 | - ctx.exception != POWERPC_EXCP_TRAP)) { | |
| 6302 | + if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP && | |
| 6303 | + (ctx.nip <= 0x100 || ctx.nip > 0xF00) && | |
| 6304 | + ctx.exception != POWERPC_SYSCALL && | |
| 6305 | + ctx.exception != POWERPC_EXCP_TRAP && | |
| 6306 | + ctx.exception != POWERPC_EXCP_BRANCH)) { | |
| 6295 | 6307 | GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0); |
| 6296 | 6308 | } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) || |
| 6297 | 6309 | (env->singlestep_enabled))) { |
| ... | ... | @@ -6307,6 +6319,10 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, |
| 6307 | 6319 | if (ctx.exception == POWERPC_EXCP_NONE) { |
| 6308 | 6320 | gen_goto_tb(&ctx, 0, ctx.nip); |
| 6309 | 6321 | } else if (ctx.exception != POWERPC_EXCP_BRANCH) { |
| 6322 | + if (unlikely(env->singlestep_enabled)) { | |
| 6323 | + gen_update_nip(&ctx, ctx.nip); | |
| 6324 | + gen_op_debug(); | |
| 6325 | + } | |
| 6310 | 6326 | /* Generate the return instruction */ |
| 6311 | 6327 | tcg_gen_exit_tb(0); |
| 6312 | 6328 | } | ... | ... |