mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-22 22:53:04 +00:00
m1n1.trace.agx: Trace AGX wip
Signed-off-by: Scott Mansell <phiren@gmail.com>
This commit is contained in:
parent
90eae66b33
commit
980b9241d2
2 changed files with 230 additions and 1 deletions
|
@ -1,5 +1,7 @@
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
from m1n1.utils import *
|
||||||
|
|
||||||
trace_device("/arm-io/sgx", False)
|
trace_device("/arm-io/sgx", False)
|
||||||
trace_device("/arm-io/pmp", False)
|
trace_device("/arm-io/pmp", False)
|
||||||
trace_device("/arm-io/gfx-asc", False)
|
trace_device("/arm-io/gfx-asc", False)
|
||||||
|
@ -7,5 +9,80 @@ trace_device("/arm-io/gfx-asc", False)
|
||||||
from m1n1.trace.asc import ASCTracer
|
from m1n1.trace.asc import ASCTracer
|
||||||
|
|
||||||
ASCTracer = ASCTracer._reloadcls()
|
ASCTracer = ASCTracer._reloadcls()
|
||||||
gfx_tracer = ASCTracer(hv, "/arm-io/gfx-asc", verbose=True)
|
|
||||||
|
# gfx_tracer = ASCTracer(hv, "/arm-io/gfx-asc", verbose=True)
|
||||||
|
# gfx_tracer.start()
|
||||||
|
|
||||||
|
from m1n1.trace.agx import AGXTracer
|
||||||
|
AGXTracer = AGXTracer._reloadcls()
|
||||||
|
|
||||||
|
gfx_tracer = AGXTracer(hv, "/arm-io/gfx-asc", verbose=False)
|
||||||
gfx_tracer.start()
|
gfx_tracer.start()
|
||||||
|
|
||||||
|
trace_range(irange(gfx_tracer.gpu_region, gfx_tracer.gpu_region_size), mode=TraceMode.SYNC)
|
||||||
|
trace_range(irange(gfx_tracer.gfx_shared_region, gfx_tracer.gfx_shared_region_size), mode=TraceMode.SYNC)
|
||||||
|
trace_range(irange(gfx_tracer.gfx_handoff, gfx_tracer.gfx_handoff_size), mode=TraceMode.SYNC)
|
||||||
|
|
||||||
|
|
||||||
|
# Trace the entire mmio range around the GPU
|
||||||
|
# node = hv.adt["/arm-io/sgx"]
|
||||||
|
# addr, size = node.get_reg(0)
|
||||||
|
# hv.trace_range(irange(addr, 0x1000000), TraceMode.SYNC)
|
||||||
|
|
||||||
|
def trace_all_gfx_io():
|
||||||
|
# These are all the IO ranges that get mapped into the UAT iommu pagetable
|
||||||
|
# Trace them so we can see if any of them are being written by the CPU
|
||||||
|
|
||||||
|
# page (8): fa010020000 ... fa010023fff -> 000000020e100000 [8000020e100447]
|
||||||
|
hv.trace_range(irange(0x20e100000, 0x4000), mode=TraceMode.SYNC)
|
||||||
|
|
||||||
|
# page (10): fa010028000 ... fa01002bfff -> 000000028e104000 [c000028e104447]
|
||||||
|
hv.trace_range(irange(0x20e100000, 0x4000), mode=TraceMode.SYNC)
|
||||||
|
|
||||||
|
# page (22): fa010058000 ... fa01005bfff -> 000000028e494000 [8000028e494447]
|
||||||
|
hv.trace_range(irange(0x28e494000, 0x4000), mode=TraceMode.SYNC)
|
||||||
|
|
||||||
|
# page (28): fa010070000 ... fa010073fff -> 0000000204d60000 [c0000204d60447]
|
||||||
|
hv.trace_range(irange(0x204d60000, 0x4000), mode=TraceMode.SYNC)
|
||||||
|
|
||||||
|
# page (30): fa010078000 ... fa01007bfff -> 0000000200000000 [c0000200000447]
|
||||||
|
# to
|
||||||
|
# page (83): fa01014c000 ... fa01014ffff -> 00000002000d4000 [c00002000d4447]
|
||||||
|
hv.trace_range(irange(0x200000000, 0xd5000), mode=TraceMode.SYNC)
|
||||||
|
|
||||||
|
# page (84): fa010150000 ... fa010153fff -> 0000000201000000 [c0000201000447]
|
||||||
|
#page (137): fa010224000 ... fa010227fff -> 00000002010d4000 [c00002010d4447]
|
||||||
|
hv.trace_range(irange(0x201000000, 0xd5000), mode=TraceMode.SYNC)
|
||||||
|
|
||||||
|
# page (138): fa010228000 ... fa01022bfff -> 0000000202000000 [c0000202000447]
|
||||||
|
# page (191): fa0102fc000 ... fa0102fffff -> 00000002020d4000 [c00002020d4447]
|
||||||
|
hv.trace_range(irange(0x202000000, 0xd5000), mode=TraceMode.SYNC)
|
||||||
|
|
||||||
|
# page (192): fa010300000 ... fa010303fff -> 0000000203000000 [c0000203000447]
|
||||||
|
hv.trace_range(irange(0x203000000, 0xd5000), mode=TraceMode.SYNC)
|
||||||
|
hv.trace_range(irange(0x204000000, 0xd5000), mode=TraceMode.SYNC)
|
||||||
|
hv.trace_range(irange(0x205000000, 0xd5000), mode=TraceMode.SYNC)
|
||||||
|
hv.trace_range(irange(0x206000000, 0xd5000), mode=TraceMode.SYNC)
|
||||||
|
hv.trace_range(irange(0x207000000, 0xd5000), mode=TraceMode.SYNC)
|
||||||
|
|
||||||
|
# page (464): fa010740000 ... fa010743fff -> 00000002643c4000 [c00002643c4447]
|
||||||
|
hv.trace_range(irange(0x2643c4000, 0x4000), mode=TraceMode.SYNC)
|
||||||
|
# page (466): fa010748000 ... fa01074bfff -> 000000028e3d0000 [c000028e3d0447]
|
||||||
|
hv.trace_range(irange(0x28e3d0000, 0x4000), mode=TraceMode.SYNC)
|
||||||
|
# page (468): fa010750000 ... fa010753fff -> 000000028e3c0000 [8000028e3c0447]
|
||||||
|
hv.trace_range(irange(0x28e3c0000, 0x4000), mode=TraceMode.SYNC)
|
||||||
|
|
||||||
|
# page (8): f9100020000 ... f9100023fff -> 0000000406000000 [60000406000447]
|
||||||
|
# page (263): f910041c000 ... f910041ffff -> 00000004063fc000 [600004063fc447]
|
||||||
|
hv.trace_range(irange(0x2643c4000, 0x63fc000), mode=TraceMode.SYNC)
|
||||||
|
|
||||||
|
def trace_gpu_irqs():
|
||||||
|
# Trace sgx interrupts
|
||||||
|
node = hv.adt["/arm-io/sgx"]
|
||||||
|
for irq in getattr(node, "interrupts"):
|
||||||
|
hv.trace_irq(f"{node.name} {irq}", irq, 1, hv.IRQTRACE_IRQ)
|
||||||
|
|
||||||
|
# Trace gfx-asc interrupts
|
||||||
|
node = hv.adt["/arm-io/gfx-asc"]
|
||||||
|
for irq in getattr(node, "interrupts"):
|
||||||
|
hv.trace_irq(f"{node.name} {irq}", irq, 1, hv.IRQTRACE_IRQ)
|
||||||
|
|
152
proxyclient/m1n1/trace/agx.py
Normal file
152
proxyclient/m1n1/trace/agx.py
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
|
||||||
|
from mmap import PAGESIZE
|
||||||
|
from . import ADTDevTracer
|
||||||
|
from .asc import *
|
||||||
|
from ..hw.uat import UAT
|
||||||
|
|
||||||
|
from m1n1.proxyutils import RegMonitor
|
||||||
|
|
||||||
|
from construct import *
|
||||||
|
from construct.core import Int16ul, Int32ul, Int64ul, Int8ul
|
||||||
|
|
||||||
|
|
||||||
|
ControlStruct = Struct(
|
||||||
|
"unkptr_0" / Int64ul, # allocation size: 0x4000
|
||||||
|
"unk_8" / Int32ul,
|
||||||
|
"unk_c"/ Int32ul,
|
||||||
|
"unkptr_10" / Int64ul, # allocation size: 0x34000
|
||||||
|
"unkptr_18" / Int64ul, # allocation size: 0x88000, heap?
|
||||||
|
"unkptr_20" / Int64ul, # allocation size: 0x4000, but probally only 0x80 bytes long
|
||||||
|
"unk_28" / Int32ul,
|
||||||
|
"unk_2c" / Int32ul,
|
||||||
|
"unk_30" / Int32ul,
|
||||||
|
)
|
||||||
|
|
||||||
|
class InitMsg(Register64):
|
||||||
|
TYPE = 59, 52
|
||||||
|
|
||||||
|
class InitReq(InitMsg):
|
||||||
|
TYPE = 59, 52, Constant(0x1)
|
||||||
|
UNK = 47, 0
|
||||||
|
|
||||||
|
class InitResp(InitMsg):
|
||||||
|
# example: 0x0010_4fa0_0c388000
|
||||||
|
TYPE = 59, 52, Constant(0x1)
|
||||||
|
UNK1 = 47, 44
|
||||||
|
ADDR = 43, 0 # GPU VA that gets filled with a repating 0xefefefef pattern
|
||||||
|
|
||||||
|
class InitEp(EP):
|
||||||
|
# This endpoint receives and sends one message during boot.
|
||||||
|
# Potentially a "Ready" and a "Init" message.
|
||||||
|
BASE_MESSAGE = InitMsg
|
||||||
|
|
||||||
|
@msg(0x1, DIR.RX, InitReq)
|
||||||
|
def init_req(self, msg):
|
||||||
|
print(f" Received Init Request, {msg.UNK:x}")
|
||||||
|
|
||||||
|
@msg(0x1, DIR.TX, InitResp)
|
||||||
|
def init_resp(self, msg):
|
||||||
|
print(f" CPU Sent Init Response {msg.UNK1:x}, ADDR: {msg.ADDR:x}")
|
||||||
|
|
||||||
|
# monitor whatever is at this address
|
||||||
|
self.tracer.mon_addva(msg.ADDR, 0x4000, "init_region")
|
||||||
|
self.tracer.mon.poll()
|
||||||
|
return True
|
||||||
|
|
||||||
|
class GpuMsg(Register64):
|
||||||
|
TYPE = 55, 48
|
||||||
|
|
||||||
|
class PongMsg(GpuMsg):
|
||||||
|
TYPE = 59, 52
|
||||||
|
UNK = 47, 0
|
||||||
|
|
||||||
|
class PongEp(EP):
|
||||||
|
# This endpoint recives pongs. The cpu code reads some status registers after receiving one
|
||||||
|
# Might be a "work done" message.
|
||||||
|
BASE_MESSAGE = GpuMsg
|
||||||
|
|
||||||
|
@msg(0x42, DIR.RX, PongMsg)
|
||||||
|
def pong_rx(self, msg):
|
||||||
|
print(f" Pong {msg.UNK:x}")
|
||||||
|
if msg.UNK != 0:
|
||||||
|
print(f" Pong had unexpected value{msg.UNK:x}")
|
||||||
|
self.hv.run_shell()
|
||||||
|
|
||||||
|
self.tracer.pong()
|
||||||
|
return True
|
||||||
|
|
||||||
|
@msg(0x81, DIR.TX, PongMsg)
|
||||||
|
def init_ep(self, msg):
|
||||||
|
print(f" Init {msg.UNK:x}")
|
||||||
|
|
||||||
|
addr = msg.UNK
|
||||||
|
|
||||||
|
#self.tracer.mon_addva(addr, 0x4000, "control_struct")
|
||||||
|
control = ControlStruct.parse(self.tracer.uat.ioread(0, addr, 0x34))
|
||||||
|
#self.tracer.mon_addva(control.unkptr_0, 0x4000, "control_struct->unkptr_0")
|
||||||
|
# self.tracer.mon_addva(control.unkptr_10, 0x34000, "control_struct->unkptr_10")
|
||||||
|
# self.tracer.mon_addva(control.unkptr_18, 0x88000, "control_struct->unkptr_18")
|
||||||
|
#self.tracer.mon_addva(control.unkptr_20, 0x4000, "control_struct->unkptr_20")
|
||||||
|
self.tracer.control = control
|
||||||
|
|
||||||
|
self.tracer.mon.poll()
|
||||||
|
|
||||||
|
self.tracer.kick_init()
|
||||||
|
return True
|
||||||
|
|
||||||
|
class KickMsg(GpuMsg):
|
||||||
|
TYPE = 59, 52
|
||||||
|
KICK = 7, 0 # Seen: 17, 16 (common), 9, 8, 1 (common), 0 (common)
|
||||||
|
|
||||||
|
class KickEp(EP):
|
||||||
|
BASE_MESSAGE = GpuMsg
|
||||||
|
|
||||||
|
@msg(0x83, DIR.TX, KickMsg)
|
||||||
|
def kick(self, msg):
|
||||||
|
print(f" Kick {msg.KICK:x}")
|
||||||
|
self.tracer.kick(msg.KICK)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
class AGXTracer(ASCTracer):
|
||||||
|
ENDPOINTS = {
|
||||||
|
0x01: InitEp,
|
||||||
|
0x20: PongEp,
|
||||||
|
0x21: KickEp
|
||||||
|
}
|
||||||
|
|
||||||
|
PAGESIZE = 0x4000
|
||||||
|
|
||||||
|
def __init__(self, hv, devpath, verbose=False):
|
||||||
|
super().__init__(hv, devpath, verbose)
|
||||||
|
self.uat = UAT(hv.iface, hv.u)
|
||||||
|
self.mon = RegMonitor(hv.u, ascii=True)
|
||||||
|
self.dev_sgx = hv.u.adt["/arm-io/sgx"]
|
||||||
|
self.gpu_region = getattr(self.dev_sgx, "gpu-region-base")
|
||||||
|
self.gpu_region_size = getattr(self.dev_sgx, "gpu-region-size")
|
||||||
|
self.gfx_shared_region = getattr(self.dev_sgx, "gfx-shared-region-base")
|
||||||
|
self.gfx_shared_region_size = getattr(self.dev_sgx, "gfx-shared-region-size")
|
||||||
|
self.gfx_handoff = getattr(self.dev_sgx, "gfx-handoff-base")
|
||||||
|
self.gfx_handoff_size = getattr(self.dev_sgx, "gfx-handoff-size")
|
||||||
|
|
||||||
|
# self.mon.add(self.gpu_region, self.gpu_region_size, "contexts")
|
||||||
|
# self.mon.add(self.gfx_shared_region, self.gfx_shared_region_size, "gfx-shared")
|
||||||
|
# self.mon.add(self.gfx_handoff, self.gfx_handoff_size, "gfx-handoff")
|
||||||
|
|
||||||
|
self.uat.set_ttbr(self.gpu_region)
|
||||||
|
|
||||||
|
def mon_addva(self, va, size, name=""):
|
||||||
|
self.mon.add(va, size, name, readfn= lambda a, s: self.uat.ioread(0, a, s))
|
||||||
|
|
||||||
|
def kick(self, val):
|
||||||
|
self.mon.poll()
|
||||||
|
|
||||||
|
# if val not in [0x0, 0x1, 0x10, 0x11]:
|
||||||
|
# self.hv.run_shell()
|
||||||
|
|
||||||
|
def pong(self):
|
||||||
|
self.mon.poll()
|
||||||
|
|
||||||
|
def kick_init(self):
|
||||||
|
self.hv.run_shell()
|
||||||
|
|
Loading…
Reference in a new issue