[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 07/27] tcg: Add EXCP_ATOMIC
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PATCH v2 07/27] tcg: Add EXCP_ATOMIC |
Date: |
Fri, 1 Jul 2016 10:04:33 -0700 |
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.
Signed-off-by: Richard Henderson <address@hidden>
---
cpu-exec-common.c | 6 +++++
cpu-exec.c | 23 +++++++++++++++++++
cpus.c | 6 +++++
include/exec/cpu-all.h | 1 +
include/exec/exec-all.h | 1 +
include/qemu-common.h | 1 +
linux-user/main.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++-
tcg/tcg.h | 1 +
translate-all.c | 1 +
9 files changed, 98 insertions(+), 1 deletion(-)
diff --git a/cpu-exec-common.c b/cpu-exec-common.c
index 0cb4ae6..767d9c6 100644
--- a/cpu-exec-common.c
+++ b/cpu-exec-common.c
@@ -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);
+}
diff --git a/cpu-exec.c b/cpu-exec.c
index b840e1d..041f8b7 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -225,6 +225,29 @@ static void cpu_exec_nocache(CPUState *cpu, int max_cycles,
}
#endif
+void cpu_exec_step(CPUState *cpu)
+{
+ CPUArchState *env = (CPUArchState *)cpu->env_ptr;
+ TranslationBlock *tb;
+ target_ulong cs_base, pc;
+ uint32_t flags;
+ bool old_tb_flushed;
+
+ old_tb_flushed = cpu->tb_flushed;
+ cpu->tb_flushed = false;
+
+ 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;
+ cpu->tb_flushed |= old_tb_flushed;
+ /* execute the generated code */
+ trace_exec_tb_nocache(tb, pc);
+ cpu_tb_exec(cpu, tb);
+ tb_phys_invalidate(tb, -1);
+ tb_free(tb);
+}
+
struct tb_desc {
target_ulong pc;
target_ulong cs_base;
diff --git a/cpus.c b/cpus.c
index 84c3520..a01bbbd 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1575,6 +1575,12 @@ static void tcg_exec_all(void)
if (r == EXCP_DEBUG) {
cpu_handle_guest_debug(cpu);
break;
+ } else if (r == EXCP_ATOMIC) {
+ /* ??? When we begin running cpus in parallel, we should
+ stop all cpus, clear parallel_cpus, and interpret a
+ single insn with cpu_exec_step. In the meantime,
+ we should never get here. */
+ abort();
}
} else if (cpu->stop || cpu->stopped) {
if (cpu->unplug) {
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 8007abb..d2aac4b 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -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:
*
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index c1f59fa..ec72c5a 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -59,6 +59,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
void cpu_exec_init(CPUState *cpu, Error **errp);
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);
diff --git a/include/qemu-common.h b/include/qemu-common.h
index 1f2cb94..77e379d 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -76,6 +76,7 @@ void tcg_exec_init(unsigned long tb_size);
bool tcg_enabled(void);
void cpu_exec_init_all(void);
+void cpu_exec_step(CPUState *cpu);
/**
* Sends a (part of) iovec down a socket, yielding when the socket is full, or
diff --git a/linux-user/main.c b/linux-user/main.c
index 78d8d04..54df300 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -179,13 +179,25 @@ static inline void start_exclusive(void)
}
/* Finish an exclusive operation. */
-static inline void __attribute__((unused)) end_exclusive(void)
+static inline void end_exclusive(void)
{
pending_cpus = 0;
pthread_cond_broadcast(&exclusive_resume);
pthread_mutex_unlock(&exclusive_lock);
}
+static void 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();
+}
+
/* Wait for exclusive ops to finish, and begin cpu execution. */
static inline void cpu_exec_start(CPUState *cpu)
{
@@ -437,6 +449,9 @@ void cpu_loop(CPUX86State *env)
}
}
break;
+ case EXCP_ATOMIC:
+ step_atomic(cs);
+ break;
default:
pc = env->segs[R_CS].base + env->eip;
EXCP_DUMP(env, "qemu: 0x%08lx: unhandled CPU exception 0x%x -
aborting\n",
@@ -929,6 +944,9 @@ void cpu_loop(CPUARMState *env)
case EXCP_YIELD:
/* nothing to do here for user-mode, just resume guest code */
break;
+ case EXCP_ATOMIC:
+ step_atomic(cs);
+ break;
default:
error:
EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
@@ -1128,6 +1146,9 @@ void cpu_loop(CPUARMState *env)
case EXCP_YIELD:
/* nothing to do here for user-mode, just resume guest code */
break;
+ case EXCP_ATOMIC:
+ step_atomic(cs);
+ break;
default:
EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
abort();
@@ -1217,6 +1238,9 @@ void cpu_loop(CPUUniCore32State *env)
}
}
break;
+ case EXCP_ATOMIC:
+ step_atomic(cs);
+ break;
default:
goto error;
}
@@ -1489,6 +1513,9 @@ void cpu_loop (CPUSPARCState *env)
}
}
break;
+ case EXCP_ATOMIC:
+ step_atomic(cs);
+ break;
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(cs, stderr, fprintf, 0);
@@ -2037,6 +2064,9 @@ void cpu_loop(CPUPPCState *env)
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
+ case EXCP_ATOMIC:
+ step_atomic(cs);
+ break;
default:
cpu_abort(cs, "Unknown exception 0x%d. Aborting\n", trapnr);
break;
@@ -2710,6 +2740,9 @@ done_syscall:
}
}
break;
+ case EXCP_ATOMIC:
+ step_atomic(cs);
+ break;
default:
error:
EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
@@ -2796,6 +2829,9 @@ void cpu_loop(CPUOpenRISCState *env)
case EXCP_NR:
qemu_log_mask(CPU_LOG_INT, "\nNR\n");
break;
+ case EXCP_ATOMIC:
+ step_atomic(cs);
+ break;
default:
EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n",
trapnr);
@@ -2871,6 +2907,9 @@ void cpu_loop(CPUSH4State *env)
queue_signal(env, info.si_signo, &info);
break;
+ case EXCP_ATOMIC:
+ step_atomic(cs);
+ break;
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(cs, stderr, fprintf, 0);
@@ -2936,6 +2975,9 @@ void cpu_loop(CPUCRISState *env)
}
}
break;
+ case EXCP_ATOMIC:
+ step_atomic(cs);
+ break;
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(cs, stderr, fprintf, 0);
@@ -3050,6 +3092,9 @@ void cpu_loop(CPUMBState *env)
}
}
break;
+ case EXCP_ATOMIC:
+ step_atomic(cs);
+ break;
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(cs, stderr, fprintf, 0);
@@ -3151,6 +3196,9 @@ void cpu_loop(CPUM68KState *env)
}
}
break;
+ case EXCP_ATOMIC:
+ step_atomic(cs);
+ break;
default:
EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
abort();
@@ -3386,6 +3434,9 @@ void cpu_loop(CPUAlphaState *env)
case EXCP_INTERRUPT:
/* Just indicate that signals should be handled asap. */
break;
+ case EXCP_ATOMIC:
+ step_atomic(cs);
+ break;
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(cs, stderr, fprintf, 0);
@@ -3513,6 +3564,9 @@ void cpu_loop(CPUS390XState *env)
queue_signal(env, info.si_signo, &info);
break;
+ case EXCP_ATOMIC:
+ step_atomic(cs);
+ break;
default:
fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(cs, stderr, fprintf, 0);
@@ -3765,6 +3819,9 @@ void cpu_loop(CPUTLGState *env)
case TILEGX_EXCP_REG_UDN_ACCESS:
gen_sigill_reg(env);
break;
+ case EXCP_ATOMIC:
+ step_atomic(cs);
+ break;
default:
fprintf(stderr, "trapnr is %d[0x%x].\n", trapnr, trapnr);
g_assert_not_reached();
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 66ae0c7..ab67537 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -691,6 +691,7 @@ struct TCGContext {
};
extern TCGContext tcg_ctx;
+extern bool parallel_cpus;
static inline void tcg_set_insn_param(int op_idx, int arg, TCGArg v)
{
diff --git a/translate-all.c b/translate-all.c
index eaa95e4..99ae7f9 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -119,6 +119,7 @@ static void *l1_map[V_L1_SIZE];
/* code generation context */
TCGContext tcg_ctx;
+bool parallel_cpus;
/* translation block context */
#ifdef CONFIG_USER_ONLY
--
2.5.5
- [Qemu-devel] [PATCH v2 01/27] atomics: add atomic_xor, (continued)
- [Qemu-devel] [PATCH v2 01/27] atomics: add atomic_xor, Richard Henderson, 2016/07/01
- [Qemu-devel] [PATCH v2 11/27] target-i386: emulate LOCK'ed cmpxchg using cmpxchg helpers, Richard Henderson, 2016/07/01
- [Qemu-devel] [PATCH v2 06/27] int128: Use complex numbers if advisable, Richard Henderson, 2016/07/01
- [Qemu-devel] [PATCH v2 10/27] tcg: Add atomic128 helpers, Richard Henderson, 2016/07/01
- [Qemu-devel] [PATCH v2 07/27] tcg: Add EXCP_ATOMIC,
Richard Henderson <=
- [Qemu-devel] [PATCH v2 13/27] target-i386: emulate LOCK'ed INC using atomic helper, Richard Henderson, 2016/07/01
- [Qemu-devel] [PATCH v2 09/27] tcg: Add atomic helpers, Richard Henderson, 2016/07/01
- [Qemu-devel] [PATCH v2 15/27] target-i386: emulate LOCK'ed NEG using cmpxchg helper, Richard Henderson, 2016/07/01
- [Qemu-devel] [PATCH v2 16/27] target-i386: emulate LOCK'ed XADD using atomic helper, Richard Henderson, 2016/07/01
- [Qemu-devel] [PATCH v2 12/27] target-i386: emulate LOCK'ed OP instructions using atomic helpers, Richard Henderson, 2016/07/01
- [Qemu-devel] [PATCH v2 14/27] target-i386: emulate LOCK'ed NOT using atomic helper, Richard Henderson, 2016/07/01
- [Qemu-devel] [PATCH v2 18/27] target-i386: emulate XCHG using atomic helper, Richard Henderson, 2016/07/01
- [Qemu-devel] [PATCH v2 19/27] target-i386: remove helper_lock(), Richard Henderson, 2016/07/01
- [Qemu-devel] [PATCH v2 21/27] target-arm: Rearrange aa32 load and store functions, Richard Henderson, 2016/07/01
- [Qemu-devel] [PATCH v2 17/27] target-i386: emulate LOCK'ed BTX ops using atomic helpers, Richard Henderson, 2016/07/01