diff options
Diffstat (limited to 'accel')
| -rw-r--r-- | accel/tcg/cpu-exec.c | 2 | ||||
| -rw-r--r-- | accel/tcg/cputlb.c | 12 | ||||
| -rw-r--r-- | accel/tcg/monitor.c | 1 | ||||
| -rw-r--r-- | accel/tcg/perf.c | 19 | ||||
| -rw-r--r-- | accel/tcg/plugin-gen.c | 6 | ||||
| -rw-r--r-- | accel/tcg/tcg-accel-ops-mttcg.c | 2 | ||||
| -rw-r--r-- | accel/tcg/tcg-accel-ops-rr.c | 2 | ||||
| -rw-r--r-- | accel/tcg/tcg-all.c | 1 | ||||
| -rw-r--r-- | accel/tcg/tcg-runtime-gvec.c | 2 | ||||
| -rw-r--r-- | accel/tcg/tcg-runtime.c | 6 | ||||
| -rw-r--r-- | accel/tcg/translate-all.c | 30 | ||||
| -rw-r--r-- | accel/tcg/translator.c | 140 |
12 files changed, 194 insertions, 29 deletions
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 60ca9e229e..1cf4f1fa22 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -297,7 +297,7 @@ static void log_cpu_exec(target_ulong pc, CPUState *cpu, { if (qemu_log_in_addr_range(pc)) { qemu_log_mask(CPU_LOG_EXEC, - "Trace %d: %p [" TARGET_FMT_lx + "Trace %d: %p [%08" PRIx64 "/" TARGET_FMT_lx "/%08x/%08x] %s\n", cpu->cpu_index, tb->tc.ptr, tb->cs_base, pc, tb->flags, tb->cflags, lookup_symbol(pc)); diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 90c72c9940..5e2ca47243 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -29,7 +29,7 @@ #include "tcg/tcg.h" #include "qemu/error-report.h" #include "exec/log.h" -#include "exec/helper-proto.h" +#include "exec/helper-proto-common.h" #include "qemu/atomic.h" #include "qemu/atomic128.h" #include "exec/translate-all.h" @@ -40,7 +40,7 @@ #include "qemu/plugin-memory.h" #endif #include "tcg/tcg-ldst.h" -#include "exec/helper-proto.h" +#include "tcg/oversized-guest.h" /* DEBUG defines, enable DEBUG_TLB_LOG to log to the CPU_LOG_MMU target */ /* #define DEBUG_TLB */ @@ -1000,11 +1000,15 @@ static void tlb_reset_dirty_range_locked(CPUTLBEntry *tlb_entry, addr &= TARGET_PAGE_MASK; addr += tlb_entry->addend; if ((addr - start) < length) { -#if TCG_OVERSIZED_GUEST +#if TARGET_LONG_BITS == 32 + uint32_t *ptr_write = (uint32_t *)&tlb_entry->addr_write; + ptr_write += HOST_BIG_ENDIAN; + qatomic_set(ptr_write, *ptr_write | TLB_NOTDIRTY); +#elif TCG_OVERSIZED_GUEST tlb_entry->addr_write |= TLB_NOTDIRTY; #else qatomic_set(&tlb_entry->addr_write, - tlb_entry->addr_write | TLB_NOTDIRTY); + tlb_entry->addr_write | TLB_NOTDIRTY); #endif } } diff --git a/accel/tcg/monitor.c b/accel/tcg/monitor.c index 92fce580f1..f171bc6f5e 100644 --- a/accel/tcg/monitor.c +++ b/accel/tcg/monitor.c @@ -15,6 +15,7 @@ #include "sysemu/cpus.h" #include "sysemu/cpu-timers.h" #include "sysemu/tcg.h" +#include "tcg/tcg.h" #include "internal.h" diff --git a/accel/tcg/perf.c b/accel/tcg/perf.c index 65e35ea3b9..cd1aa99a7e 100644 --- a/accel/tcg/perf.c +++ b/accel/tcg/perf.c @@ -111,6 +111,8 @@ static void write_perfmap_entry(const void *start, size_t insn, } static FILE *jitdump; +static size_t perf_marker_size; +static void *perf_marker = MAP_FAILED; #define JITHEADER_MAGIC 0x4A695444 #define JITHEADER_VERSION 1 @@ -190,7 +192,6 @@ void perf_enable_jitdump(void) { struct jitheader header; char jitdump_file[32]; - void *perf_marker; if (!use_rt_clock) { warn_report("CLOCK_MONOTONIC is not available, proceeding without jitdump"); @@ -210,7 +211,8 @@ void perf_enable_jitdump(void) * PERF_RECORD_MMAP or PERF_RECORD_MMAP2 event is of the form jit-%d.dump * and will process it as a jitdump file. */ - perf_marker = mmap(NULL, qemu_real_host_page_size(), PROT_READ | PROT_EXEC, + perf_marker_size = qemu_real_host_page_size(); + perf_marker = mmap(NULL, perf_marker_size, PROT_READ | PROT_EXEC, MAP_PRIVATE, fileno(jitdump), 0); if (perf_marker == MAP_FAILED) { warn_report("Could not map %s: %s, proceeding without jitdump", @@ -311,7 +313,8 @@ void perf_report_code(uint64_t guest_pc, TranslationBlock *tb, const void *start) { struct debuginfo_query *q; - size_t insn; + size_t insn, start_words; + uint64_t *gen_insn_data; if (!perfmap && !jitdump) { return; @@ -325,9 +328,12 @@ void perf_report_code(uint64_t guest_pc, TranslationBlock *tb, debuginfo_lock(); /* Query debuginfo for each guest instruction. */ + gen_insn_data = tcg_ctx->gen_insn_data; + start_words = tcg_ctx->insn_start_words; + for (insn = 0; insn < tb->icount; insn++) { /* FIXME: This replicates the restore_state_to_opc() logic. */ - q[insn].address = tcg_ctx->gen_insn_data[insn][0]; + q[insn].address = gen_insn_data[insn * start_words + 0]; if (tb_cflags(tb) & CF_PCREL) { q[insn].address |= (guest_pc & TARGET_PAGE_MASK); } else { @@ -368,6 +374,11 @@ void perf_exit(void) perfmap = NULL; } + if (perf_marker != MAP_FAILED) { + munmap(perf_marker, perf_marker_size); + perf_marker = MAP_FAILED; + } + if (jitdump) { fclose(jitdump); jitdump = NULL; diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c index 5b73a39ce5..5c13615112 100644 --- a/accel/tcg/plugin-gen.c +++ b/accel/tcg/plugin-gen.c @@ -43,12 +43,18 @@ * CPU's index into a TCG temp, since the first callback did it already. */ #include "qemu/osdep.h" +#include "cpu.h" #include "tcg/tcg.h" #include "tcg/tcg-temp-internal.h" #include "tcg/tcg-op.h" #include "exec/exec-all.h" #include "exec/plugin-gen.h" #include "exec/translator.h" +#include "exec/helper-proto-common.h" + +#define HELPER_H "accel/tcg/plugin-helpers.h" +#include "exec/helper-info.c.inc" +#undef HELPER_H #ifdef CONFIG_SOFTMMU # define CONFIG_SOFTMMU_GATE 1 diff --git a/accel/tcg/tcg-accel-ops-mttcg.c b/accel/tcg/tcg-accel-ops-mttcg.c index d50239e0e2..5d72c9b1bd 100644 --- a/accel/tcg/tcg-accel-ops-mttcg.c +++ b/accel/tcg/tcg-accel-ops-mttcg.c @@ -32,7 +32,7 @@ #include "qemu/guest-random.h" #include "exec/exec-all.h" #include "hw/boards.h" - +#include "tcg/tcg.h" #include "tcg-accel-ops.h" #include "tcg-accel-ops-mttcg.h" diff --git a/accel/tcg/tcg-accel-ops-rr.c b/accel/tcg/tcg-accel-ops-rr.c index b6d10fa9a2..70b9b89073 100644 --- a/accel/tcg/tcg-accel-ops-rr.c +++ b/accel/tcg/tcg-accel-ops-rr.c @@ -32,7 +32,7 @@ #include "qemu/notify.h" #include "qemu/guest-random.h" #include "exec/exec-all.h" - +#include "tcg/tcg.h" #include "tcg-accel-ops.h" #include "tcg-accel-ops-rr.h" #include "tcg-accel-ops-icount.h" diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c index a831f8d7c3..02af6a2891 100644 --- a/accel/tcg/tcg-all.c +++ b/accel/tcg/tcg-all.c @@ -28,6 +28,7 @@ #include "exec/replay-core.h" #include "sysemu/cpu-timers.h" #include "tcg/tcg.h" +#include "tcg/oversized-guest.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/accel.h" diff --git a/accel/tcg/tcg-runtime-gvec.c b/accel/tcg/tcg-runtime-gvec.c index 97399493d5..6c99f952ca 100644 --- a/accel/tcg/tcg-runtime-gvec.c +++ b/accel/tcg/tcg-runtime-gvec.c @@ -20,7 +20,7 @@ #include "qemu/osdep.h" #include "qemu/host-utils.h" #include "cpu.h" -#include "exec/helper-proto.h" +#include "exec/helper-proto-common.h" #include "tcg/tcg-gvec-desc.h" diff --git a/accel/tcg/tcg-runtime.c b/accel/tcg/tcg-runtime.c index e4e030043f..9fa539ad3d 100644 --- a/accel/tcg/tcg-runtime.c +++ b/accel/tcg/tcg-runtime.c @@ -24,13 +24,17 @@ #include "qemu/osdep.h" #include "qemu/host-utils.h" #include "cpu.h" -#include "exec/helper-proto.h" +#include "exec/helper-proto-common.h" #include "exec/cpu_ldst.h" #include "exec/exec-all.h" #include "disas/disas.h" #include "exec/log.h" #include "tcg/tcg.h" +#define HELPER_H "accel/tcg/tcg-runtime.h" +#include "exec/helper-info.c.inc" +#undef HELPER_H + /* 32-bit helpers */ int32_t HELPER(div_i32)(int32_t arg1, int32_t arg2) diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index bf814b9e81..c4d081f5ad 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -19,7 +19,6 @@ #include "qemu/osdep.h" -#define NO_CPU_IO_DEFS #include "trace.h" #include "disas/disas.h" #include "exec/exec-all.h" @@ -64,6 +63,7 @@ #include "tb-context.h" #include "internal.h" #include "perf.h" +#include "tcg/insn-start-words.h" TBContext tb_ctx; @@ -127,22 +127,26 @@ static int64_t decode_sleb128(const uint8_t **pp) static int encode_search(TranslationBlock *tb, uint8_t *block) { uint8_t *highwater = tcg_ctx->code_gen_highwater; + uint64_t *insn_data = tcg_ctx->gen_insn_data; + uint16_t *insn_end_off = tcg_ctx->gen_insn_end_off; uint8_t *p = block; int i, j, n; for (i = 0, n = tb->icount; i < n; ++i) { - uint64_t prev; + uint64_t prev, curr; for (j = 0; j < TARGET_INSN_START_WORDS; ++j) { if (i == 0) { prev = (!(tb_cflags(tb) & CF_PCREL) && j == 0 ? tb->pc : 0); } else { - prev = tcg_ctx->gen_insn_data[i - 1][j]; + prev = insn_data[(i - 1) * TARGET_INSN_START_WORDS + j]; } - p = encode_sleb128(p, tcg_ctx->gen_insn_data[i][j] - prev); + curr = insn_data[i * TARGET_INSN_START_WORDS + j]; + p = encode_sleb128(p, curr - prev); } - prev = (i == 0 ? 0 : tcg_ctx->gen_insn_end_off[i - 1]); - p = encode_sleb128(p, tcg_ctx->gen_insn_end_off[i] - prev); + prev = (i == 0 ? 0 : insn_end_off[i - 1]); + curr = insn_end_off[i]; + p = encode_sleb128(p, curr - prev); /* Test for (pending) buffer overflow. The assumption is that any one row beginning below the high water mark cannot overrun @@ -350,11 +354,19 @@ TranslationBlock *tb_gen_code(CPUState *cpu, tb_set_page_addr0(tb, phys_pc); tb_set_page_addr1(tb, -1); tcg_ctx->gen_tb = tb; - tcg_ctx->addr_type = TCG_TYPE_TL; + tcg_ctx->addr_type = TARGET_LONG_BITS == 32 ? TCG_TYPE_I32 : TCG_TYPE_I64; #ifdef CONFIG_SOFTMMU tcg_ctx->page_bits = TARGET_PAGE_BITS; tcg_ctx->page_mask = TARGET_PAGE_MASK; tcg_ctx->tlb_dyn_max_bits = CPU_TLB_DYN_MAX_BITS; + tcg_ctx->tlb_fast_offset = + (int)offsetof(ArchCPU, neg.tlb.f) - (int)offsetof(ArchCPU, env); +#endif + tcg_ctx->insn_start_words = TARGET_INSN_START_WORDS; +#ifdef TCG_GUEST_DEFAULT_MO + tcg_ctx->guest_mo = TCG_GUEST_DEFAULT_MO; +#else + tcg_ctx->guest_mo = TCG_MO_ALL; #endif tb_overflow: @@ -449,7 +461,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, fprintf(logfile, "OUT: [size=%d]\n", gen_code_size); fprintf(logfile, " -- guest addr 0x%016" PRIx64 " + tb prologue\n", - tcg_ctx->gen_insn_data[insn][0]); + tcg_ctx->gen_insn_data[insn * TARGET_INSN_START_WORDS]); chunk_start = tcg_ctx->gen_insn_end_off[insn]; disas(logfile, tb->tc.ptr, chunk_start); @@ -462,7 +474,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, size_t chunk_end = tcg_ctx->gen_insn_end_off[insn]; if (chunk_end > chunk_start) { fprintf(logfile, " -- guest addr 0x%016" PRIx64 "\n", - tcg_ctx->gen_insn_data[insn][0]); + tcg_ctx->gen_insn_data[insn * TARGET_INSN_START_WORDS]); disas(logfile, tb->tc.ptr + chunk_start, chunk_end - chunk_start); chunk_start = chunk_end; diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 6120ef2a92..918a455e73 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -8,15 +8,114 @@ */ #include "qemu/osdep.h" +#include "qemu/log.h" #include "qemu/error-report.h" -#include "tcg/tcg.h" -#include "tcg/tcg-op.h" #include "exec/exec-all.h" -#include "exec/gen-icount.h" -#include "exec/log.h" #include "exec/translator.h" +#include "exec/translate-all.h" #include "exec/plugin-gen.h" -#include "exec/replay-core.h" +#include "tcg/tcg-op-common.h" + +static void gen_io_start(void) +{ + tcg_gen_st_i32(tcg_constant_i32(1), cpu_env, + offsetof(ArchCPU, parent_obj.can_do_io) - + offsetof(ArchCPU, env)); +} + +bool translator_io_start(DisasContextBase *db) +{ + uint32_t cflags = tb_cflags(db->tb); + + if (!(cflags & CF_USE_ICOUNT)) { + return false; + } + if (db->num_insns == db->max_insns && (cflags & CF_LAST_IO)) { + /* Already started in translator_loop. */ + return true; + } + + gen_io_start(); + + /* + * Ensure that this instruction will be the last in the TB. + * The target may override this to something more forceful. + */ + if (db->is_jmp == DISAS_NEXT) { + db->is_jmp = DISAS_TOO_MANY; + } + return true; +} + +static TCGOp *gen_tb_start(uint32_t cflags) +{ + TCGv_i32 count = tcg_temp_new_i32(); + TCGOp *icount_start_insn = NULL; + + tcg_gen_ld_i32(count, cpu_env, + offsetof(ArchCPU, neg.icount_decr.u32) - + offsetof(ArchCPU, env)); + + if (cflags & CF_USE_ICOUNT) { + /* + * We emit a sub with a dummy immediate argument. Keep the insn index + * of the sub so that we later (when we know the actual insn count) + * can update the argument with the actual insn count. + */ + tcg_gen_sub_i32(count, count, tcg_constant_i32(0)); + icount_start_insn = tcg_last_op(); + } + + /* + * Emit the check against icount_decr.u32 to see if we should exit + * unless we suppress the check with CF_NOIRQ. If we are using + * icount and have suppressed interruption the higher level code + * should have ensured we don't run more instructions than the + * budget. + */ + if (cflags & CF_NOIRQ) { + tcg_ctx->exitreq_label = NULL; + } else { + tcg_ctx->exitreq_label = gen_new_label(); + tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, tcg_ctx->exitreq_label); + } + + if (cflags & CF_USE_ICOUNT) { + tcg_gen_st16_i32(count, cpu_env, + offsetof(ArchCPU, neg.icount_decr.u16.low) - + offsetof(ArchCPU, env)); + /* + * cpu->can_do_io is cleared automatically here at the beginning of + * each translation block. The cost is minimal and only paid for + * -icount, plus it would be very easy to forget doing it in the + * translator. Doing it here means we don't need a gen_io_end() to + * go with gen_io_start(). + */ + tcg_gen_st_i32(tcg_constant_i32(0), cpu_env, + offsetof(ArchCPU, parent_obj.can_do_io) - + offsetof(ArchCPU, env)); + } + + return icount_start_insn; +} + +static void gen_tb_end(const TranslationBlock *tb, uint32_t cflags, + TCGOp *icount_start_insn, int num_insns) +{ + if (cflags & CF_USE_ICOUNT) { + /* + * Update the num_insn immediate parameter now that we know + * the actual insn count. + */ + tcg_set_insn_param(icount_start_insn, 2, + tcgv_i32_arg(tcg_constant_i32(num_insns))); + } + + if (tcg_ctx->exitreq_label) { + gen_set_label(tcg_ctx->exitreq_label); + tcg_gen_exit_tb(tb, TB_EXIT_REQUESTED); + } +} bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest) { @@ -34,6 +133,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns, const TranslatorOps *ops, DisasContextBase *db) { uint32_t cflags = tb_cflags(tb); + TCGOp *icount_start_insn; bool plugin_enabled; /* Initialize DisasContext */ @@ -55,7 +155,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns, tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ /* Start translating. */ - gen_tb_start(db->tb); + icount_start_insn = gen_tb_start(cflags); ops->tb_start(db, cpu); tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ @@ -112,7 +212,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns, /* Emit code to exit the TB, as indicated by db->is_jmp. */ ops->tb_stop(db, cpu); - gen_tb_end(db->tb, db->num_insns); + gen_tb_end(tb, cflags, icount_start_insn, db->num_insns); if (plugin_enabled) { plugin_gen_tb_end(cpu); @@ -185,6 +285,27 @@ static void *translator_access(CPUArchState *env, DisasContextBase *db, return host + (pc - base); } +static void plugin_insn_append(abi_ptr pc, const void *from, size_t size) +{ +#ifdef CONFIG_PLUGIN + struct qemu_plugin_insn *insn = tcg_ctx->plugin_insn; + abi_ptr off; + + if (insn == NULL) { + return; + } + off = pc - insn->vaddr; + if (off < insn->data->len) { + g_byte_array_set_size(insn->data, off); + } else if (off > insn->data->len) { + /* we have an unexpected gap */ + g_assert_not_reached(); + } + + insn->data = g_byte_array_append(insn->data, from, size); +#endif +} + uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc) { uint8_t ret; @@ -243,3 +364,8 @@ uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, abi_ptr pc) plugin_insn_append(pc, &plug, sizeof(ret)); return ret; } + +void translator_fake_ldb(uint8_t insn8, abi_ptr pc) +{ + plugin_insn_append(pc, &insn8, sizeof(insn8)); +} |