Commit 0a49bfa1 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/stsquad/tags/pull-mttcg-fixups-for-rc2-100417-1' into staging



Final icount and misc MTTCG fixes for 2.9

Minor differences from:
  Message-Id: <20170405132503.32125-1-alex.bennee@linaro.org>

  - dropped new feature patches
  - last minute typo fix from Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>

# gpg: Signature made Mon 10 Apr 2017 11:38:10 BST
# gpg:                using RSA key 0xFBD0DB095A9E2A44
# gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>"
# Primary key fingerprint: 6685 AE99 E751 67BC AFC8  DF35 FBD0 DB09 5A9E 2A44

* remotes/stsquad/tags/pull-mttcg-fixups-for-rc2-100417-1:
  replay: assert time only goes forward
  cpus: call cpu_update_icount on read
  cpu-exec: update icount after each TB_EXIT
  cpus: introduce cpu_update_icount helper
  cpus: don't credit executed instructions before they have run
  cpus: move icount preparation out of tcg_exec_cpu
  cpus: check cpu->running in cpu_get_icount_raw()
  cpus: remove icount handling from qemu_tcg_cpu_thread_fn
  target/i386/misc_helper: wrap BQL around another IRQ generator
  cpus: fix wrong define name
  scripts/qemugdb/mtree.py: fix up mtree dump

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents ad04d8cb 982263ce
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -600,13 +600,13 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
    /* Instruction counter expired.  */
    assert(use_icount);
#ifndef CONFIG_USER_ONLY
    if (cpu->icount_extra) {
    /* Ensure global icount has gone forward */
    cpu_update_icount(cpu);
    /* Refill decrementer and continue execution.  */
        cpu->icount_extra += insns_left;
        insns_left = MIN(0xffff, cpu->icount_extra);
        cpu->icount_extra -= insns_left;
    insns_left = MIN(0xffff, cpu->icount_budget);
    cpu->icount_decr.u16.low = insns_left;
    } else {
    cpu->icount_extra = cpu->icount_budget - insns_left;
    if (!cpu->icount_extra) {
        /* Execute any remaining instructions, then let the main loop
         * handle the next event.
         */
+80 −31
Original line number Diff line number Diff line
@@ -202,7 +202,7 @@ void qemu_tcg_configure(QemuOpts *opts, Error **errp)
            } else if (use_icount) {
                error_setg(errp, "No MTTCG when icount is enabled");
            } else {
#ifndef TARGET_SUPPORT_MTTCG
#ifndef TARGET_SUPPORTS_MTTCG
                error_report("Guest not yet converted to MTTCG - "
                             "you may get unexpected results");
#endif
@@ -223,20 +223,51 @@ void qemu_tcg_configure(QemuOpts *opts, Error **errp)
    }
}

/* The current number of executed instructions is based on what we
 * originally budgeted minus the current state of the decrementing
 * icount counters in extra/u16.low.
 */
static int64_t cpu_get_icount_executed(CPUState *cpu)
{
    return cpu->icount_budget - (cpu->icount_decr.u16.low + cpu->icount_extra);
}

/*
 * Update the global shared timer_state.qemu_icount to take into
 * account executed instructions. This is done by the TCG vCPU
 * thread so the main-loop can see time has moved forward.
 */
void cpu_update_icount(CPUState *cpu)
{
    int64_t executed = cpu_get_icount_executed(cpu);
    cpu->icount_budget -= executed;

#ifdef CONFIG_ATOMIC64
    atomic_set__nocheck(&timers_state.qemu_icount,
                        atomic_read__nocheck(&timers_state.qemu_icount) +
                        executed);
#else /* FIXME: we need 64bit atomics to do this safely */
    timers_state.qemu_icount += executed;
#endif
}

int64_t cpu_get_icount_raw(void)
{
    int64_t icount;
    CPUState *cpu = current_cpu;

    icount = timers_state.qemu_icount;
    if (cpu) {
    if (cpu && cpu->running) {
        if (!cpu->can_do_io) {
            fprintf(stderr, "Bad icount read\n");
            exit(1);
        }
        icount -= (cpu->icount_decr.u16.low + cpu->icount_extra);
        /* Take into account what has run */
        cpu_update_icount(cpu);
    }
    return icount;
#ifdef CONFIG_ATOMIC64
    return atomic_read__nocheck(&timers_state.qemu_icount);
#else /* FIXME: we need 64bit atomics to do this safely */
    return timers_state.qemu_icount;
#endif
}

/* Return the virtual CPU time, based on the instruction counter.  */
@@ -1179,6 +1210,41 @@ static void handle_icount_deadline(void)
    }
}

