aboutsummaryrefslogtreecommitdiff
path: root/accel/tcg
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-04-28 11:43:09 +0100
committerPeter Maydell <peter.maydell@linaro.org>2019-04-28 11:43:10 +0100
commite0fb2c3d89aa77057ac4aa073e01f4ca484449b0 (patch)
treef28672f770bfe0b95165c10cad34dbaf214fdbea /accel/tcg
parent9ec34ecc97bcd5df04b0f67a774d79ffcd6b0a11 (diff)
parentef5dae6805cce7b59d129d801bdc5db71bcbd60d (diff)
Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20190426' into staging
Add tcg_gen_extract2_*. Deal with overflow of TranslationBlocks. Respect access_type in io_readx. # gpg: Signature made Fri 26 Apr 2019 18:17:01 BST # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full] # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * remotes/rth/tags/pull-tcg-20190426: cputlb: Fix io_readx() to respect the access_type tcg/arm: Restrict constant pool displacement to 12 bits tcg/ppc: Allow the constant pool to overflow at 32k tcg: Restart TB generation after out-of-line ldst overflow tcg: Restart TB generation after constant pool overflow tcg: Restart TB generation after relocation overflow tcg: Restart after TB code generation overflow tcg: Hoist max_insns computation to tb_gen_code tcg/aarch64: Support INDEX_op_extract2_{i32,i64} tcg/arm: Support INDEX_op_extract2_i32 tcg/i386: Support INDEX_op_extract2_{i32,i64} tcg: Use extract2 in tcg_gen_deposit_{i32,i64} tcg: Use deposit and extract2 in tcg_gen_shifti_i64 tcg: Add INDEX_op_extract2_{i32,i64} tcg: Implement tcg_gen_extract2_{i32,i64} Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'accel/tcg')
-rw-r--r--accel/tcg/cputlb.c5
-rw-r--r--accel/tcg/translate-all.c53
-rw-r--r--accel/tcg/translator.c15
3 files changed, 50 insertions, 23 deletions
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 88cc8389e9..f2f618217d 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -878,10 +878,11 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
CPUTLBEntry *entry;
target_ulong tlb_addr;
- tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
+ tlb_fill(cpu, addr, size, access_type, mmu_idx, retaddr);
entry = tlb_entry(env, mmu_idx, addr);
- tlb_addr = entry->addr_read;
+ tlb_addr = (access_type == MMU_DATA_LOAD ?
+ entry->addr_read : entry->addr_code);
if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
/* RAM access */
uintptr_t haddr = addr + entry->addend;
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 75a6cf49f1..20b59f93f4 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1674,7 +1674,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
tb_page_addr_t phys_pc, phys_page2;
target_ulong virt_page2;
tcg_insn_unit *gen_code_buf;
- int gen_code_size, search_size;
+ int gen_code_size, search_size, max_insns;
#ifdef CONFIG_PROFILER
TCGProfile *prof = &tcg_ctx->prof;
int64_t ti;
@@ -1692,6 +1692,17 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
cflags &= ~CF_CLUSTER_MASK;
cflags |= cpu->cluster_index << CF_CLUSTER_SHIFT;
+ max_insns = cflags & CF_COUNT_MASK;
+ if (max_insns == 0) {
+ max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
+ if (cpu->singlestep_enabled || singlestep) {
+ max_insns = 1;
+ }
+
buffer_overflow:
tb = tb_alloc(pc);
if (unlikely(!tb)) {
@@ -1711,6 +1722,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
tb->cflags = cflags;
tb->trace_vcpu_dstate = *cpu->trace_dstate;
tcg_ctx->tb_cflags = cflags;
+ tb_overflow:
#ifdef CONFIG_PROFILER
/* includes aborted translations because of exceptions */
@@ -1721,7 +1733,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
tcg_func_start(tcg_ctx);
tcg_ctx->cpu = ENV_GET_CPU(env);
- gen_intermediate_code(cpu, tb);
+ gen_intermediate_code(cpu, tb, max_insns);
tcg_ctx->cpu = NULL;
trace_translate_block(tb, tb->pc, tb->tc.ptr);
@@ -1744,14 +1756,39 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
ti = profile_getclock();
#endif
- /* ??? Overflow could be handled better here. In particular, we
- don't need to re-do gen_intermediate_code, nor should we re-do
- the tcg optimization currently hidden inside tcg_gen_code. All
- that should be required is to flush the TBs, allocate a new TB,
- re-initialize it per above, and re-do the actual code generation. */
gen_code_size = tcg_gen_code(tcg_ctx, tb);
if (unlikely(gen_code_size < 0)) {
- goto buffer_overflow;
+ switch (gen_code_size) {
+ case -1:
+ /*
+ * Overflow of code_gen_buffer, or the current slice of it.
+ *
+ * TODO: We don't need to re-do gen_intermediate_code, nor
+ * should we re-do the tcg optimization currently hidden
+ * inside tcg_gen_code. All that should be required is to
+ * flush the TBs, allocate a new TB, re-initialize it per
+ * above, and re-do the actual code generation.
+ */
+ goto buffer_overflow;
+
+ case -2:
+ /*
+ * The code generated for the TranslationBlock is too large.
+ * The maximum size allowed by the unwind info is 64k.
+ * There may be stricter constraints from relocations
+ * in the tcg backend.
+ *
+ * Try again with half as many insns as we attempted this time.
+ * If a single insn overflows, there's a bug somewhere...
+ */
+ max_insns = tb->icount;
+ assert(max_insns > 1);
+ max_insns /= 2;
+ goto tb_overflow;
+
+ default:
+ g_assert_not_reached();
+ }
}
search_size = encode_search(tb, (void *)gen_code_buf + gen_code_size);
if (unlikely(search_size < 0)) {
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index afd0a49ea6..8d65ead708 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -32,7 +32,7 @@ void translator_loop_temp_check(DisasContextBase *db)
}
void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
- CPUState *cpu, TranslationBlock *tb)
+ CPUState *cpu, TranslationBlock *tb, int max_insns)
{
int bp_insn = 0;
@@ -42,20 +42,9 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
db->pc_next = db->pc_first;
db->is_jmp = DISAS_NEXT;
db->num_insns = 0;
+ db->max_insns = max_insns;
db->singlestep_enabled = cpu->singlestep_enabled;
- /* Instruction counting */
- db->max_insns = tb_cflags(db->tb) & CF_COUNT_MASK;
- if (db->max_insns == 0) {
- db->max_insns = CF_COUNT_MASK;
- }
- if (db->max_insns > TCG_MAX_INSNS) {
- db->max_insns = TCG_MAX_INSNS;
- }
- if (db->singlestep_enabled || singlestep) {
- db->max_insns = 1;
- }
-
ops->init_disas_context(db, cpu);
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */