All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/5] cpu-exec: Restructure cpu_exec()
@ 2016-05-11 10:21 Sergey Fedorov
  2016-05-11 10:21 ` [Qemu-devel] [PATCH 1/5] cpu-exec: Move halt handling out of cpu_exec() Sergey Fedorov
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Sergey Fedorov @ 2016-05-11 10:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Sergey Fedorov, Alex Bennée, Richard Henderson,
	Paolo Bonzini, Peter Crosthwaite

From: Sergey Fedorov <serge.fdrv@gmail.com>

cpu_exec() was a huge function also sprinkled with some preprocessor
directives. It was hard to read and see the main loop crowded by all
this code. Restructure cpu_exec() by moving its conceptual parts into
separate static inline functions. That makes it possible to see the
whole main loop at once, especially its sigsetjmp() handling part.

This series is based on commit
    40f646483a11 (cpu-exec: Remove relic orphaned comment)
from
    git://github.com/rth7680/qemu.git tcg-next
and is available at
    git://github.com/sergefdrv/qemu.git cpu_exec-restructure-v2

Summary of changes in v2:
 * Declare x86_cpu variable in the inner-most block [PATCH 1/5]

Sergey Fedorov (5):
  cpu-exec: Move halt handling out of cpu_exec()
  cpu-exec: Move exception handling out of cpu_exec()
  cpu-exec: Move interrupt handling out of cpu_exec()
  cpu-exec: Move TB execution stuff out of cpu_exec()
  cpu-exec: Remove unused 'x86_cpu' and 'env' from cpu_exec()

 cpu-exec.c | 395 +++++++++++++++++++++++++++++++++----------------------------
 1 file changed, 211 insertions(+), 184 deletions(-)

-- 
1.9.1

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 1/5] cpu-exec: Move halt handling out of cpu_exec()
  2016-05-11 10:21 [Qemu-devel] [PATCH 0/5] cpu-exec: Restructure cpu_exec() Sergey Fedorov
@ 2016-05-11 10:21 ` Sergey Fedorov
  2016-05-11 10:21 ` [Qemu-devel] [PATCH 2/5] cpu-exec: Move exception " Sergey Fedorov
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Sergey Fedorov @ 2016-05-11 10:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Sergey Fedorov, Sergey Fedorov, Paolo Bonzini, Peter Crosthwaite,
	Richard Henderson

From: Sergey Fedorov <serge.fdrv@gmail.com>

Simplify cpu_exec() by extracting CPU halt state handling code out of
cpu_exec() into a new static inline function cpu_handle_halt().

Signed-off-by: Sergey Fedorov <serge.fdrv@gmail.com>
Signed-off-by: Sergey Fedorov <sergey.fedorov@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---

Changes in v2:
 * Declare x86_cpu variable in the inner-most block

 cpu-exec.c | 39 +++++++++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 14 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index d55faa5114c7..1fcdc3fabb39 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -352,6 +352,29 @@ static inline TranslationBlock *tb_find_fast(CPUState *cpu,
     return tb;
 }
 
+static inline bool cpu_handle_halt(CPUState *cpu)
+{
+    if (cpu->halted) {
+#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
+
+        if ((cpu->interrupt_request & CPU_INTERRUPT_POLL)
+            && replay_interrupt()) {
+            X86CPU *x86_cpu = X86_CPU(cpu);
+            apic_poll_irq(x86_cpu->apic_state);
+            cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
+        }
+#endif
+        if (!cpu_has_work(cpu)) {
+            current_cpu = NULL;
+            return true;
+        }
+
+        cpu->halted = 0;
+    }
+
+    return false;
+}
+
 static void cpu_handle_debug_exception(CPUState *cpu)
 {
     CPUClass *cc = CPU_GET_CLASS(cpu);
@@ -383,20 +406,8 @@ int cpu_exec(CPUState *cpu)
     /* replay_interrupt may need current_cpu */
     current_cpu = cpu;
 
-    if (cpu->halted) {
-#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
-        if ((cpu->interrupt_request & CPU_INTERRUPT_POLL)
-            && replay_interrupt()) {
-            apic_poll_irq(x86_cpu->apic_state);
-            cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
-        }
-#endif
-        if (!cpu_has_work(cpu)) {
-            current_cpu = NULL;
-            return EXCP_HALTED;
-        }
-
-        cpu->halted = 0;
+    if (cpu_handle_halt(cpu)) {
+        return EXCP_HALTED;
     }
 
     atomic_mb_set(&tcg_current_cpu, cpu);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 2/5] cpu-exec: Move exception handling out of cpu_exec()
  2016-05-11 10:21 [Qemu-devel] [PATCH 0/5] cpu-exec: Restructure cpu_exec() Sergey Fedorov
  2016-05-11 10:21 ` [Qemu-devel] [PATCH 1/5] cpu-exec: Move halt handling out of cpu_exec() Sergey Fedorov
