diff options
Diffstat (limited to 'tools/proxyclient/m1n1/find_regs.py')
| -rw-r--r-- | tools/proxyclient/m1n1/find_regs.py | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/tools/proxyclient/m1n1/find_regs.py b/tools/proxyclient/m1n1/find_regs.py new file mode 100644 index 0000000..9982661 --- /dev/null +++ b/tools/proxyclient/m1n1/find_regs.py @@ -0,0 +1,99 @@ +# SPDX-License-Identifier: MIT +import struct + +from . import asm, sysreg +from .proxyutils import GuardedHeap + +__all__ = ["dynamic_regs", "impdef_regs", "static_regs", "find_regs"] + +def _all(): + for op1 in range(1 << 3): + for CRn in (0b1011, 0b1111): + for CRm in range(1 << 4): + for op2 in range(1 << 3): + yield 3, op1, CRn, CRm, op2 + +dynamic_regs = [ + sysreg.CNTVCT_ALIAS_EL0, + sysreg.CNTPCT_ALIAS_EL0, +] + +impdef_regs = list(_all()) +static_regs = [i for i in _all() if i not in dynamic_regs] + +def find_regs(u, regs=None, block=1024, call=None, values=True): + if regs is None: + regs = impdef_regs + + p = u.proxy + iface = u.iface + + data_len = 8 * block + + with GuardedHeap(u.heap) as heap: + data_buffer = heap.malloc(data_len) + + template = asm.ARMAsm(""" + mov x2, x0 + mrs x2, s3_0_c0_c0_0 + str x2, [x1], #8 + """, 0x1000) + + mov, mrs, st = struct.unpack("3I", template.data) + + + BAD = 0xacce5515abad1dea + OOPS = 0xdeadc0dedeadc0de + + iregs = iter(regs) + + while True: + insns = [] + bregs = [] + for i in iregs: + op0, op1, CRn, CRm, op2 = enc = sysreg.sysreg_parse(i) + bregs.append(enc) + assert op0 == 3 + + insns.extend((mov, mrs | (op1 << 16) | (CRn << 12) | (CRm << 8) | (op2 << 5), st)) + + if len(bregs) >= block: + break + + if not bregs: + break + + p.memset64(data_buffer, OOPS, data_len) + u.exec(insns, BAD, data_buffer, call=call, silent=True, ignore_exceptions=True) + data = iface.readmem(data_buffer, 8 * len(bregs)) + for reg, val in zip(bregs, struct.unpack(f"<{len(bregs)}Q", data)): + if val == OOPS: + raise Exception(f"Failed to execute reg-finder code at {reg}") + if val != BAD: + if values: + yield reg, val + else: + yield reg + +if __name__ == "__main__": + from m1n1.setup import * + + p.iodev_set_usage(IODEV.FB, 0) + + for reg, val in find_regs(u): + print(f"{sysreg_name(reg)} ({', '.join(map(str, reg))}) = 0x{val:x}") + + try: + u.msr(reg, val, silent=True) + except: + print(" - READONLY") + try: + u.mrs(reg, silent=True, call="el1") + except: + print(" - ### EL2 only ###") + try: + u.mrs(reg, silent=True, call="el0") + except: + pass + else: + print(" - *** EL0 accessible ***") |
