Merge branch 'icount-update' into HEAD
authorPaolo Bonzini <pbonzini@redhat.com>
Fri, 3 Mar 2017 15:39:18 +0000 (16:39 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 3 Mar 2017 15:39:18 +0000 (16:39 +0100)
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 <pbonzini@redhat.com>
1  2 
cpu-exec.c
include/qom/cpu.h
qom/cpu.c
tcg/tcg.h
translate-all.c
translate-common.c

diff --cc cpu-exec.c
index 1a5ad4889d382f72af84fbbdf93cae3eb1918303,7db959c82172763fdeb9ad280333d3e2f158340c..d04dd91ebd2390cfd8e40ef13acc3139906ddd0d
@@@ -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 */
Simple merge
diff --cc qom/cpu.c
Simple merge
diff --cc tcg/tcg.h
Simple merge
diff --cc translate-all.c
index 9bac061c9b4e85b179eeee7380b1a3c07dc8f264,1a21e3fb1f86b2359e979f9d572a52f882c17fa1..d42d003e674d4d0f806e9dfe0d159c8adacfb8d4
@@@ -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;
  }
  
  /*
index d504dd0d33631aa133f7f2b060b23d54c5a534d3,77762fd86c3fcd77519785ca3785f9171a1db7e5..40fe5a19bb3c2ec14f0f2ac58e78db95cbc89aea
@@@ -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");
 +        }
      }
  }