@ 2016-05-11 10:21 ` Sergey Fedorov
  2016-05-11 10:21 ` [Qemu-devel] [PATCH 3/5] cpu-exec: Move interrupt " Sergey Fedorov
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Sergey Fedorov @ 2016-05-11 10:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Sergey Fedorov, Sergey Fedorov, Paolo Bonzini, Peter Crosthwaite,
	Richard Henderson

From: Sergey Fedorov <serge.fdrv@gmail.com>

Simplify cpu_exec() by extracting exception handling code out of
cpu_exec() into a new static inline function cpu_handle_exception().
Also make cpu_handle_debug_exception() inline as it is used only once.

Signed-off-by: Sergey Fedorov <serge.fdrv@gmail.com>
Signed-off-by: Sergey Fedorov <sergey.fedorov@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 cpu-exec.c | 93 +++++++++++++++++++++++++++++++++++---------------------------
 1 file changed, 52 insertions(+), 41 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index 1fcdc3fabb39..f7e175e9ae1c 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -375,7 +375,7 @@ static inline bool cpu_handle_halt(CPUState *cpu)
     return false;
 }
 
-static void cpu_handle_debug_exception(CPUState *cpu)
+static inline void cpu_handle_debug_exception(CPUState *cpu)
 {
     CPUClass *cc = CPU_GET_CLASS(cpu);
     CPUWatchpoint *wp;
@@ -389,6 +389,55 @@ static void cpu_handle_debug_exception(CPUState *cpu)
     cc->debug_excp_handler(cpu);
 }
 
+static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
+{
+    if (cpu->exception_index >= 0) {
+        if (cpu->exception_index >= EXCP_INTERRUPT) {
+            /* exit request from the cpu execution loop */
+            *ret = cpu->exception_index;
+            if (*ret == EXCP_DEBUG) {
+                cpu_handle_debug_exception(cpu);
+            }
+            cpu->exception_index = -1;
+            return true;
+        } else {
+#if defined(CONFIG_USER_ONLY)
+            /* if user mode only, we simulate a fake exception
+               which will be handled outside the cpu execution
+               loop */
+#if defined(TARGET_I386)
+            CPUClass *cc = CPU_GET_CLASS(cpu);
+            cc->do_interrupt(cpu);
+#endif
+            *ret = cpu->exception_index;
+            cpu->exception_index = -1;
+            return true;
+#else
+            if (replay_exception()) {
+                CPUClass *cc = CPU_GET_CLASS(cpu);
+                cc->do_interrupt(cpu);
+                cpu->exception_index = -1;
+            } else if (!replay_has_interrupt()) {
+                /* give a chance to iothread in replay mode */
+                *ret = EXCP_INTERRUPT;
+                return true;
+            }
+#endif
+        }
+#ifndef CONFIG_USER_ONLY
+    } else if (replay_has_exception()
+               && cpu->icount_decr.u16.low + cpu->icount_extra == 0) {
+        /* try to cause an exception pending in the log */
+        TranslationBlock *last_tb = NULL; /* Avoid chaining TBs */
+        cpu_exec_nocache(cpu, 1, tb_find_fast(cpu, &last_tb, 0), true);
+        *ret = -1;
+        return true;
+#endif
+    }
+
+    return false;
+}
+
 /* main execution loop */
 
 int cpu_exec(CPUState *cpu)
@@ -426,50 +475,12 @@ int cpu_exec(CPUState *cpu)
      */
     init_delay_params(&sc, cpu);
 
