From: Paolo Bonzini Date: Fri, 3 Mar 2017 15:39:18 +0000 (+0100) Subject: Merge branch 'icount-update' into HEAD X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=30f3dda24b2a4cd30f8fbf984ab08ef08eaf5020;p=qemu.git Merge branch 'icount-update' into HEAD Merge the original development branch due to breakage caused by the MTTCG merge. Conflicts: cpu-exec.c translate-common.c Signed-off-by: Paolo Bonzini --- 30f3dda24b2a4cd30f8fbf984ab08ef08eaf5020 diff --cc cpu-exec.c index 1a5ad4889d,7db959c821..d04dd91ebd --- a/cpu-exec.c +++ b/cpu-exec.c @@@ -555,13 -516,11 +549,14 @@@ static inline bool cpu_handle_interrupt the program flow was changed */ *last_tb = NULL; } + + /* If we exit via cpu_loop_exit/longjmp it is reset in cpu_exec */ + qemu_mutex_unlock_iothread(); } - - if (unlikely(atomic_read(&cpu->exit_request) || replay_has_interrupt())) { + /* Finally, check if we need to exit to the main loop. */ + if (unlikely(atomic_read(&cpu->exit_request) + || (use_icount && cpu->icount_decr.u16.low + cpu->icount_extra == 0))) { atomic_set(&cpu->exit_request, 0); cpu->exception_index = EXCP_INTERRUPT; return true; @@@ -584,49 -539,47 +575,45 @@@ static inline void cpu_loop_exec_tb(CPU ret = cpu_tb_exec(cpu, tb); tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK); *tb_exit = ret & TB_EXIT_MASK; - switch (*tb_exit) { - case TB_EXIT_REQUESTED: + if (*tb_exit != TB_EXIT_REQUESTED) { + *last_tb = tb; + return; + } + + *last_tb = NULL; + insns_left = atomic_read(&cpu->icount_decr.u32); + atomic_set(&cpu->icount_decr.u16.high, 0); + if (insns_left < 0) { - /* Something asked us to stop executing - * chained TBs; just continue round the main - * loop. Whatever requested the exit will also - * have set something else (eg exit_request or - * interrupt_request) which we will handle - * next time around the loop. But we need to - * ensure the zeroing of tcg_exit_req (see cpu_tb_exec) + /* Something asked us to stop executing chained TBs; just + * continue round the main loop. Whatever requested the exit - * will also have set something else (eg interrupt_request) - * which we will handle next time around the loop. But we - * need to ensure the tcg_exit_req read in generated code - * comes before the next read of cpu->exit_request or - * cpu->interrupt_request. ++ * will also have set something else (eg exit_request or ++ * interrupt_request) which we will handle next time around ++ * the loop. But we need to ensure the zeroing of icount_decr + * comes before the next read of cpu->exit_request + * or cpu->interrupt_request. */ smp_mb(); - *last_tb = NULL; - break; - case TB_EXIT_ICOUNT_EXPIRED: - { - /* Instruction counter expired. */ - #ifdef CONFIG_USER_ONLY - abort(); - #else - int insns_left = cpu->icount_decr.u32; - *last_tb = NULL; - if (cpu->icount_extra && insns_left >= 0) { - /* Refill decrementer and continue execution. */ - cpu->icount_extra += insns_left; - insns_left = MIN(0xffff, cpu->icount_extra); - cpu->icount_extra -= insns_left; - cpu->icount_decr.u16.low = insns_left; - } else { - if (insns_left > 0) { - /* Execute remaining instructions. */ - cpu_exec_nocache(cpu, insns_left, tb, false); - align_clocks(sc, cpu); - } - cpu->exception_index = EXCP_INTERRUPT; - cpu_loop_exit(cpu); - } - break; - #endif + return; } - default: - *last_tb = tb; - break; + + /* Instruction counter expired. */ + assert(use_icount); + #ifndef CONFIG_USER_ONLY + if (cpu->icount_extra) { + /* Refill decrementer and continue execution. */ + cpu->icount_extra += insns_left; + insns_left = MIN(0xffff, cpu->icount_extra); + cpu->icount_extra -= insns_left; + cpu->icount_decr.u16.low = insns_left; + } else { + /* Execute any remaining instructions, then let the main loop + * handle the next event. + */ + if (insns_left > 0) { + cpu_exec_nocache(cpu, insns_left, tb, false); + } } + #endif } /* main execution loop */ diff --cc translate-all.c index 9bac061c9b,1a21e3fb1f..d42d003e67 --- a/translate-all.c +++ b/translate-all.c @@@ -1928,9 -1957,8 +1928,9 @@@ void dump_opcount_info(FILE *f, fprintf void cpu_interrupt(CPUState *cpu, int mask) { + g_assert(qemu_mutex_iothread_locked()); cpu->interrupt_request |= mask; - cpu->tcg_exit_req = 1; + cpu->icount_decr.u16.high = -1; } /* diff --cc translate-common.c index d504dd0d33,77762fd86c..40fe5a19bb --- a/translate-common.c +++ b/translate-common.c @@@ -42,16 -40,14 +42,13 @@@ static void tcg_handle_interrupt(CPUSta */ if (!qemu_cpu_is_self(cpu)) { qemu_cpu_kick(cpu); - return; - } - - cpu->icount_decr.u16.high = -1; - if (use_icount && - !cpu->can_do_io - && (mask & ~old_mask) != 0) { - cpu_abort(cpu, "Raised interrupt while not in I/O function"); + } else { - if (use_icount) { - cpu->icount_decr.u16.high = 0xffff; - if (!cpu->can_do_io - && (mask & ~old_mask) != 0) { - cpu_abort(cpu, "Raised interrupt while not in I/O function"); - } - } else { - cpu->tcg_exit_req = 1; ++ cpu->icount_decr.u16.high = -1; ++ if (use_icount && ++ !cpu->can_do_io ++ && (mask & ~old_mask) != 0) { ++ cpu_abort(cpu, "Raised interrupt while not in I/O function"); + } } }