static void prepare_icount_for_run(CPUState *cpu)
{
    if (use_icount) {
        int insns_left;

        /* These should always be cleared by process_icount_data after
         * each vCPU execution. However u16.high can be raised
         * asynchronously by cpu_exit/cpu_interrupt/tcg_handle_interrupt
         */
        g_assert(cpu->icount_decr.u16.low == 0);
        g_assert(cpu->icount_extra == 0);

        cpu->icount_budget = tcg_get_icount_limit();
        insns_left = MIN(0xffff, cpu->icount_budget);
        cpu->icount_decr.u16.low = insns_left;
        cpu->icount_extra = cpu->icount_budget - insns_left;
    }
}

static void process_icount_data(CPUState *cpu)
{
    if (use_icount) {
        /* Account for executed instructions */
        cpu_update_icount(cpu);

        /* Reset the counters */
        cpu->icount_decr.u16.low = 0;
        cpu->icount_extra = 0;
        cpu->icount_budget = 0;

        replay_account_executed_instructions();
    }
}


static int tcg_cpu_exec(CPUState *cpu)
{
    int ret;
@@ -1189,20 +1255,6 @@ static int tcg_cpu_exec(CPUState *cpu)
#ifdef CONFIG_PROFILER
    ti = profile_getclock();
#endif
    if (use_icount) {
        int64_t count;
        int decr;
        timers_state.qemu_icount -= (cpu->icount_decr.u16.low
                                    + cpu->icount_extra);
        cpu->icount_decr.u16.low = 0;
        cpu->icount_extra = 0;
        count = tcg_get_icount_limit();
        timers_state.qemu_icount += count;
        decr = (count > 0xffff) ? 0xffff : count;
        count -= decr;
        cpu->icount_decr.u16.low = decr;
        cpu->icount_extra = count;
    }
    qemu_mutex_unlock_iothread();
    cpu_exec_start(cpu);
    ret = cpu_exec(cpu);
@@ -1211,15 +1263,6 @@ static int tcg_cpu_exec(CPUState *cpu)
#ifdef CONFIG_PROFILER
    tcg_time += profile_getclock() - ti;
#endif
    if (use_icount) {
        /* Fold pending instructions back into the
           instruction counter, and clear the interrupt flag.  */
        timers_state.qemu_icount -= (cpu->icount_decr.u16.low
                        + cpu->icount_extra);
        cpu->icount_decr.u32 = 0;
        cpu->icount_extra = 0;
        replay_account_executed_instructions();
    }
    return ret;
}

@@ -1306,7 +1349,13 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg)

            if (cpu_can_run(cpu)) {
                int r;

                prepare_icount_for_run(cpu);

                r = tcg_cpu_exec(cpu);

                process_icount_data(cpu);

                if (r == EXCP_DEBUG) {
                    cpu_handle_guest_debug(cpu);
                    break;
@@ -1392,6 +1441,8 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
{
    CPUState *cpu = arg;

    g_assert(!use_icount);

    rcu_register_thread();

    qemu_mutex_lock_iothread();
@@ -1434,8 +1485,6 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
            }
        }

        handle_icount_deadline();

        atomic_mb_set(&cpu->exit_request, 0);
        qemu_tcg_wait_io_event(cpu);
    }
+1 −0
Original line number Diff line number Diff line
@@ -869,6 +869,7 @@ int64_t cpu_get_icount_raw(void);
int64_t cpu_get_icount(void);
int64_t cpu_get_clock(void);
int64_t cpu_icount_to_ns(int64_t icount);
void    cpu_update_icount(CPUState *cpu);

/*******************************************/
/* host CPU ticks (if available) */
+1 −0
Original line number Diff line number Diff line
@@ -332,6 +332,7 @@ struct CPUState {
    /* updates protected by BQL */
    uint32_t interrupt_request;
    int singlestep_enabled;
    int64_t icount_budget;
    int64_t icount_extra;
    sigjmp_buf jmp_env;

+4 −0
Original line number Diff line number Diff line
@@ -195,6 +195,10 @@ void replay_save_instructions(void)
    if (replay_file && replay_mode == REPLAY_MODE_RECORD) {
        replay_mutex_lock();
        int diff = (int)(replay_get_current_step() - replay_state.current_step);

        /* Time can only go forward */
        assert(diff >= 0);

        if (diff > 0) {
            replay_put_event(EVENT_INSTRUCTION);
            replay_put_dword(diff);
Loading