-    /* prepare setjmp context for exception handling */
     for(;;) {
+        /* prepare setjmp context for exception handling */
         if (sigsetjmp(cpu->jmp_env, 0) == 0) {
             /* if an exception is pending, we execute it here */
-            if (cpu->exception_index >= 0) {
-                if (cpu->exception_index >= EXCP_INTERRUPT) {
-                    /* exit request from the cpu execution loop */
-                    ret = cpu->exception_index;
-                    if (ret == EXCP_DEBUG) {
-                        cpu_handle_debug_exception(cpu);
-                    }
-                    cpu->exception_index = -1;
-                    break;
-                } else {
-#if defined(CONFIG_USER_ONLY)
-                    /* if user mode only, we simulate a fake exception
-                       which will be handled outside the cpu execution
-                       loop */
-#if defined(TARGET_I386)
-                    cc->do_interrupt(cpu);
-#endif
-                    ret = cpu->exception_index;
-                    cpu->exception_index = -1;
-                    break;
-#else
-                    if (replay_exception()) {
-                        cc->do_interrupt(cpu);
-                        cpu->exception_index = -1;
-                    } else if (!replay_has_interrupt()) {
-                        /* give a chance to iothread in replay mode */
-                        ret = EXCP_INTERRUPT;
-                        break;
-                    }
-#endif
-                }
-#ifndef CONFIG_USER_ONLY
-            } else if (replay_has_exception()
-                       && cpu->icount_decr.u16.low + cpu->icount_extra == 0) {
-                /* try to cause an exception pending in the log */
-                last_tb = NULL; /* Avoid chaining TBs */
-                cpu_exec_nocache(cpu, 1, tb_find_fast(cpu, &last_tb, 0), true);
-                ret = -1;
+            if (cpu_handle_exception(cpu, &ret)) {
                 break;
-#endif
             }
 
             last_tb = NULL; /* forget the last executed TB after exception */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 3/5] cpu-exec: Move interrupt handling out of cpu_exec()
  2016-05-11 10:21 [Qemu-devel] [PATCH 0/5] cpu-exec: Restructure cpu_exec() Sergey Fedorov
  2016-05-11 10:21 ` [Qemu-devel] [PATCH 1/5] cpu-exec: Move halt handling out of cpu_exec() Sergey Fedorov
  2016-05-11 10:21 ` [Qemu-devel] [PATCH 2/5] cpu-exec: Move exception " Sergey Fedorov
@ 2016-05-11 10:21 ` Sergey Fedorov
  2016-05-11 10:21 ` [Qemu-devel] [PATCH 4/5] cpu-exec: Move TB execution stuff " Sergey Fedorov
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Sergey Fedorov @ 2016-05-11 10:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Sergey Fedorov, Sergey Fedorov, Paolo Bonzini, Peter Crosthwaite,
	Richard Henderson

From: Sergey Fedorov <serge.fdrv@gmail.com>

Simplify cpu_exec() by extracting interrupt handling code outside of
cpu_exec() into a new static inline function cpu_handle_interrupt().

Signed-off-by: Sergey Fedorov <serge.fdrv@gmail.com>
Signed-off-by: Sergey Fedorov <sergey.fedorov@linaro.org>
Reviewed-by: Richard Henderson  <rth@twiddle.net>
---
 cpu-exec.c | 132 ++++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 70 insertions(+), 62 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index f7e175e9ae1c..a053b5e73af1 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -438,6 +438,74 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
     return false;
 }
 
+static inline void cpu_handle_interrupt(CPUState *cpu,
+                                        TranslationBlock **last_tb)
+{
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+    int interrupt_request = cpu->interrupt_request;
+
+    if (unlikely(interrupt_request)) {
+        if (unlikely(cpu->singlestep_enabled & SSTEP_NOIRQ)) {
+            /* Mask out external interrupts for this step. */
+            interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
+        }
+        if (interrupt_request & CPU_INTERRUPT_DEBUG) {
+            cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
+            cpu->exception_index = EXCP_DEBUG;
+            cpu_loop_exit(cpu);
+        }
+        if (replay_mode == REPLAY_MODE_PLAY && !replay_has_interrupt()) {
+            /* Do nothing */
+        } else if (interrupt_request & CPU_INTERRUPT_HALT) {
+            replay_interrupt();
+            cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
+            cpu->halted = 1;
+            cpu->exception_index = EXCP_HLT;
+            cpu_loop_exit(cpu);
+        }
+#if defined(TARGET_I386)
+        else if (interrupt_request & CPU_INTERRUPT_INIT) {
+            X86CPU *x86_cpu = X86_CPU(cpu);
+            CPUArchState *env = &x86_cpu->env;
+            replay_interrupt();
+            cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, 0);
+            do_cpu_init(x86_cpu);
+            cpu->exception_index = EXCP_HALTED;
+            cpu_loop_exit(cpu);
+        }
+#else
+        else if (interrupt_request & CPU_INTERRUPT_RESET) {
+            replay_interrupt();
+            cpu_reset(cpu);
+            cpu_loop_exit(cpu);
+        }
+#endif
+        /* The target hook has 3 exit conditions:
+           False when the interrupt isn't processed,
+           True when it is, and we should restart on a new TB,
+           and via longjmp via cpu_loop_exit.  */
+        else {
+            replay_interrupt();
+            if (cc->cpu_exec_interrupt(cpu, interrupt_request)) {
+                *last_tb = NULL;
+            }
+        }
+        /* Don't use the cached interrupt_request value,
+           do_interrupt may have updated the EXITTB flag. */
+        if (cpu->interrupt_request & CPU_INTERRUPT_EXITTB) {
+            cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
+            /* ensure that no TB jump will be modified as
+               the program flow was changed */
+            *last_tb = NULL;
+        }
+    }
+    if (unlikely(cpu->exit_request || replay_has_interrupt())) {
+        cpu->exit_request = 0;
+        cpu->exception_index = EXCP_INTERRUPT;
+        cpu_loop_exit(cpu);
+    }
+}
+
 /* main execution loop */
 
 int cpu_exec(CPUState *cpu)
@@ -447,7 +515,7 @@ int cpu_exec(CPUState *cpu)
     X86CPU *x86_cpu = X86_CPU(cpu);
     CPUArchState *env = &x86_cpu->env;
 #endif
-    int ret, interrupt_request;
+    int ret;
     TranslationBlock *tb, *last_tb;
     int tb_exit = 0;
     SyncClocks sc;
@@ -486,67 +554,7 @@ int cpu_exec(CPUState *cpu)
             last_tb = NULL; /* forget the last executed TB after exception */
             cpu->tb_flushed = false; /* reset before first TB lookup */
             for(;;) {
-                interrupt_request = cpu->interrupt_request;
-                if (unlikely(interrupt_request)) {
-                    if (unlikely(cpu->singlestep_enabled & SSTEP_NOIRQ)) {
-                        /* Mask out external interrupts for this step. */
-                        interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
-                    }
-                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
-                        cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
-                        cpu->exception_index = EXCP_DEBUG;
-                        cpu_loop_exit(cpu);
-                    }
-                    if (replay_mode == REPLAY_MODE_PLAY
-                        && !replay_has_interrupt()) {
-                        /* Do nothing */
-                    } else if (interrupt_request & CPU_INTERRUPT_HALT) {
-                        replay_interrupt();
-                        cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
-                        cpu->halted = 1;
-                        cpu->exception_index = EXCP_HLT;
-                        cpu_loop_exit(cpu);
-                    }
-#if defined(TARGET_I386)
-                    else if (interrupt_request & CPU_INTERRUPT_INIT) {
-                        replay_interrupt();
-                        cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, 0);
-                        do_cpu_init(x86_cpu);
-                        cpu->exception_index = EXCP_HALTED;
-                        cpu_loop_exit(cpu);
-                    }
-#else
-                    else if (interrupt_request & CPU_INTERRUPT_RESET) {
-                        replay_interrupt();
-                        cpu_reset(cpu);
-                        cpu_loop_exit(cpu);
-                    }
-#endif
-                    /* The target hook has 3 exit conditions:
-                       False when the interrupt isn't processed,
-                       True when it is, and we should restart on a new TB,
-                       and via longjmp via cpu_loop_exit.  */
-                    else {
-                        replay_interrupt();
-                        if (cc->cpu_exec_interrupt(cpu, interrupt_request)) {
-                            last_tb = NULL;
-                        }
-                    }
-                    /* Don't use the cached interrupt_request value,
-                       do_interrupt may have updated the EXITTB flag. */
-                    if (cpu->interrupt_request & CPU_INTERRUPT_EXITTB) {
-                        cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
-                        /* ensure that no TB jump will be modified as
-                           the program flow was changed */
-                        last_tb = NULL;
-                    }
-                }
-                if (unlikely(cpu->exit_request
-                             || replay_has_interrupt())) {
-                    cpu->exit_request = 0;
-                    cpu->exception_index = EXCP_INTERRUPT;
-                    cpu_loop_exit(cpu);
-                }
+                cpu_handle_interrupt(cpu, &last_tb);
                 tb = tb_find_fast(cpu, &last_tb, tb_exit);
                 if (likely(!cpu->exit_request)) {
                     uintptr_t ret;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 4/5] cpu-exec: Move TB execution stuff out of cpu_exec()
  2016-05-11 10:21 [Qemu-devel] [PATCH 0/5] cpu-exec: Restructure cpu_exec() Sergey Fedorov
                   ` (2 preceding siblings ...)
  2016-05-11 10:21 ` [Qemu-devel] [PATCH 3/5] cpu-exec: Move interrupt " Sergey Fedorov
@ 2016-05-11 10:21 ` Sergey Fedorov
  2016-07-15  6:45   ` Stefan Weil
  2016-05-11 10:21 ` [Qemu-devel] [PATCH 5/5] cpu-exec: Remove unused 'x86_cpu' and 'env' from cpu_exec() Sergey Fedorov
  2016-05-12  0:05 ` [Qemu-devel] [PATCH 0/5] cpu-exec: Restructure cpu_exec() Richard Henderson
  5 siblings, 1 reply; 11+ messages in thread
From: Sergey Fedorov @ 2016-05-11 10:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Sergey Fedorov, Sergey Fedorov, Paolo Bonzini, Peter Crosthwaite,
	Richard Henderson

From: Sergey Fedorov <serge.fdrv@gmail.com>

Simplify cpu_exec() by extracting TB execution code outside of
cpu_exec() into a new static inline function cpu_loop_exec_tb().

Signed-off-by: Sergey Fedorov <serge.fdrv@gmail.com>
Signed-off-by: Sergey Fedorov <sergey.fedorov@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 cpu-exec.c | 119 +++++++++++++++++++++++++++++++++----------------------------
 1 file changed, 64 insertions(+), 55 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index a053b5e73af1..197861f8407b 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -506,6 +506,66 @@ static inline void cpu_handle_interrupt(CPUState *cpu,
     }
 }
 
