staticbool is_ll(uint32_t insn)
{ switch (insn >> 26) { case OP_LL: case OP_LLD: returntrue;
default: returnfalse;
}
}
staticbool is_sc(uint32_t insn)
{ switch (insn >> 26) { case OP_SC: case OP_SCD: returntrue;
default: returnfalse;
}
}
staticbool is_sync(uint32_t insn)
{ /* Bits 31:11 should all be zeroes */ if (insn >> 11) returnfalse;
/* Bits 5:0 specify the SYNC special encoding */ if ((insn & 0x3f) != SPECIAL_SYNC) returnfalse;
returntrue;
}
staticbool is_branch(uint32_t insn, int *off)
{ switch (insn >> 26) { case OP_BEQ: case OP_BEQL: case OP_BNE: case OP_BNEL: case OP_BGTZ: case OP_BGTZL: case OP_BLEZ: case OP_BLEZL:
*off = se16(insn) + 1; returntrue;
case OP_REGIMM: switch ((insn >> 16) & 0x1f) { case REGIMM_BGEZ: case REGIMM_BGEZL: case REGIMM_BGEZAL: case REGIMM_BGEZALL: case REGIMM_BLTZ: case REGIMM_BLTZL: case REGIMM_BLTZAL: case REGIMM_BLTZALL:
*off = se16(insn) + 1; returntrue;
default: returnfalse;
}
default: returnfalse;
}
}
staticint check_ll(uint64_t pc, uint32_t *code, size_t sz)
{
ssize_t i, max, sc_pos; int off;
/* * Every LL must be preceded by a sync instruction in order to ensure * that instruction reordering doesn't allow a prior memory access to * execute after the LL & cause erroneous results.
*/ if (!is_sync(le32toh(code[-1]))) {
fprintf(stderr, "%" PRIx64 ": LL not preceded by sync\n", pc); return -EINVAL;
}
/* Find the matching SC instruction */
max = sz / 4; for (sc_pos = 0; sc_pos < max; sc_pos++) { if (is_sc(le32toh(code[sc_pos]))) break;
} if (sc_pos >= max) {
fprintf(stderr, "%" PRIx64 ": LL has no matching SC\n", pc); return -EINVAL;
}
/* * Check branches within the LL/SC loop target sync instructions, * ensuring that speculative execution can't generate memory accesses * due to instructions outside of the loop.
*/ for (i = 0; i < sc_pos; i++) { if (!is_branch(le32toh(code[i]), &off)) continue;
/* * If the branch target is within the LL/SC loop then we don't * need to worry about it.
*/ if ((off >= -i) && (off <= sc_pos)) continue;
/* If the branch targets a sync instruction we're all good... */ if (is_sync(le32toh(code[i + off]))) continue;
/* ...but if not, we have a problem */
fprintf(stderr, "%" PRIx64 ": Branch target not a sync\n",
pc + (i * 4)); return -EINVAL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.