On Tue, Apr 10, 2018 at 13:56:25 +1000, Richard Henderson wrote: > Ok, well, there are existing bugs within the MIPS translation here, and we > might as well fix them within this patch set. > > (1) The description for BS_STOP says we want to stop, but (what will become) > mips_tr_tb_stop calls goto_tb. > > That's not correct, since we use that after e.g. helper_mtc0_hwrena, > MIPS_HFLAG_HWRENA_ULR is included in tb->flags, and therefore the next TB is > not fixed but depends on the actual value stored into hwrena. > > We should instead use lookup_and_goto_ptr, which does a full lookup of the > processor state every time through.
I thought I understood what you meant here but the corresponding change doesn't seem to work; without the change I can boot a guest in ~1m20s; with it, boot-up gets stuck -- or at the very least, it's so slow that I'm giving up after 3+ minutes. The change I made: --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -20339,7 +20339,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) } else { switch (ctx.is_jmp) { case DISAS_STOP: - gen_goto_tb(&ctx, 0, ctx.pc); + tcg_gen_lookup_and_goto_ptr(); break; So I'm afraid I don't understand what the change should be, then. > (2) The BS_EXCP in generate_exception_err should map to DISAS_NORETURN, > because > we do not return after raising an exception. > > (3) Otherwise, the use of BS_EXCP has nothing to do with an exception; e.g. > > > case 0: > > save_cpu_state(ctx, 1); > > gen_helper_mtc0_status(cpu_env, arg); > > /* BS_STOP isn't good enough here, hflags may have changed. */ > > gen_save_pc(ctx->pc + 4); > > ctx->bstate = BS_EXCP; > > rn = "Status"; > > break; > > where we are in fact relying on (what will become) mips_tr_tb_stop to emit > exit_tb. It would be better to name these uses DISAS_EXIT, which would match > e.g. target/arm. Thanks for this -- delta with (2) and (3) below. Emilio --- diff --git a/target/mips/translate.c b/target/mips/translate.c index 99ecfa1..4183ec2 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -1463,6 +1463,7 @@ typedef struct DisasContext { #define DISAS_STOP DISAS_TARGET_0 #define DISAS_EXCP DISAS_TARGET_1 +#define DISAS_EXIT DISAS_TARGET_2 static const char * const regnames[] = { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", @@ -1635,7 +1636,7 @@ static inline void generate_exception_err(DisasContext *ctx, int excp, int err) gen_helper_raise_exception_err(cpu_env, texcp, terr); tcg_temp_free_i32(terr); tcg_temp_free_i32(texcp); - ctx->is_jmp = DISAS_EXCP; + ctx->is_jmp = DISAS_NORETURN; } static inline void generate_exception(DisasContext *ctx, int excp) @@ -5333,7 +5334,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) after reading count. DISAS_STOP isn't sufficient, we need to ensure we break completely out of translated code. */ gen_save_pc(ctx->pc + 4); - ctx->is_jmp = DISAS_EXCP; + ctx->is_jmp = DISAS_EXIT; rn = "Count"; break; /* 6,7 are implementation dependent */ @@ -6026,7 +6027,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mtc0_status(cpu_env, arg); /* DISAS_STOP isn't good enough here, hflags may have changed. */ gen_save_pc(ctx->pc + 4); - ctx->is_jmp = DISAS_EXCP; + ctx->is_jmp = DISAS_EXIT; rn = "Status"; break; case 1: @@ -6063,7 +6064,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) * DISAS_STOP isn't sufficient, we need to ensure we break out of * translated code to check for pending interrupts. */ gen_save_pc(ctx->pc + 4); - ctx->is_jmp = DISAS_EXCP; + ctx->is_jmp = DISAS_EXIT; rn = "Cause"; break; default: @@ -6219,7 +6220,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */ /* DISAS_STOP isn't good enough here, hflags may have changed. */ gen_save_pc(ctx->pc + 4); - ctx->is_jmp = DISAS_EXCP; + ctx->is_jmp = DISAS_EXIT; rn = "Debug"; break; case 1: @@ -6401,7 +6402,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) /* DISAS_STOP isn't sufficient, we need to ensure we break out of * translated code to check for pending interrupts. */ gen_save_pc(ctx->pc + 4); - ctx->is_jmp = DISAS_EXCP; + ctx->is_jmp = DISAS_EXIT; } return; @@ -6685,7 +6686,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) after reading count. DISAS_STOP isn't sufficient, we need to ensure we break completely out of translated code. */ gen_save_pc(ctx->pc + 4); - ctx->is_jmp = DISAS_EXCP; + ctx->is_jmp = DISAS_EXIT; rn = "Count"; break; /* 6,7 are implementation dependent */ @@ -7365,7 +7366,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mtc0_status(cpu_env, arg); /* DISAS_STOP isn't good enough here, hflags may have changed. */ gen_save_pc(ctx->pc + 4); - ctx->is_jmp = DISAS_EXCP; + ctx->is_jmp = DISAS_EXIT; rn = "Status"; break; case 1: @@ -7402,7 +7403,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) * DISAS_STOP isn't sufficient, we need to ensure we break out of * translated code to check for pending interrupts. */ gen_save_pc(ctx->pc + 4); - ctx->is_jmp = DISAS_EXCP; + ctx->is_jmp = DISAS_EXIT; rn = "Cause"; break; default: @@ -7547,7 +7548,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */ /* DISAS_STOP isn't good enough here, hflags may have changed. */ gen_save_pc(ctx->pc + 4); - ctx->is_jmp = DISAS_EXCP; + ctx->is_jmp = DISAS_EXIT; rn = "Debug"; break; case 1: @@ -7727,7 +7728,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) /* DISAS_STOP isn't sufficient, we need to ensure we break out of * translated code to check for pending interrupts. */ gen_save_pc(ctx->pc + 4); - ctx->is_jmp = DISAS_EXCP; + ctx->is_jmp = DISAS_EXIT; } return; @@ -10763,7 +10764,7 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel) after reading count. DISAS_STOP isn't sufficient, we need to ensure we break completely out of translated code. */ gen_save_pc(ctx->pc + 4); - ctx->is_jmp = DISAS_EXCP; + ctx->is_jmp = DISAS_EXIT; break; case 3: gen_helper_rdhwr_ccres(t0, cpu_env); @@ -13585,7 +13586,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs) /* DISAS_STOP isn't sufficient, we need to ensure we break out of translated code to check for pending interrupts. */ gen_save_pc(ctx->pc + 4); - ctx->is_jmp = DISAS_EXCP; + ctx->is_jmp = DISAS_EXIT; tcg_temp_free(t0); } break; @@ -19710,7 +19711,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) /* DISAS_STOP isn't sufficient, we need to ensure we break out of translated code to check for pending interrupts */ gen_save_pc(ctx->pc + 4); - ctx->is_jmp = DISAS_EXCP; + ctx->is_jmp = DISAS_EXIT; break; default: /* Invalid */ MIPS_INVAL("mfmc0"); @@ -20346,6 +20347,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) gen_goto_tb(&ctx, 0, ctx.pc); break; case DISAS_EXCP: + case DISAS_EXIT: tcg_gen_exit_tb(0); break; case DISAS_NORETURN: