From 886946dcf4125e1003823e1a2626084fd930d38c Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sat, 26 Sep 2015 16:49:00 +0800 Subject: [PATCH] do not use syscall to quit emulation. this can fix issues #147 & #148 --- qemu/aarch64.h | 1 + qemu/arm.h | 1 + qemu/cpu-exec.c | 12 ------------ qemu/header_gen.py | 1 + qemu/m68k.h | 1 + qemu/mips.h | 1 + qemu/mips64.h | 1 + qemu/mips64el.h | 1 + qemu/mipsel.h | 1 + qemu/powerpc.h | 1 + qemu/sparc.h | 1 + qemu/sparc64.h | 1 + qemu/target-arm/translate-a64.c | 6 ++++-- qemu/target-arm/translate.c | 10 +++++++--- qemu/target-i386/translate.c | 11 +++++++++-- qemu/target-m68k/translate.c | 4 ++-- qemu/target-mips/translate.c | 7 +++++-- qemu/target-sparc/helper.c | 4 ++-- qemu/target-sparc/helper.h | 2 +- qemu/target-sparc/translate.c | 14 +++++++++++++- qemu/x86_64.h | 1 + samples/sample_sparc.c | 4 ++-- 22 files changed, 57 insertions(+), 29 deletions(-) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 77de1644..b888e1cd 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_AARCH64_H #define UNICORN_AUTOGEN_AARCH64_H +#define helper_power_down helper_power_down_aarch64 #define check_exit_request check_exit_request_aarch64 #define address_space_unregister address_space_unregister_aarch64 #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_aarch64 diff --git a/qemu/arm.h b/qemu/arm.h index 3d405fac..5f70b6bf 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_ARM_H #define UNICORN_AUTOGEN_ARM_H +#define helper_power_down helper_power_down_arm #define check_exit_request check_exit_request_arm #define address_space_unregister address_space_unregister_arm #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_arm diff --git a/qemu/cpu-exec.c b/qemu/cpu-exec.c index c83485c3..01e8ca75 100644 --- a/qemu/cpu-exec.c +++ b/qemu/cpu-exec.c @@ -108,18 +108,6 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq break; } - if ((uc->arch == UC_ARCH_X86 && cpu->exception_index == 0x99) || // X86's Int 0x99 - (uc->arch == UC_ARCH_ARM && cpu->exception_index == 2) || /* ARM's EXCP_SWI */ - (uc->arch == UC_ARCH_ARM64 && cpu->exception_index == 2) || /* ARM's EXCP_SWI */ - (uc->arch == UC_ARCH_MIPS && cpu->exception_index == 17) || /* Mips's EXCP_SYSCALL */ - (uc->arch == UC_ARCH_SPARC && cpu->exception_index == 0x80) || /* Sparc's TT_TRAP */ - (uc->arch == UC_ARCH_SPARC && cpu->exception_index == 0x100) || /* Sparc64's TT_TRAP */ - (uc->arch == UC_ARCH_M68K && cpu->exception_index == 0x2f) /* M68K's EXCP_TRAP15 */ - ) { - cpu->halted = 1; - ret = EXCP_HLT; - break; - } if (cpu->exception_index >= EXCP_INTERRUPT) { /* exit request from the cpu execution loop */ ret = cpu->exception_index; diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 67982502..c5133381 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -7,6 +7,7 @@ import sys symbols = ( + 'helper_power_down', 'check_exit_request', 'address_space_unregister', 'tb_invalidate_phys_page_fast', diff --git a/qemu/m68k.h b/qemu/m68k.h index 4be757ba..8a344cbb 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_M68K_H #define UNICORN_AUTOGEN_M68K_H +#define helper_power_down helper_power_down_m68k #define check_exit_request check_exit_request_m68k #define address_space_unregister address_space_unregister_m68k #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 7a3e308a..21258098 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPS_H #define UNICORN_AUTOGEN_MIPS_H +#define helper_power_down helper_power_down_mips #define check_exit_request check_exit_request_mips #define address_space_unregister address_space_unregister_mips #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 9870cb15..d6863cc3 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPS64_H #define UNICORN_AUTOGEN_MIPS64_H +#define helper_power_down helper_power_down_mips64 #define check_exit_request check_exit_request_mips64 #define address_space_unregister address_space_unregister_mips64 #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 5fde9e53..07118619 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPS64EL_H #define UNICORN_AUTOGEN_MIPS64EL_H +#define helper_power_down helper_power_down_mips64el #define check_exit_request check_exit_request_mips64el #define address_space_unregister address_space_unregister_mips64el #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index caf1fe4d..901fb181 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPSEL_H #define UNICORN_AUTOGEN_MIPSEL_H +#define helper_power_down helper_power_down_mipsel #define check_exit_request check_exit_request_mipsel #define address_space_unregister address_space_unregister_mipsel #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index 92e614e1..35bf7578 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_POWERPC_H #define UNICORN_AUTOGEN_POWERPC_H +#define helper_power_down helper_power_down_powerpc #define check_exit_request check_exit_request_powerpc #define address_space_unregister address_space_unregister_powerpc #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index 6aa47aa5..82bab3a2 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_SPARC_H #define UNICORN_AUTOGEN_SPARC_H +#define helper_power_down helper_power_down_sparc #define check_exit_request check_exit_request_sparc #define address_space_unregister address_space_unregister_sparc #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 6d3d2a1d..ac1b66e6 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_SPARC64_H #define UNICORN_AUTOGEN_SPARC64_H +#define helper_power_down helper_power_down_sparc64 #define check_exit_request check_exit_request_sparc64 #define address_space_unregister address_space_unregister_sparc64 #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_sparc64 diff --git a/qemu/target-arm/translate-a64.c b/qemu/target-arm/translate-a64.c index d081fc49..8e267f98 100644 --- a/qemu/target-arm/translate-a64.c +++ b/qemu/target-arm/translate-a64.c @@ -10974,7 +10974,8 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s) // Unicorn: end address tells us to stop emulation if (s->pc == s->uc->addr_end) { - gen_exception_insn(s, 0, EXCP_SWI, 0); + // imitate WFI instruction to halt emulation + s->is_jmp = DISAS_WFI; return; } @@ -11107,8 +11108,9 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, // Unicorn: early check to see if the address of this block is the until address if (tb->pc == env->uc->addr_end) { + // imitate WFI instruction to halt emulation gen_tb_start(tcg_ctx); - gen_exception_insn(dc, 0, EXCP_SWI, 0); + dc->is_jmp = DISAS_WFI; goto done_generating; } diff --git a/qemu/target-arm/translate.c b/qemu/target-arm/translate.c index 8875b641..585ca07c 100644 --- a/qemu/target-arm/translate.c +++ b/qemu/target-arm/translate.c @@ -10396,7 +10396,8 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq // Unicorn: end address tells us to stop emulation if (s->pc == s->uc->addr_end) { - gen_exception_insn(s, 0, EXCP_SWI, 0); + // imitate WFI instruction to halt emulation + s->is_jmp = DISAS_WFI; return; } @@ -11230,8 +11231,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, // Unicorn: early check to see if the address of this block is the until address if (tb->pc == env->uc->addr_end) { + // imitate WFI instruction to halt emulation gen_tb_start(tcg_ctx); - gen_exception_insn(dc, 0, EXCP_SWI, 0); + dc->is_jmp = DISAS_WFI; goto done_generating; } @@ -11289,6 +11291,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, store_cpu_field(tcg_ctx, tmp, condexec_bits); } do { + //printf(">>> arm pc = %x\n", dc->pc); #ifdef CONFIG_USER_ONLY /* Intercept jump to the magic kernel page. */ if (dc->pc >= 0xffff0000) { @@ -11370,7 +11373,8 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, // end address tells us to stop emulation if (dc->pc == dc->uc->addr_end) { - gen_exception_insn(dc, 0, EXCP_SWI, 0); + // imitate WFI instruction to halt emulation + dc->is_jmp = DISAS_WFI; } else { insn = arm_ldl_code(env, dc->pc, dc->bswap_code); dc->pc += 4; diff --git a/qemu/target-i386/translate.c b/qemu/target-i386/translate.c index 84db6114..a920689c 100644 --- a/qemu/target-i386/translate.c +++ b/qemu/target-i386/translate.c @@ -4751,7 +4751,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, // end address tells us to stop emulation if (s->pc == s->uc->addr_end) { - gen_interrupt(s, 0x99, pc_start - s->cs_base, pc_start - s->cs_base); + // imitate the HLT instruction + gen_update_cc_op(s); + gen_jmp_im(s, pc_start - s->cs_base); + gen_helper_hlt(tcg_ctx, cpu_env, tcg_const_i32(tcg_ctx, s->pc - pc_start)); + s->is_jmp = DISAS_TB_JUMP; return s->pc; } @@ -8361,8 +8365,11 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op, // early check to see if the address of this block is the until address if (tb->pc == env->uc->addr_end) { + // imitate the HLT instruction gen_tb_start(tcg_ctx); - gen_interrupt(dc, 0x99, tb->pc - tb->cs_base, tb->pc - tb->cs_base); + gen_jmp_im(dc, tb->pc - tb->cs_base); + gen_helper_hlt(tcg_ctx, tcg_ctx->cpu_env, tcg_const_i32(tcg_ctx, 0)); + dc->is_jmp = DISAS_TB_JUMP; goto done_generating; } diff --git a/qemu/target-m68k/translate.c b/qemu/target-m68k/translate.c index fedffecc..109c7f1f 100644 --- a/qemu/target-m68k/translate.c +++ b/qemu/target-m68k/translate.c @@ -3038,7 +3038,7 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s) // Unicorn: end address tells us to stop emulation if (s->pc == s->uc->addr_end) { - gen_exception(s, s->pc, EXCP_TRAP15); + gen_exception(s, s->pc, EXCP_HLT); return; } @@ -3104,7 +3104,7 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, // Unicorn: early check to see if the address of this block is the until address if (tb->pc == env->uc->addr_end) { gen_tb_start(tcg_ctx); - gen_exception(dc, dc->pc, EXCP_TRAP15); + gen_exception(dc, dc->pc, EXCP_HLT); goto done_generating; } diff --git a/qemu/target-mips/translate.c b/qemu/target-mips/translate.c index e1ff51a7..d9d73f38 100644 --- a/qemu/target-mips/translate.c +++ b/qemu/target-mips/translate.c @@ -19211,7 +19211,8 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, // Unicorn: early check to see if the address of this block is the until address if (tb->pc == env->uc->addr_end) { gen_tb_start(tcg_ctx); - generate_exception(&ctx, EXCP_SYSCALL); + gen_helper_wait(tcg_ctx, tcg_ctx->cpu_env); + ctx.bstate = BS_EXCP; goto done_generating; } @@ -19229,6 +19230,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, gen_tb_start(tcg_ctx); while (ctx.bstate == BS_NONE) { + // printf(">>> mips pc = %x\n", ctx.pc); if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { if (bp->pc == ctx.pc) { @@ -19261,7 +19263,8 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, // Unicorn: end address tells us to stop emulation if (ctx.pc == ctx.uc->addr_end) { - generate_exception(&ctx, EXCP_SYSCALL); + gen_helper_wait(tcg_ctx, tcg_ctx->cpu_env); + ctx.bstate = BS_EXCP; break; } else { // Unicorn: save param buffer diff --git a/qemu/target-sparc/helper.c b/qemu/target-sparc/helper.c index 98a80fe5..8f60d0ae 100644 --- a/qemu/target-sparc/helper.c +++ b/qemu/target-sparc/helper.c @@ -241,7 +241,7 @@ target_ulong helper_tsubcctv(CPUSPARCState *env, target_ulong src1, helper_raise_exception(env, TT_TOVF); } -#ifndef TARGET_SPARC64 +//#ifndef TARGET_SPARC64 void helper_power_down(CPUSPARCState *env) { CPUState *cs = CPU(sparc_env_get_cpu(env)); @@ -252,4 +252,4 @@ void helper_power_down(CPUSPARCState *env) env->npc = env->pc + 4; cpu_loop_exit(cs); } -#endif +//#endif diff --git a/qemu/target-sparc/helper.h b/qemu/target-sparc/helper.h index 14c8a335..2557dd08 100644 --- a/qemu/target-sparc/helper.h +++ b/qemu/target-sparc/helper.h @@ -1,10 +1,10 @@ DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr) +DEF_HELPER_1(power_down, void, env) #ifndef TARGET_SPARC64 DEF_HELPER_1(rett, void, env) DEF_HELPER_2(wrpsr, void, env, tl) DEF_HELPER_1(rdpsr, tl, env) -DEF_HELPER_1(power_down, void, env) #else DEF_HELPER_2(wrpil, void, env, tl) DEF_HELPER_2(wrpstate, void, env, tl) diff --git a/qemu/target-sparc/translate.c b/qemu/target-sparc/translate.c index ff68fd64..35516676 100644 --- a/qemu/target-sparc/translate.c +++ b/qemu/target-sparc/translate.c @@ -5405,6 +5405,14 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, if (max_insns == 0) max_insns = CF_COUNT_MASK; + // Unicorn: early check to see if the address of this block is the until address + if (tb->pc == env->uc->addr_end) { + gen_tb_start(tcg_ctx); + save_state(dc); + gen_helper_power_down(tcg_ctx, tcg_ctx->cpu_env); + goto done_generating; + } + // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache @@ -5448,7 +5456,9 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, // gen_io_start(); // Unicorn: end address tells us to stop emulation if (dc->pc == dc->uc->addr_end) { - insn = 0x91d02000; // generate TRAP to end this TB + save_state(dc); + gen_helper_power_down(tcg_ctx, tcg_ctx->cpu_env); + break; } else { last_pc = dc->pc; insn = cpu_ldl_code(env, dc->pc); @@ -5497,6 +5507,8 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, tcg_gen_exit_tb(tcg_ctx, 0); } } + +done_generating: gen_tb_end(tcg_ctx, tb, num_insns); *tcg_ctx->gen_opc_ptr = INDEX_op_end; if (spc) { diff --git a/qemu/x86_64.h b/qemu/x86_64.h index ac9f34f0..9c133773 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_X86_64_H #define UNICORN_AUTOGEN_X86_64_H +#define helper_power_down helper_power_down_x86_64 #define check_exit_request check_exit_request_x86_64 #define address_space_unregister address_space_unregister_x86_64 #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_x86_64 diff --git a/samples/sample_sparc.c b/samples/sample_sparc.c index 3f253ff1..45c185a5 100644 --- a/samples/sample_sparc.c +++ b/samples/sample_sparc.c @@ -59,8 +59,8 @@ static void test_sparc(void) // tracing all basic blocks with customized callback uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); - // tracing one instruction at ADDRESS with customized callback - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + // tracing all instructions with customized callback + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); // emulate machine code in infinite time (last param = 0), or when // finishing all the code.