Commit fdbc2b57 authored by Richard Henderson's avatar Richard Henderson
Browse files

tcg: Add EXCP_ATOMIC



When we cannot emulate an atomic operation within a parallel
context, this exception allows us to stop the world and try
again in a serial context.

Reviewed-by: default avatarEmilio G. Cota <cota@braap.org>
Reviewed-by: default avatarAlex Bennée <alex.bennee@linaro.org>
Signed-off-by: default avatarRichard Henderson <rth@twiddle.net>
parent 1edaeee0
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -77,3 +77,9 @@ void cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc)
    }
    siglongjmp(cpu->jmp_env, 1);
}

void cpu_loop_exit_atomic(CPUState *cpu, uintptr_t pc)
{
    cpu->exception_index = EXCP_ATOMIC;
    cpu_loop_exit_restore(cpu, pc);
}
+30 −0
Original line number Diff line number Diff line
@@ -222,6 +222,36 @@ static void cpu_exec_nocache(CPUState *cpu, int max_cycles,
}
#endif

static void cpu_exec_step(CPUState *cpu)
{
    CPUArchState *env = (CPUArchState *)cpu->env_ptr;
    TranslationBlock *tb;
    target_ulong cs_base, pc;
    uint32_t flags;

    cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
    tb = tb_gen_code(cpu, pc, cs_base, flags,
                     1 | CF_NOCACHE | CF_IGNORE_ICOUNT);
    tb->orig_tb = NULL;
    /* execute the generated code */
    trace_exec_tb_nocache(tb, pc);
    cpu_tb_exec(cpu, tb);
    tb_phys_invalidate(tb, -1);
    tb_free(tb);
}

void cpu_exec_step_atomic(CPUState *cpu)
{
    start_exclusive();

    /* Since we got here, we know that parallel_cpus must be true.  */
    parallel_cpus = false;
    cpu_exec_step(cpu);
    parallel_cpus = true;

    end_exclusive();
}

struct tb_desc {
    target_ulong pc;
    target_ulong cs_base;
+2 −0
Original line number Diff line number Diff line
@@ -1497,6 +1497,8 @@ static void tcg_exec_all(void)
            if (r == EXCP_DEBUG) {
                cpu_handle_guest_debug(cpu);
                break;
            } else if (r == EXCP_ATOMIC) {
                cpu_exec_step_atomic(cpu);
            }
        } else if (cpu->stop || cpu->stopped) {
            if (cpu->unplug) {
+1 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#define EXCP_DEBUG      0x10002 /* cpu stopped after a breakpoint or singlestep */
#define EXCP_HALTED     0x10003 /* cpu is halted (waiting for external event) */
#define EXCP_YIELD      0x10004 /* cpu wants to yield timeslice to another */
#define EXCP_ATOMIC     0x10005 /* stop-the-world and emulate atomic */

/* some important defines:
 *
+1 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,

void QEMU_NORETURN cpu_loop_exit(CPUState *cpu);
void QEMU_NORETURN cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc);
void QEMU_NORETURN cpu_loop_exit_atomic(CPUState *cpu, uintptr_t pc);

#if !defined(CONFIG_USER_ONLY)
void cpu_reloading_memory_map(void);
Loading