+static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
+                                    TranslationBlock **last_tb, int *tb_exit,
+                                    SyncClocks *sc)
+{
+    uintptr_t ret;
+
+    if (unlikely(cpu->exit_request)) {
+        return;
+    }
+
+    trace_exec_tb(tb, tb->pc);
+    ret = cpu_tb_exec(cpu, tb);
+    *last_tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK);
+    *tb_exit = ret & TB_EXIT_MASK;
+    switch (*tb_exit) {
+    case TB_EXIT_REQUESTED:
+        /* 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 tcg_exit_req read in generated code
+         * comes before the next read of cpu->exit_request
+         * or cpu->interrupt_request.
+         */
+        smp_rmb();
+        *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;
+        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, *last_tb, false);
+                align_clocks(sc, cpu);
+            }
+            cpu->exception_index = EXCP_INTERRUPT;
+            *last_tb = NULL;
+            cpu_loop_exit(cpu);
+        }
+        break;
+#endif
+    }
+    default:
+        break;
+    }
+}
+
 /* main execution loop */
 
 int cpu_exec(CPUState *cpu)
@@ -516,8 +576,6 @@ int cpu_exec(CPUState *cpu)
     CPUArchState *env = &x86_cpu->env;
 #endif
     int ret;
-    TranslationBlock *tb, *last_tb;
-    int tb_exit = 0;
     SyncClocks sc;
 
     /* replay_interrupt may need current_cpu */
@@ -544,6 +602,9 @@ int cpu_exec(CPUState *cpu)
     init_delay_params(&sc, cpu);
 
     for(;;) {
+        TranslationBlock *tb, *last_tb;
+        int tb_exit = 0;
+
         /* prepare setjmp context for exception handling */
         if (sigsetjmp(cpu->jmp_env, 0) == 0) {
             /* if an exception is pending, we execute it here */
@@ -556,59 +617,7 @@ int cpu_exec(CPUState *cpu)
             for(;;) {
                 cpu_handle_interrupt(cpu, &last_tb);
                 tb = tb_find_fast(cpu, &last_tb, tb_exit);
-                if (likely(!cpu->exit_request)) {
-                    uintptr_t ret;
-                    trace_exec_tb(tb, tb->pc);
-                    /* execute the generated code */
-                    ret = cpu_tb_exec(cpu, tb);
-                    last_tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK);
-                    tb_exit = ret & TB_EXIT_MASK;
-                    switch (tb_exit) {
-                    case TB_EXIT_REQUESTED:
-                        /* 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 tcg_exit_req read in generated code
-                         * comes before the next read of cpu->exit_request
-                         * or cpu->interrupt_request.
-                         */
-                        smp_rmb();
-                        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;
-                        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,
-                                                 last_tb, false);
-                                align_clocks(&sc, cpu);
-                            }
-                            cpu->exception_index = EXCP_INTERRUPT;
-                            last_tb = NULL;
-                            cpu_loop_exit(cpu);
-                        }
-                        break;
-#endif
-                    }
-                    default:
-                        break;
-                    }
-                }
+                cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit, &sc);
                 /* Try to align the host and virtual clocks
                    if the guest is in advance */
                 align_clocks(&sc, cpu);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 5/5] cpu-exec: Remove unused 'x86_cpu' and 'env' from cpu_exec()
  2016-05-11 10:21 [Qemu-devel] [PATCH 0/5] cpu-exec: Restructure cpu_exec() Sergey Fedorov
                   ` (3 preceding siblings ...)
  2016-05-11 10:21 ` [Qemu-devel] [PATCH 4/5] cpu-exec: Move TB execution stuff " Sergey Fedorov
@ 2016-05-11 10:21 ` Sergey Fedorov
  2016-05-12  0:05 ` [Qemu-devel] [PATCH 0/5] cpu-exec: Restructure cpu_exec() Richard Henderson
  5 siblings, 0 replies; 11+ messages in thread
From: Sergey Fedorov @ 2016-05-11 10:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Sergey Fedorov, Sergey Fedorov, Paolo Bonzini, Peter Crosthwaite,
	Richard Henderson

From: Sergey Fedorov <serge.fdrv@gmail.com>

