diff options
Diffstat (limited to 'tcg')
-rw-r--r-- | tcg/tcg-pool.c.inc | 6 | ||||
-rw-r--r-- | tcg/tcg.c | 56 | ||||
-rw-r--r-- | tcg/tci.c | 6 |
3 files changed, 59 insertions, 9 deletions
diff --git a/tcg/tcg-pool.c.inc b/tcg/tcg-pool.c.inc index 82cbcc89bd..90c2e63b7f 100644 --- a/tcg/tcg-pool.c.inc +++ b/tcg/tcg-pool.c.inc @@ -140,6 +140,8 @@ static int tcg_out_pool_finalize(TCGContext *s) for (; p != NULL; p = p->next) { size_t size = sizeof(tcg_target_ulong) * p->nlong; + uintptr_t value; + if (!l || l->nlong != p->nlong || memcmp(l->data, p->data, size)) { if (unlikely(a > s->code_gen_highwater)) { return -1; @@ -148,7 +150,9 @@ static int tcg_out_pool_finalize(TCGContext *s) a += size; l = p; } - if (!patch_reloc(p->label, p->rtype, (intptr_t)a - size, p->addend)) { + + value = (uintptr_t)tcg_splitwx_to_rx(a) - size; + if (!patch_reloc(p->label, p->rtype, value, p->addend)) { return -2; } } @@ -162,6 +162,7 @@ static TCGContext **tcg_ctxs; static unsigned int n_tcg_ctxs; TCGv_env cpu_env = 0; void *tcg_code_gen_epilogue; +uintptr_t tcg_splitwx_diff; #ifndef CONFIG_TCG_INTERPRETER 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; if (p < region.start_aligned) { @@ -701,6 +703,7 @@ void tcg_region_init(void) size_t region_size; size_t n_regions; size_t i; + uintptr_t splitwx_diff; n_regions = tcg_n_regions(); @@ -731,6 +734,7 @@ void tcg_region_init(void) region.end -= page_size; /* set guard pages */ + splitwx_diff = tcg_splitwx_diff; for (i = 0; i < region.n; i++) { void *start, *end; int rc; @@ -738,6 +742,10 @@ void tcg_region_init(void) tcg_region_bounds(i, &start, &end); rc = qemu_mprotect_none(end, page_size); g_assert(!rc); + if (splitwx_diff) { + rc = qemu_mprotect_none(end + splitwx_diff, page_size); + g_assert(!rc); + } } tcg_region_trees_init(); @@ -752,6 +760,29 @@ void tcg_region_init(void) #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) { #ifdef CONFIG_PLUGIN @@ -1061,8 +1092,15 @@ void tcg_prologue_init(TCGContext *s) s->code_buf = buf0; 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 - tcg_qemu_tb_exec = (tcg_prologue_fn *)buf0; + tcg_qemu_tb_exec = (tcg_prologue_fn *)tcg_splitwx_to_rx(buf0); #endif /* 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; #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)); #endif @@ -4231,8 +4269,13 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) 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 QSIMPLEQ_INIT(&s->ldst_labels); @@ -4337,7 +4380,8 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) #ifndef CONFIG_TCG_INTERPRETER /* 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)); #endif @@ -481,9 +481,11 @@ static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition) * One possible operation in the pseudo code is a call to binary code. * Therefore, disable CFI checks in the interpreter function */ -uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, void *v_tb_ptr) +uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, + const void *v_tb_ptr) { - uint8_t *tb_ptr = v_tb_ptr; + /* TODO: Propagate const through this file. */ + uint8_t *tb_ptr = (uint8_t *)v_tb_ptr; tcg_target_ulong regs[TCG_TARGET_NB_REGS]; long tcg_temps[CPU_TEMP_BUF_NLONGS]; uintptr_t sp_value = (uintptr_t)(tcg_temps + CPU_TEMP_BUF_NLONGS); |