diff mbox series

[v1,07/12] accel/tcg: actually cache our partial icount TB

Message ID 20210209182749.31323-8-alex.bennee@linaro.org
State New
Headers show
Series fix plugins double counting with mmio, cleanup CF_ flags | expand

Commit Message

Alex Bennée Feb. 9, 2021, 6:27 p.m. UTC
When we exit a block under icount with instructions left to execute we
might need a shorter than normal block to take us to the next
deterministic event. Instead of creating a throwaway block on demand
we use the existing compile flags mechanism to ensure we fetch (or
compile and fetch) a block with exactly the number of instructions we
need.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 accel/tcg/cpu-exec.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

Comments

Richard Henderson Feb. 9, 2021, 6:41 p.m. UTC | #1
On 2/9/21 10:27 AM, Alex Bennée wrote:
>      /* Refill decrementer and continue execution.  */
> -    insns_left = MIN(0xffff, cpu->icount_budget);
> +    insns_left = MIN(CF_COUNT_MASK, cpu->icount_budget);
...
> +        g_assert(insns_left < CF_COUNT_MASK);

Why both the MIN and the assert?


r~
Alex Bennée Feb. 9, 2021, 8:49 p.m. UTC | #2
Richard Henderson <richard.henderson@linaro.org> writes:

> On 2/9/21 10:27 AM, Alex Bennée wrote:
>>      /* Refill decrementer and continue execution.  */
>> -    insns_left = MIN(0xffff, cpu->icount_budget);
>> +    insns_left = MIN(CF_COUNT_MASK, cpu->icount_budget);
> ...
>> +        g_assert(insns_left < CF_COUNT_MASK);
>
> Why both the MIN and the assert?

Lack of faith in MIN I guess ;-)

I'll drop the assert.

>
>
> r~
diff mbox series

Patch

diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index d9ef69121c..7f477af891 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -730,16 +730,18 @@  static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
     /* Ensure global icount has gone forward */
     icount_update(cpu);
     /* Refill decrementer and continue execution.  */
-    insns_left = MIN(0xffff, cpu->icount_budget);
+    insns_left = MIN(CF_COUNT_MASK, cpu->icount_budget);
     cpu_neg(cpu)->icount_decr.u16.low = insns_left;
     cpu->icount_extra = cpu->icount_budget - insns_left;
-    if (!cpu->icount_extra && insns_left < tb->icount) {
-        /* 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);
-        }
+
+    /*
+     * If the next tb has more instructions than we have left to
+     * execute we need to ensure we find/generate a TB with exactly
+     * insns_left instructions in it.
+     */
+    if (!cpu->icount_extra && insns_left > 0 && insns_left < tb->icount)  {
+        g_assert(insns_left < CF_COUNT_MASK);
+        cpu->cflags_next_tb = (tb->cflags & ~CF_COUNT_MASK) | insns_left;
     }
 #endif
 }