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

Merge remote-tracking branch 'remotes/rth/tags/cota-target-pull-request' into staging



* Fix all next_page checks for overflow.
* Convert six targets to the translator loop.

# gpg: Signature made Wed 09 May 2018 18:20:43 BST
# gpg:                using RSA key 64DF38E8AF7E215F
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>"
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A  05C0 64DF 38E8 AF7E 215F

* remotes/rth/tags/cota-target-pull-request: (28 commits)
  target/riscv: convert to TranslatorOps
  target/riscv: convert to DisasContextBase
  target/riscv: convert to DisasJumpType
  target/openrisc: convert to TranslatorOps
  target/openrisc: convert to DisasContextBase
  target/s390x: convert to TranslatorOps
  target/s390x: convert to DisasContextBase
  target/s390x: convert to DisasJumpType
  target/mips: convert to TranslatorOps
  target/mips: use *ctx for DisasContext
  target/mips: convert to DisasContextBase
  target/mips: convert to DisasJumpType
  target/mips: use lookup_and_goto_ptr on BS_STOP
  target/sparc: convert to TranslatorOps
  target/sparc: convert to DisasContextBase
  target/sparc: convert to DisasJumpType
  target/sh4: convert to TranslatorOps
  translator: merge max_insns into DisasContextBase
  target/mips: avoid integer overflow in next_page PC check
  target/s390x: avoid integer overflow in next_page PC check
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 6d7cde80 5b4f1d2d
Loading
Loading
Loading
Loading
+10 −11
Original line number Diff line number Diff line
@@ -34,8 +34,6 @@ void translator_loop_temp_check(DisasContextBase *db)
void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
                     CPUState *cpu, TranslationBlock *tb)
{
    int max_insns;

    /* Initialize DisasContext */
    db->tb = tb;
    db->pc_first = tb->pc;
@@ -45,18 +43,18 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
    db->singlestep_enabled = cpu->singlestep_enabled;

    /* Instruction counting */
    max_insns = tb_cflags(db->tb) & CF_COUNT_MASK;
    if (max_insns == 0) {
        max_insns = CF_COUNT_MASK;
    db->max_insns = tb_cflags(db->tb) & CF_COUNT_MASK;
    if (db->max_insns == 0) {
        db->max_insns = CF_COUNT_MASK;
    }
    if (max_insns > TCG_MAX_INSNS) {
        max_insns = TCG_MAX_INSNS;
    if (db->max_insns > TCG_MAX_INSNS) {
        db->max_insns = TCG_MAX_INSNS;
    }
    if (db->singlestep_enabled || singlestep) {
        max_insns = 1;
        db->max_insns = 1;
    }

    max_insns = ops->init_disas_context(db, cpu, max_insns);
    ops->init_disas_context(db, cpu);
    tcg_debug_assert(db->is_jmp == DISAS_NEXT);  /* no early exit */

    /* Reset the temp count so that we can identify leaks */
@@ -95,7 +93,8 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
           update db->pc_next and db->is_jmp to indicate what should be
           done next -- either exiting this loop or locate the start of
           the next instruction.  */
        if (db->num_insns == max_insns && (tb_cflags(db->tb) & CF_LAST_IO)) {
        if (db->num_insns == db->max_insns
            && (tb_cflags(db->tb) & CF_LAST_IO)) {
            /* Accept I/O on the last instruction.  */
            gen_io_start();
            ops->translate_insn(db, cpu);
@@ -111,7 +110,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,

        /* Stop translation if the output buffer is full,
           or we have executed all of the allowed instructions.  */
        if (tcg_op_buf_full() || db->num_insns >= max_insns) {
        if (tcg_op_buf_full() || db->num_insns >= db->max_insns) {
            db->is_jmp = DISAS_TOO_MANY;
            break;
        }
+4 −4
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ typedef enum DisasJumpType {
 *           disassembly).
 * @is_jmp: What instruction to disassemble next.
 * @num_insns: Number of translated instructions (including current).
 * @max_insns: Maximum number of instructions to be translated in this TB.
 * @singlestep_enabled: "Hardware" single stepping enabled.
 *
 * Architecture-agnostic disassembly context.
@@ -67,7 +68,8 @@ typedef struct DisasContextBase {
    target_ulong pc_first;
    target_ulong pc_next;
    DisasJumpType is_jmp;
    unsigned int num_insns;
    int num_insns;
    int max_insns;
    bool singlestep_enabled;
} DisasContextBase;

@@ -76,7 +78,6 @@ typedef struct DisasContextBase {
 * @init_disas_context:
 *      Initialize the target-specific portions of DisasContext struct.
 *      The generic DisasContextBase has already been initialized.
 *      Return max_insns, modified as necessary by db->tb->flags.
 *
 * @tb_start:
 *      Emit any code required before the start of the main loop,
@@ -106,8 +107,7 @@ typedef struct DisasContextBase {
 *      Print instruction disassembly to log.
 */
typedef struct TranslatorOps {
    int (*init_disas_context)(DisasContextBase *db, CPUState *cpu,
                              int max_insns);
    void (*init_disas_context)(DisasContextBase *db, CPUState *cpu);
    void (*tb_start)(DisasContextBase *db, CPUState *cpu);
    void (*insn_start)(DisasContextBase *db, CPUState *cpu);
    bool (*breakpoint_check)(DisasContextBase *db, CPUState *cpu,
+2 −4
Original line number Diff line number Diff line
@@ -2919,8 +2919,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
    return ret;
}

static int alpha_tr_init_disas_context(DisasContextBase *dcbase,
                                       CPUState *cpu, int max_insns)
static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
{
    DisasContext *ctx = container_of(dcbase, DisasContext, base);
    CPUAlphaState *env = cpu->env_ptr;
@@ -2959,8 +2958,7 @@ static int alpha_tr_init_disas_context(DisasContextBase *dcbase,
        mask = TARGET_PAGE_MASK;
    }
    bound = -(ctx->base.pc_first | mask) / 4;

    return MIN(max_insns, bound);
    ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
}

static void alpha_tr_tb_start(DisasContextBase *db, CPUState *cpu)
+3 −5
Original line number Diff line number Diff line
@@ -13224,8 +13224,8 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
    free_tmp_a64(s);
}

static int aarch64_tr_init_disas_context(DisasContextBase *dcbase,
                                         CPUState *cpu, int max_insns)
static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
                                          CPUState *cpu)
{
    DisasContext *dc = container_of(dcbase, DisasContext, base);
    CPUARMState *env = cpu->env_ptr;
@@ -13288,11 +13288,9 @@ static int aarch64_tr_init_disas_context(DisasContextBase *dcbase,
    if (dc->ss_active) {
        bound = 1;
    }
    max_insns = MIN(max_insns, bound);
    dc->base.max_insns = MIN(dc->base.max_insns, bound);

    init_tmp_a64_array(dc);

    return max_insns;
}

static void aarch64_tr_tb_start(DisasContextBase *db, CPUState *cpu)
+8 −12
Original line number Diff line number Diff line
@@ -9930,7 +9930,7 @@ static bool thumb_insn_is_16bit(DisasContext *s, uint32_t insn)
        return false;
    }

    if ((insn >> 11) == 0x1e && (s->pc < s->next_page_start - 3)) {
    if ((insn >> 11) == 0x1e && s->pc - s->page_start < TARGET_PAGE_SIZE - 3) {
        /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
         * is not on the next page; we merge this into a 32-bit
         * insn.
@@ -12243,8 +12243,7 @@ static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
    return !thumb_insn_is_16bit(s, insn);
}

static int arm_tr_init_disas_context(DisasContextBase *dcbase,
                                     CPUState *cs, int max_insns)
static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
{
    DisasContext *dc = container_of(dcbase, DisasContext, base);
    CPUARMState *env = cs->env_ptr;
@@ -12301,19 +12300,18 @@ static int arm_tr_init_disas_context(DisasContextBase *dcbase,
    dc->is_ldex = false;
    dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */

    dc->next_page_start =
        (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
    dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;

    /* If architectural single step active, limit to 1.  */
    if (is_singlestepping(dc)) {
        max_insns = 1;
        dc->base.max_insns = 1;
    }

    /* ARM is a fixed-length ISA.  Bound the number of insns to execute
       to those left on the page.  */
    if (!dc->thumb) {
        int bound = (dc->next_page_start - dc->base.pc_first) / 4;
        max_insns = MIN(max_insns, bound);
        int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
        dc->base.max_insns = MIN(dc->base.max_insns, bound);
    }

    cpu_F0s = tcg_temp_new_i32();
@@ -12324,8 +12322,6 @@ static int arm_tr_init_disas_context(DisasContextBase *dcbase,
    cpu_V1 = cpu_F1d;
    /* FIXME: cpu_M0 can probably be the same as cpu_V0.  */
    cpu_M0 = tcg_temp_new_i64();

    return max_insns;
}

static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
@@ -12584,8 +12580,8 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
     * but isn't very efficient).
     */
    if (dc->base.is_jmp == DISAS_NEXT
        && (dc->pc >= dc->next_page_start
            || (dc->pc >= dc->next_page_start - 3
        && (dc->pc - dc->page_start >= TARGET_PAGE_SIZE
            || (dc->pc - dc->page_start >= TARGET_PAGE_SIZE - 3
                && insn_crosses_page(env, dc)))) {
        dc->base.is_jmp = DISAS_TOO_MANY;
    }
Loading