Signed-off-by: Sergey Fedorov <serge.fdrv@gmail.com>
Signed-off-by: Sergey Fedorov <sergey.fedorov@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 cpu-exec.c | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index 197861f8407b..b57f91ced162 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -571,10 +571,6 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
 int cpu_exec(CPUState *cpu)
 {
     CPUClass *cc = CPU_GET_CLASS(cpu);
-#ifdef TARGET_I386
-    X86CPU *x86_cpu = X86_CPU(cpu);
-    CPUArchState *env = &x86_cpu->env;
-#endif
     int ret;
     SyncClocks sc;
 
@@ -630,18 +626,10 @@ int cpu_exec(CPUState *cpu)
              * Newer versions of gcc would complain about this code (-Wclobbered). */
             cpu = current_cpu;
             cc = CPU_GET_CLASS(cpu);
-#ifdef TARGET_I386
-            x86_cpu = X86_CPU(cpu);
-            env = &x86_cpu->env;
-#endif
 #else /* buggy compiler */
             /* Assert that the compiler does not smash local variables. */
             g_assert(cpu == current_cpu);
             g_assert(cc == CPU_GET_CLASS(cpu));
-#ifdef TARGET_I386
-            g_assert(x86_cpu == X86_CPU(cpu));
-            g_assert(env == &x86_cpu->env);
-#endif
 #endif /* buggy compiler */
             cpu->can_do_io = 1;
             tb_lock_reset();
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [PATCH 0/5] cpu-exec: Restructure cpu_exec()
  2016-05-11 10:21 [Qemu-devel] [PATCH 0/5] cpu-exec: Restructure cpu_exec() Sergey Fedorov
                   ` (4 preceding siblings ...)
  2016-05-11 10:21 ` [Qemu-devel] [PATCH 5/5] cpu-exec: Remove unused 'x86_cpu' and 'env' from cpu_exec() Sergey Fedorov
@ 2016-05-12  0:05 ` Richard Henderson
  5 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2016-05-12  0:05 UTC (permalink / raw)
  To: Sergey Fedorov, qemu-devel
  Cc: Sergey Fedorov, Alex Bennée, Paolo Bonzini, Peter Crosthwaite

On 05/11/2016 12:21 AM, Sergey Fedorov wrote:
> From: Sergey Fedorov <serge.fdrv@gmail.com>
>
> cpu_exec() was a huge function also sprinkled with some preprocessor
> directives. It was hard to read and see the main loop crowded by all
> this code. Restructure cpu_exec() by moving its conceptual parts into
> separate static inline functions. That makes it possible to see the
> whole main loop at once, especially its sigsetjmp() handling part.
>
> This series is based on commit
>     40f646483a11 (cpu-exec: Remove relic orphaned comment)
> from
>     git://github.com/rth7680/qemu.git tcg-next
> and is available at
>     git://github.com/sergefdrv/qemu.git cpu_exec-restructure-v2
>
> Summary of changes in v2:
>  * Declare x86_cpu variable in the inner-most block [PATCH 1/5]
>
> Sergey Fedorov (5):
>   cpu-exec: Move halt handling out of cpu_exec()
>   cpu-exec: Move exception handling out of cpu_exec()
>   cpu-exec: Move interrupt handling out of cpu_exec()
>   cpu-exec: Move TB execution stuff out of cpu_exec()
>   cpu-exec: Remove unused 'x86_cpu' and 'env' from cpu_exec()
>
>  cpu-exec.c | 395 +++++++++++++++++++++++++++++++++----------------------------
>  1 file changed, 211 insertions(+), 184 deletions(-)
>

Applied to tcg-next.


r~

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [PATCH 4/5] cpu-exec: Move TB execution stuff out of cpu_exec()
  2016-05-11 10:21 ` [Qemu-devel] [PATCH 4/5] cpu-exec: Move TB execution stuff " Sergey Fedorov
@ 2016-07-15  6:45   ` Stefan Weil
  2016-07-15 19:32     ` Sergey Fedorov
  0 siblings, 1 reply; 11+ messages in thread
From: Stefan Weil @ 2016-07-15  6:45 UTC (permalink / raw)
  To: Sergey Fedorov, Richard Henderson; +Cc: QEMU Developer

Hi,

Am 11.05.2016 um 12:21 schrieb Sergey Fedorov:
[...]
>   int cpu_exec(CPUState *cpu)
> @@ -516,8 +576,6 @@ int cpu_exec(CPUState *cpu)
>      CPUArchState *env = &x86_cpu->env;
>  #endif
>      int ret;
> -    TranslationBlock *tb, *last_tb;
> -    int tb_exit = 0;

Here tb_exit was only once set to 0, ...

>      SyncClocks sc;
>  
>      /* replay_interrupt may need current_cpu */
> @@ -544,6 +602,9 @@ int cpu_exec(CPUState *cpu)
>      init_delay_params(&sc, cpu);
>  
>      for(;;) {
> +        TranslationBlock *tb, *last_tb;
> +        int tb_exit = 0;

... while now it is zeroed in each iteration of the for loop.
I'm not sure whether the new code is still correct.

If it is, ...

> +
>          /* prepare setjmp context for exception handling */
>          if (sigsetjmp(cpu->jmp_env, 0) == 0) {

... the declaration of tb_exit could also be done here, after the sigsetjmp.
That would fix a compiler warning which I get when compiling with
-Wclobbered:


    cpu-exec.c:603:13: warning: variable ‘tb_exit’ might be clobbered by
‘longjmp’ or ‘vfork’ [-Wclobbered]


Regards

Stefan

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [PATCH 4/5] cpu-exec: Move TB execution stuff out of cpu_exec()
  2016-07-15  6:45   ` Stefan Weil
@ 2016-07-15 19:32     ` Sergey Fedorov
  0 siblings, 0 replies; 11+ messages in thread
From: Sergey Fedorov @ 2016-07-15 19:32 UTC (permalink / raw)
  To: Stefan Weil, Sergey Fedorov, Richard Henderson; +Cc: QEMU Developer

On 15/07/16 09:45, Stefan Weil wrote:
> Hi,
>
> Am 11.05.2016 um 12:21 schrieb Sergey Fedorov:
> [...]
>>   int cpu_exec(CPUState *cpu)
>> @@ -516,8 +576,6 @@ int cpu_exec(CPUState *cpu)
>>      CPUArchState *env = &x86_cpu->env;
>>  #endif
>>      int ret;
>> -    TranslationBlock *tb, *last_tb;
>> -    int tb_exit = 0;
> Here tb_exit was only once set to 0, ...
>
>>      SyncClocks sc;
>>  
>>      /* replay_interrupt may need current_cpu */
>> @@ -544,6 +602,9 @@ int cpu_exec(CPUState *cpu)
>>      init_delay_params(&sc, cpu);
>>  
>>      for(;;) {
>> +        TranslationBlock *tb, *last_tb;
>> +        int tb_exit = 0;
> ... while now it is zeroed in each iteration of the for loop.
> I'm not sure whether the new code is still correct.

That is okay because 'tb_exit' only makes sense when "last_tb != NULL".
But we always reset 'last_tb' in this loop:

    last_tb = NULL; /* forget the last executed TB after exception */

>
> If it is, ...
>
>> +
>>          /* prepare setjmp context for exception handling */
>>          if (sigsetjmp(cpu->jmp_env, 0) == 0) {
> ... the declaration of tb_exit could also be done here, after the sigsetjmp.
> That would fix a compiler warning which I get when compiling with
> -Wclobbered:
>
>
>     cpu-exec.c:603:13: warning: variable ‘tb_exit’ might be clobbered by
> ‘longjmp’ or ‘vfork’ [-Wclobbered]

I've sent the patch to fix this:

    Message-Id: <20160715193123.28113-1-sergey.fedorov@linaro.org>

Thanks,
Sergey

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [PATCH 4/5] cpu-exec: Move TB execution stuff out of cpu_exec()
  2016-05-10 15:46 ` [Qemu-devel] [PATCH 4/5] cpu-exec: Move TB execution stuff out of cpu_exec() Sergey Fedorov
@ 2016-05-10 16:56   ` Richard Henderson
  0 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2016-05-10 16:56 UTC (permalink / raw)
  To: Sergey Fedorov, qemu-devel
  Cc: Sergey Fedorov, Alex Bennée, Paolo Bonzini, Peter Crosthwaite

On 05/10/2016 05:46 AM, Sergey Fedorov wrote:
> From: Sergey Fedorov <serge.fdrv@gmail.com>
>
> Simplify cpu_exec() by extracting TB execution code outside of
> cpu_exec() into a new static inline function cpu_loop_exec_tb().
>
> Signed-off-by: Sergey Fedorov <serge.fdrv@gmail.com>
> Signed-off-by: Sergey Fedorov <sergey.fedorov@linaro.org>
> ---
>  cpu-exec.c | 119 +++++++++++++++++++++++++++++++++----------------------------
>  1 file changed, 64 insertions(+), 55 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 4/5] cpu-exec: Move TB execution stuff out of cpu_exec()
  2016-05-10 15:46 Sergey Fedorov
@ 2016-05-10 15:46 ` Sergey Fedorov
  2016-05-10 16:56   ` Richard Henderson
  0 siblings, 1 reply; 11+ messages in thread
From: Sergey Fedorov @ 2016-05-10 15:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Sergey Fedorov, Alex Bennée, Sergey Fedorov, Paolo Bonzini,
	Peter Crosthwaite, Richard Henderson

From: Sergey Fedorov <serge.fdrv@gmail.com>

Simplify cpu_exec() by extracting TB execution code outside of
cpu_exec() into a new static inline function cpu_loop_exec_tb().

Signed-off-by: Sergey Fedorov <serge.fdrv@gmail.com>
Signed-off-by: Sergey Fedorov <sergey.fedorov@linaro.org>
---
 cpu-exec.c | 119 +++++++++++++++++++++++++++++++++----------------------------
 1 file changed, 64 insertions(+), 55 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index 0760d5dc274d..60f565074618 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -506,6 +506,66 @@ static inline void cpu_handle_interrupt(CPUState *cpu,
     }
 }
 
+static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
+                                    TranslationBlock **last_tb, int *tb_exit,
+                                    SyncClocks *sc)
+{
+    uintptr_t ret;
+
+    if (unlikely(cpu->exit_request)) {
+        return;
+    }
+
+    trace_exec_tb(tb, tb->pc);
+    ret = cpu_tb_exec(cpu, tb);
+    *last_tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK);
+    *tb_exit = ret & TB_EXIT_MASK;
+    switch (*tb_exit) {
+    case TB_EXIT_REQUESTED:
+        /* 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 tcg_exit_req read in generated code
+         * comes before the next read of cpu->exit_request
+         * or cpu->interrupt_request.
+         */
+        smp_rmb();
+        *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;
+        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, *last_tb, false);
+                align_clocks(sc, cpu);
+            }
+            cpu->exception_index = EXCP_INTERRUPT;
+            *last_tb = NULL;
+            cpu_loop_exit(cpu);
+        }
+        break;
+#endif
+    }
+    default:
+        break;
+    }
+}
+
 /* main execution loop */
 
 int cpu_exec(CPUState *cpu)
@@ -516,8 +576,6 @@ int cpu_exec(CPUState *cpu)
     CPUArchState *env = &x86_cpu->env;
 #endif
     int ret;
-    TranslationBlock *tb, *last_tb;
-    int tb_exit = 0;
     SyncClocks sc;
 
     /* replay_interrupt may need current_cpu */
@@ -544,6 +602,9 @@ int cpu_exec(CPUState *cpu)
     init_delay_params(&sc, cpu);
 
     for(;;) {
+        TranslationBlock *tb, *last_tb;
+        int tb_exit = 0;
+
         /* prepare setjmp context for exception handling */
         if (sigsetjmp(cpu->jmp_env, 0) == 0) {
             /* if an exception is pending, we execute it here */
@@ -556,59 +617,7 @@ int cpu_exec(CPUState *cpu)
             for(;;) {
                 cpu_handle_interrupt(cpu, &last_tb);
                 tb = tb_find_fast(cpu, &last_tb, tb_exit);
-                if (likely(!cpu->exit_request)) {
-                    uintptr_t ret;
-                    trace_exec_tb(tb, tb->pc);
-                    /* execute the generated code */
-                    ret = cpu_tb_exec(cpu, tb);
-                    last_tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK);
-                    tb_exit = ret & TB_EXIT_MASK;
-                    switch (tb_exit) {
-                    case TB_EXIT_REQUESTED:
-                        /* 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 tcg_exit_req read in generated code
-                         * comes before the next read of cpu->exit_request
-                         * or cpu->interrupt_request.
-                         */
-                        smp_rmb();
-                        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;
-                        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,
-                                                 last_tb, false);
-                                align_clocks(&sc, cpu);
-                            }
-                            cpu->exception_index = EXCP_INTERRUPT;
-                            last_tb = NULL;
-                            cpu_loop_exit(cpu);
-                        }
-                        break;
-#endif
-                    }
-                    default:
-                        break;
-                    }
-                }
+                cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit, &sc);
                 /* Try to align the host and virtual clocks
                    if the guest is in advance */
                 align_clocks(&sc, cpu);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2016-07-15 19:32 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-11 10:21 [Qemu-devel] [PATCH 0/5] cpu-exec: Restructure cpu_exec() Sergey Fedorov
