Commit db7a99cd authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20170619' into staging



Queued TCG patches

# gpg: Signature made Mon 19 Jun 2017 19:12:06 BST
# gpg:                using RSA key 0xAD1270CC4DD0279B
# gpg: Good signature from "Richard Henderson <rth7680@gmail.com>"
# gpg:                 aka "Richard Henderson <rth@redhat.com>"
# gpg:                 aka "Richard Henderson <rth@twiddle.net>"
# Primary key fingerprint: 9CB1 8DDA F8E8 49AD 2AFC  16A4 AD12 70CC 4DD0 279B

* remotes/rth/tags/pull-tcg-20170619:
  target/arm: Exit after clearing aarch64 interrupt mask
  target/s390x: Exit after changing PSW mask
  target/alpha: Use tcg_gen_lookup_and_goto_ptr
  tcg: Increase hit rate of lookup_tb_ptr
  tcg/arm: Use ldr (literal) for goto_tb
  tcg/arm: Try pc-relative addresses for movi
  tcg/arm: Remove limit on code buffer size
  tcg/arm: Use indirect branch for goto_tb
  tcg/aarch64: Use ADR in tcg_out_movi
  translate-all: consolidate tb init in tb_gen_code
  tcg: allocate TB structs before the corresponding translated code
  util: add cacheinfo

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 8dfaf23a 8da54b25
Loading
Loading
Loading
Loading
+26 −20
Original line number Diff line number Diff line
@@ -523,8 +523,6 @@ static inline PageDesc *page_find(tb_page_addr_t index)
# define MAX_CODE_GEN_BUFFER_SIZE  (32u * 1024 * 1024)
#elif defined(__aarch64__)
# define MAX_CODE_GEN_BUFFER_SIZE  (128ul * 1024 * 1024)
#elif defined(__arm__)
# define MAX_CODE_GEN_BUFFER_SIZE  (16u * 1024 * 1024)
#elif defined(__s390x__)
  /* We have a +- 4GB range on the branches; leave some slop.  */
# define MAX_CODE_GEN_BUFFER_SIZE  (3ul * 1024 * 1024 * 1024)
@@ -781,12 +779,13 @@ static inline void code_gen_alloc(size_t tb_size)
        exit(1);
    }

    /* Estimate a good size for the number of TBs we can support.  We
       still haven't deducted the prologue from the buffer size here,
       but that's minimal and won't affect the estimate much.  */
    tcg_ctx.code_gen_max_blocks
        = tcg_ctx.code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
    tcg_ctx.tb_ctx.tbs = g_new(TranslationBlock, tcg_ctx.code_gen_max_blocks);
    /* size this conservatively -- realloc later if needed */
    tcg_ctx.tb_ctx.tbs_size =
        tcg_ctx.code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE / 8;
    if (unlikely(!tcg_ctx.tb_ctx.tbs_size)) {
        tcg_ctx.tb_ctx.tbs_size = 64 * 1024;
    }
    tcg_ctx.tb_ctx.tbs = g_new(TranslationBlock *, tcg_ctx.tb_ctx.tbs_size);

    qemu_mutex_init(&tcg_ctx.tb_ctx.tb_lock);
}
@@ -828,16 +827,20 @@ bool tcg_enabled(void)
static TranslationBlock *tb_alloc(target_ulong pc)
{
    TranslationBlock *tb;
    TBContext *ctx;

    assert_tb_locked();

    if (tcg_ctx.tb_ctx.nb_tbs >= tcg_ctx.code_gen_max_blocks) {
    tb = tcg_tb_alloc(&tcg_ctx);
    if (unlikely(tb == NULL)) {
        return NULL;
    }
    tb = &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs++];
    tb->pc = pc;
    tb->cflags = 0;
    tb->invalid = false;
    ctx = &tcg_ctx.tb_ctx;
    if (unlikely(ctx->nb_tbs == ctx->tbs_size)) {
        ctx->tbs_size *= 2;
        ctx->tbs = g_renew(TranslationBlock *, ctx->tbs, ctx->tbs_size);
    }
    ctx->tbs[ctx->nb_tbs++] = tb;
    return tb;
}

