diff --git a/proxyclient/hv/trace_bt.py b/proxyclient/hv/trace_bt.py new file mode 100644 index 000000000..d2c501661 --- /dev/null +++ b/proxyclient/hv/trace_bt.py @@ -0,0 +1,446 @@ +from m1n1.trace import Tracer +from m1n1.trace.dart import DARTTracer +from m1n1.utils import * +from collections import namedtuple +import itertools +import struct + + +ContextStruct = namedtuple('ContextStruct', [ + 'version', + 'sz', + 'enabled_caps', + 'perInfo', + 'crHIA', + 'trTIA', + 'crTIA', + 'trHIA', + 'crIAEntry', + 'trIAEntry', + 'mcr', + 'mtr', + 'mtrEntry', + 'mcrEntry', + 'mtrDb', + 'mcrDb', + 'mtrMsi', + 'mcrMsi', + 'mtrOptHeadSize', + 'mtrOptFootSize', + 'mcrOptHeadSize', + 'mcrOptFootSize', + 'res_inPlaceComp_oOOComp', + 'piMsi', + 'scratchPa', + 'scratchSize', + 'res', +]) +CONTEXTSTRUCT_STR = "= len(self.REGMAPS) or (regmap := self.REGMAPS[i]) is None: + continue + prefix = name = None + if i < len(self.NAMES): + name = self.NAMES[i] + if i < len(self.PREFIXES): + prefix = self.PREFIXES[i] + + start, size = self.REGRANGES[i] + self.trace_regmap(start, size, regmap, name=name, prefix=prefix) + + +# FIXME how do we get stream IDs without hardcoding? +STREAM = 2 + + +class BTTracer(MemRangeTracer): + DEFAULT_MODE = TraceMode.SYNC + REGMAPS = [BTBAR0Regs, BTBAR1Regs] + # FIXME this is kinda a hack + REGRANGES = [(0x5c2410000, 0x8000), (0x5c2000000, 0x400000)] + NAMES = ['BAR0', 'BAR1'] + + def __init__(self, hv, dart_tracer): + super().__init__(hv, verbose=3) + self.dart_tracer = dart_tracer + self._dart_tracer_started = False + self._dumped_host_window = False + self._dump_idx = 0 + self._host_window_lo = 0 + self._host_window_hi = 0 + self._host_window_sz = 0 + self._rti_window_lo = 0 + self._rti_window_hi = 0 + self._rti_window_sz = 0 + self._rti_context_lo = 0 + self._rti_context_hi = 0 + + def w_DOORBELL_6(self, val): + # this is the first access macos does + if not self._dart_tracer_started: + self.dart_tracer.start() + self._dart_tracer_started = True + print("starting DART tracer") + + def w_HOST_WINDOW_LO(self, val): + self._host_window_lo = val + + def w_HOST_WINDOW_HI(self, val): + self._host_window_hi = val + + def w_HOST_WINDOW_SZ(self, val): + self._host_window_sz = val + + def w_IMG_DOORBELL(self, val): + print("Image doorbell was rung") + host_window_iova = int(self._host_window_hi) << 32 | int(self._host_window_lo) + host_window_sz = int(self._host_window_sz) + print(f"Host window @ {host_window_iova:016X} sz {host_window_sz:08X}") + + self.dart_tracer.dart.dump_all() + + try: + data = self.dart_tracer.dart.ioread(STREAM, host_window_iova, host_window_sz) + with open(f'bt_dump_{self._dump_idx}.bin', 'wb') as f: + f.write(data) + chexdump(data[:0x400]) + self._dump_idx += 1 + except Exception as e: + print(e) + + + def w_RTI_WINDOW_LO(self, val): + self._rti_window_lo = val + + def w_RTI_WINDOW_HI(self, val): + self._rti_window_hi = val + + def w_RTI_WINDOW_SZ(self, val): + self._rti_window_sz = val + + def w_RTI_CONTEXT_LO(self, val): + self._rti_context_lo = val + + def w_RTI_CONTEXT_HI(self, val): + self._rti_context_hi = val + + def w_RTI_CONTROL(self, val): + print("RTI control was set") + host_window_iova = int(self._host_window_hi) << 32 | int(self._host_window_lo) + host_window_sz = int(self._host_window_sz) + print(f"Host window @ {host_window_iova:016X} sz {host_window_sz:08X}") + rti_window_iova = int(self._rti_window_hi) << 32 | int(self._rti_window_lo) + rti_window_sz = int(self._rti_window_sz) + print(f"RTI window @ {rti_window_iova:016X} sz {rti_window_sz:08X}") + rti_context_iova = int(self._rti_context_hi) << 32 | int(self._rti_context_lo) + print(f"RTI context @ {rti_context_iova:016X}") + + self.dart_tracer.dart.dump_all() + + try: + data = self.dart_tracer.dart.ioread(STREAM, host_window_iova, host_window_sz) + with open(f'bt_dump_{self._dump_idx}.bin', 'wb') as f: + f.write(data) + chexdump(data[:0x400]) + self._dump_idx += 1 + except Exception as e: + print(e) + + try: + data = self.dart_tracer.dart.ioread(STREAM, rti_context_iova, 0x68) + with open(f'bt_dump_{self._dump_idx}.bin', 'wb') as f: + f.write(data) + chexdump(data) + self._dump_idx += 1 + + print("Got context data now") + context = ContextStruct._make(struct.unpack(CONTEXTSTRUCT_STR, data)) + print(context) + + def hook(name, iova, sz): + physaddr = self.dart_tracer.dart.iotranslate(STREAM, iova, sz)[0][0] + print(f"hooking {name} @ IOVA {iova:016X} phys {physaddr:016X}") + self.trace(physaddr, sz, TraceMode.SYNC, prefix=name) + + # hook('perInfo', context.perInfo, 0x10) + # hook('crHIA', context.crHIA, 12) + # hook('crTIA', context.crTIA, 12) + # hook('trHIA', context.trHIA, 18) + # hook('trTIA', context.trTIA, 18) + # hook('mcr', context.mcr, 0x800) # no idea size + # hook('mtr', context.mtr, 0x800) # i _think_ this is correct + + crhia_physaddr = self.dart_tracer.dart.iotranslate(STREAM, context.crHIA, 1)[0][0] + self.hv.add_tracer( + irange(crhia_physaddr, 4), + self.ident, + TraceMode.SYNC, + self.completion_hax_event, + None + ) + + self._crhia_physaddr = crhia_physaddr + self._ctx = context + self._open_pipes = {} + self._open_crs = {} + + except Exception as e: + print(e) + + def w_DOORBELL_05(self, val): + val = int(val) + if val & 0x20 != 0x20: + print(f"UNKNOWN write to doorbell {val:X}") + else: + db_idx = (val >> 8) & 0xFF + ring_idx = (val >> 16) & 0xFFFF + print(f"doorbell #{db_idx} rung @ {ring_idx}") + + try: + tr_heads = struct.unpack("= tr_tails[pipe_idx]: + range_ = range(tr_tails[pipe_idx], tr_heads[pipe_idx]) + else: + range_ = itertools.chain(range(tr_tails[pipe_idx], tr_ring_sz), range(0, tr_heads[pipe_idx])) + + for i in range_: + tr_data_addr = tr_iova_base + tr_ent_sz * i + print(f"TR{pipe_idx} idx {i} @ iova {tr_data_addr:016X}") + tr_data = self.dart_tracer.dart.ioread(STREAM, tr_data_addr, tr_ent_sz) + chexdump(tr_data) + + if tr_data[0] & 3 == 1: + buf_addr = struct.unpack("= cr_tails[cr_idx]: + range_ = range(cr_tails[cr_idx], cr_heads[cr_idx]) + else: + range_ = itertools.chain(range(cr_tails[cr_idx], cr_ring_sz), range(0, cr_heads[cr_idx])) + + for i in range_: + cr_data_addr = cr_iova_base + cr_ent_sz * i + print(f"CR{cr_idx} idx {i} @ iova {cr_data_addr:016X}") + cr_data = self.dart_tracer.dart.ioread(STREAM, cr_data_addr, cr_ent_sz) + chexdump(cr_data) + except Exception as e: + print(e) + + +BTTracer = BTTracer._reloadcls() + +dart_tracer = DARTTracer(hv, "/arm-io/dart-apcie0", verbose=1) +dart_tracer.DEFAULT_MODE = TraceMode.SYNC +# do not start, clock gates aren't enabled yet +print(dart_tracer) + +bt_tracer = BTTracer(hv, dart_tracer) +bt_tracer.start() +print(bt_tracer) diff --git a/proxyclient/m1n1/proxy.py b/proxyclient/m1n1/proxy.py index 39b8e3449..5f080b103 100644 --- a/proxyclient/m1n1/proxy.py +++ b/proxyclient/m1n1/proxy.py @@ -712,7 +712,8 @@ def reboot(self): def write64(self, addr, data): '''write 8 byte value to given address''' if addr & 7: - raise AlignmentError() + self.write32(addr, data & 0xFFFFFFFF) + self.write32(addr + 4, data >> 32) self.request(self.P_WRITE64, addr, data) def write32(self, addr, data): '''write 4 byte value to given address'''