2016-05-11 10:21 ` [Qemu-devel] [PATCH 1/5] cpu-exec: Move halt handling out of cpu_exec() Sergey Fedorov
2016-05-11 10:21 ` [Qemu-devel] [PATCH 2/5] cpu-exec: Move exception " Sergey Fedorov
2016-05-11 10:21 ` [Qemu-devel] [PATCH 3/5] cpu-exec: Move interrupt " Sergey Fedorov
2016-05-11 10:21 ` [Qemu-devel] [PATCH 4/5] cpu-exec: Move TB execution stuff " Sergey Fedorov
2016-07-15  6:45   ` Stefan Weil
2016-07-15 19:32     ` Sergey Fedorov
2016-05-11 10:21 ` [Qemu-devel] [PATCH 5/5] cpu-exec: Remove unused 'x86_cpu' and 'env' from cpu_exec() Sergey Fedorov
2016-05-12  0:05 ` [Qemu-devel] [PATCH 0/5] cpu-exec: Restructure cpu_exec() Richard Henderson
  -- strict thread matches above, loose matches on Subject: below --
2016-05-10 15:46 Sergey Fedorov
2016-05-10 15:46 ` [Qemu-devel] [PATCH 4/5] cpu-exec: Move TB execution stuff out of cpu_exec() Sergey Fedorov
2016-05-10 16:56   ` Richard Henderson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.