@@ -850,8 +853,10 @@ void tb_free(TranslationBlock *tb)
       Ignore the hard cases and just back up if this TB happens to
       be the last one generated.  */
    if (tcg_ctx.tb_ctx.nb_tbs > 0 &&
            tb == &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs - 1]) {
        tcg_ctx.code_gen_ptr = tb->tc_ptr;
            tb == tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs - 1]) {
        size_t struct_size = ROUND_UP(sizeof(*tb), qemu_icache_linesize);

        tcg_ctx.code_gen_ptr = tb->tc_ptr - struct_size;
        tcg_ctx.tb_ctx.nb_tbs--;
    }
}
@@ -1279,9 +1284,11 @@ TranslationBlock *tb_gen_code(CPUState *cpu,

    gen_code_buf = tcg_ctx.code_gen_ptr;
    tb->tc_ptr = gen_code_buf;
    tb->pc = pc;
    tb->cs_base = cs_base;
    tb->flags = flags;
    tb->cflags = cflags;
    tb->invalid = false;

#ifdef CONFIG_PROFILER
    tcg_ctx.tb_count1++; /* includes aborted translations because of
@@ -1666,7 +1673,7 @@ static TranslationBlock *tb_find_pc(uintptr_t tc_ptr)
    m_max = tcg_ctx.tb_ctx.nb_tbs - 1;
    while (m_min <= m_max) {
        m = (m_min + m_max) >> 1;
        tb = &tcg_ctx.tb_ctx.tbs[m];
        tb = tcg_ctx.tb_ctx.tbs[m];
        v = (uintptr_t)tb->tc_ptr;
        if (v == tc_ptr) {
            return tb;
@@ -1676,7 +1683,7 @@ static TranslationBlock *tb_find_pc(uintptr_t tc_ptr)
            m_min = m + 1;
        }
    }
    return &tcg_ctx.tb_ctx.tbs[m_max];
    return tcg_ctx.tb_ctx.tbs[m_max];
}

#if !defined(CONFIG_USER_ONLY)
@@ -1874,7 +1881,7 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
    direct_jmp_count = 0;
    direct_jmp2_count = 0;
    for (i = 0; i < tcg_ctx.tb_ctx.nb_tbs; i++) {
        tb = &tcg_ctx.tb_ctx.tbs[i];
        tb = tcg_ctx.tb_ctx.tbs[i];
        target_code_size += tb->size;
        if (tb->size > max_target_code_size) {
            max_target_code_size = tb->size;
@@ -1894,8 +1901,7 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
    cpu_fprintf(f, "gen code size       %td/%zd\n",
                tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer,
                tcg_ctx.code_gen_highwater - tcg_ctx.code_gen_buffer);
    cpu_fprintf(f, "TB count            %d/%d\n",
            tcg_ctx.tb_ctx.nb_tbs, tcg_ctx.code_gen_max_blocks);
    cpu_fprintf(f, "TB count            %d\n", tcg_ctx.tb_ctx.nb_tbs);
    cpu_fprintf(f, "TB avg target size  %d max=%d bytes\n",
            tcg_ctx.tb_ctx.nb_tbs ? target_code_size /
                    tcg_ctx.tb_ctx.nb_tbs : 0,
+1 −4
Original line number Diff line number Diff line
@@ -301,7 +301,7 @@ static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu,
#define CODE_GEN_AVG_BLOCK_SIZE 150
#endif

#if defined(__arm__) || defined(_ARCH_PPC) \
#if defined(_ARCH_PPC) \
    || defined(__x86_64__) || defined(__i386__) \
    || defined(__sparc__) || defined(__aarch64__) \
    || defined(__s390x__) || defined(__mips__) \
@@ -401,9 +401,6 @@ static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
#elif defined(__aarch64__)
void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr);
#define tb_set_jmp_target1 aarch64_tb_set_jmp_target
#elif defined(__arm__)
void arm_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr);
#define tb_set_jmp_target1 arm_tb_set_jmp_target
#elif defined(__sparc__) || defined(__mips__)
void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr);
#else
+2 −1
Original line number Diff line number Diff line
@@ -31,8 +31,9 @@ typedef struct TBContext TBContext;

struct TBContext {

    TranslationBlock *tbs;
    TranslationBlock **tbs;
    struct qht htable;
    size_t tbs_size;
    int nb_tbs;
    /* any access to the tbs or the page table must use this lock */
    QemuMutex tb_lock;
+3 −0
Original line number Diff line number Diff line
@@ -483,4 +483,7 @@ char *qemu_get_pid_name(pid_t pid);
 */
pid_t qemu_fork(Error **errp);

extern int qemu_icache_linesize;
extern int qemu_dcache_linesize;

#endif
+22 −5
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ typedef enum {
       the PC (for whatever reason), so there's no need to do it again on
       exiting the TB.  */
    EXIT_PC_UPDATED,
    EXIT_PC_UPDATED_NOCHAIN,

    /* We are exiting the TB, but have neither emitted a goto_tb, nor
       updated the PC for the next instruction to be executed.  */
@@ -458,11 +459,17 @@ static bool in_superpage(DisasContext *ctx, int64_t addr)
#endif
}

static bool use_exit_tb(DisasContext *ctx)
{
    return ((ctx->tb->cflags & CF_LAST_IO)
            || ctx->singlestep_enabled
            || singlestep);
}

static bool use_goto_tb(DisasContext *ctx, uint64_t dest)
{
    /* Suppress goto_tb in the case of single-steping and IO.  */
    if ((ctx->tb->cflags & CF_LAST_IO)
        || ctx->singlestep_enabled || singlestep) {
    if (unlikely(use_exit_tb(ctx))) {
        return false;
    }
#ifndef CONFIG_USER_ONLY
@@ -1198,7 +1205,10 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
            tcg_gen_andi_i64(tmp, ctx->ir[IR_A0], PS_INT_MASK);
            tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, ps));
            tcg_temp_free(tmp);
            break;

            /* Allow interrupts to be recognized right away.  */
            tcg_gen_movi_i64(cpu_pc, ctx->pc);
            return EXIT_PC_UPDATED_NOCHAIN;

        case 0x36:
            /* RDPS */
@@ -1266,7 +1276,7 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
           need the page permissions check.  We'll see the existence of
           the page when we create the TB, and we'll flush all TBs if
           we change the PAL base register.  */
        if (!ctx->singlestep_enabled && !(ctx->tb->cflags & CF_LAST_IO)) {
        if (!use_exit_tb(ctx)) {
            tcg_gen_goto_tb(0);
            tcg_gen_movi_i64(cpu_pc, entry);
            tcg_gen_exit_tb((uintptr_t)ctx->tb);
@@ -2686,7 +2696,8 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
        tcg_gen_andi_i64(tmp, vb, 1);
        tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, pal_mode));
        tcg_gen_andi_i64(cpu_pc, vb, ~3);
        ret = EXIT_PC_UPDATED;
        /* Allow interrupts to be recognized right away.  */
        ret = EXIT_PC_UPDATED_NOCHAIN;
        break;
#else
        goto invalid_opc;
@@ -3010,6 +3021,12 @@ void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
        tcg_gen_movi_i64(cpu_pc, ctx.pc);
        /* FALLTHRU */
    case EXIT_PC_UPDATED:
        if (!use_exit_tb(&ctx)) {
            tcg_gen_lookup_and_goto_ptr(cpu_pc);
            break;
        }
        /* FALLTHRU */
    case EXIT_PC_UPDATED_NOCHAIN:
        if (ctx.singlestep_enabled) {
            gen_excp_1(EXCP_DEBUG, 0);
        } else {
Loading