|
@@ -162,6 +162,7 @@ static TCGContext **tcg_ctxs;
|
|
static unsigned int n_tcg_ctxs;
|
|
static unsigned int n_tcg_ctxs;
|
|
TCGv_env cpu_env = 0;
|
|
TCGv_env cpu_env = 0;
|
|
void *tcg_code_gen_epilogue;
|
|
void *tcg_code_gen_epilogue;
|
|
|
|
+uintptr_t tcg_splitwx_diff;
|
|
|
|
|
|
#ifndef CONFIG_TCG_INTERPRETER
|
|
#ifndef CONFIG_TCG_INTERPRETER
|
|
tcg_prologue_fn *tcg_qemu_tb_exec;
|
|
tcg_prologue_fn *tcg_qemu_tb_exec;
|
|
@@ -406,8 +407,9 @@ static void tcg_region_trees_init(void)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static struct tcg_region_tree *tc_ptr_to_region_tree(void *p)
|
|
|
|
|
|
+static struct tcg_region_tree *tc_ptr_to_region_tree(const void *cp)
|
|
{
|
|
{
|
|
|
|
+ void *p = tcg_splitwx_to_rw(cp);
|
|
size_t region_idx;
|
|
size_t region_idx;
|
|
|
|
|
|
if (p < region.start_aligned) {
|
|
if (p < region.start_aligned) {
|
|
@@ -701,6 +703,7 @@ void tcg_region_init(void)
|
|
size_t region_size;
|
|
size_t region_size;
|
|
size_t n_regions;
|
|
size_t n_regions;
|
|
size_t i;
|
|
size_t i;
|
|
|
|
+ uintptr_t splitwx_diff;
|
|
|
|
|
|
n_regions = tcg_n_regions();
|
|
n_regions = tcg_n_regions();
|
|
|
|
|
|
@@ -731,6 +734,7 @@ void tcg_region_init(void)
|
|
region.end -= page_size;
|
|
region.end -= page_size;
|
|
|
|
|
|
/* set guard pages */
|
|
/* set guard pages */
|
|
|
|
+ splitwx_diff = tcg_splitwx_diff;
|
|
for (i = 0; i < region.n; i++) {
|
|
for (i = 0; i < region.n; i++) {
|
|
void *start, *end;
|
|
void *start, *end;
|
|
int rc;
|
|
int rc;
|
|
@@ -738,6 +742,10 @@ void tcg_region_init(void)
|
|
tcg_region_bounds(i, &start, &end);
|
|
tcg_region_bounds(i, &start, &end);
|
|
rc = qemu_mprotect_none(end, page_size);
|
|
rc = qemu_mprotect_none(end, page_size);
|
|
g_assert(!rc);
|
|
g_assert(!rc);
|
|
|
|
+ if (splitwx_diff) {
|
|
|
|
+ rc = qemu_mprotect_none(end + splitwx_diff, page_size);
|
|
|
|
+ g_assert(!rc);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
tcg_region_trees_init();
|
|
tcg_region_trees_init();
|
|
@@ -752,6 +760,29 @@ void tcg_region_init(void)
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifdef CONFIG_DEBUG_TCG
|
|
|
|
+const void *tcg_splitwx_to_rx(void *rw)
|
|
|
|
+{
|
|
|
|
+ /* Pass NULL pointers unchanged. */
|
|
|
|
+ if (rw) {
|
|
|
|
+ g_assert(in_code_gen_buffer(rw));
|
|
|
|
+ rw += tcg_splitwx_diff;
|
|
|
|
+ }
|
|
|
|
+ return rw;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void *tcg_splitwx_to_rw(const void *rx)
|
|
|
|
+{
|
|
|
|
+ /* Pass NULL pointers unchanged. */
|
|
|
|
+ if (rx) {
|
|
|
|
+ rx -= tcg_splitwx_diff;
|
|
|
|
+ /* Assert that we end with a pointer in the rw region. */
|
|
|
|
+ g_assert(in_code_gen_buffer(rx));
|
|
|
|
+ }
|
|
|
|
+ return (void *)rx;
|
|
|
|
+}
|
|
|
|
+#endif /* CONFIG_DEBUG_TCG */
|
|
|
|
+
|
|
static void alloc_tcg_plugin_context(TCGContext *s)
|
|
static void alloc_tcg_plugin_context(TCGContext *s)
|
|
{
|
|
{
|
|
#ifdef CONFIG_PLUGIN
|
|
#ifdef CONFIG_PLUGIN
|
|
@@ -1061,8 +1092,15 @@ void tcg_prologue_init(TCGContext *s)
|
|
s->code_buf = buf0;
|
|
s->code_buf = buf0;
|
|
s->data_gen_ptr = NULL;
|
|
s->data_gen_ptr = NULL;
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * The region trees are not yet configured, but tcg_splitwx_to_rx
|
|
|
|
+ * needs the bounds for an assert.
|
|
|
|
+ */
|
|
|
|
+ region.start = buf0;
|
|
|
|
+ region.end = buf0 + total_size;
|
|
|
|
+
|
|
#ifndef CONFIG_TCG_INTERPRETER
|
|
#ifndef CONFIG_TCG_INTERPRETER
|
|
- tcg_qemu_tb_exec = (tcg_prologue_fn *)buf0;
|
|
|
|
|
|
+ tcg_qemu_tb_exec = (tcg_prologue_fn *)tcg_splitwx_to_rx(buf0);
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/* Compute a high-water mark, at which we voluntarily flush the buffer
|
|
/* Compute a high-water mark, at which we voluntarily flush the buffer
|
|
@@ -1087,7 +1125,7 @@ void tcg_prologue_init(TCGContext *s)
|
|
|
|
|
|
buf1 = s->code_ptr;
|
|
buf1 = s->code_ptr;
|
|
#ifndef CONFIG_TCG_INTERPRETER
|
|
#ifndef CONFIG_TCG_INTERPRETER
|
|
- flush_idcache_range((uintptr_t)buf0, (uintptr_t)buf0,
|
|
|
|
|
|
+ flush_idcache_range((uintptr_t)tcg_splitwx_to_rx(buf0), (uintptr_t)buf0,
|
|
tcg_ptr_byte_diff(buf1, buf0));
|
|
tcg_ptr_byte_diff(buf1, buf0));
|
|
#endif
|
|
#endif
|
|
|
|
|
|
@@ -4231,8 +4269,13 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
|
|
|
|
|
|
tcg_reg_alloc_start(s);
|
|
tcg_reg_alloc_start(s);
|
|
|
|
|
|
- s->code_buf = tb->tc.ptr;
|
|
|
|
- s->code_ptr = tb->tc.ptr;
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Reset the buffer pointers when restarting after overflow.
|
|
|
|
+ * TODO: Move this into translate-all.c with the rest of the
|
|
|
|
+ * buffer management. Having only this done here is confusing.
|
|
|
|
+ */
|
|
|
|
+ s->code_buf = tcg_splitwx_to_rw(tb->tc.ptr);
|
|
|
|
+ s->code_ptr = s->code_buf;
|
|
|
|
|
|
#ifdef TCG_TARGET_NEED_LDST_LABELS
|
|
#ifdef TCG_TARGET_NEED_LDST_LABELS
|
|
QSIMPLEQ_INIT(&s->ldst_labels);
|
|
QSIMPLEQ_INIT(&s->ldst_labels);
|
|
@@ -4337,7 +4380,8 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
|
|
|
|
|
|
#ifndef CONFIG_TCG_INTERPRETER
|
|
#ifndef CONFIG_TCG_INTERPRETER
|
|
/* flush instruction cache */
|
|
/* flush instruction cache */
|
|
- flush_idcache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_buf,
|
|
|
|
|
|
+ flush_idcache_range((uintptr_t)tcg_splitwx_to_rx(s->code_buf),
|
|
|
|
+ (uintptr_t)s->code_buf,
|
|
tcg_ptr_byte_diff(s->code_ptr, s->code_buf));
|
|
tcg_ptr_byte_diff(s->code_ptr, s->code_buf));
|
|
#endif
|
|
#endif
|
|
|
|
|