1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
from . import Tracer, TraceMode
from ..utils import *
class R_BAR(Register32):
BASE = 31, 4
PREFETCH = 3
ADDR64 = 2
BELOW_1M = 1
SPACE = 0
class PCICfgSpace(RegMap):
VENDOR_ID = 0x00, Register16
PRODUCT_ID = 0x02, Register16
COMMAND = 0x04, Register16
STATUS = 0x06, Register16
BAR = irange(0x10, 6, 4), R_BAR
ROMADDR = 0x30, Register32
class PCIeDevTracer(Tracer):
CFGMAP = PCICfgSpace
BARMAPS = []
NAMES = []
PREFIXES = []
def __init__(self, hv, apcie, bus, dev, fn, verbose=False):
super().__init__(hv, verbose=verbose, ident=f"{type(self).__name__}@{apcie}/{bus:02x}:{dev:02x}.{fn:1x}")
self.busn = bus
self.devn = dev
self.fn = fn
self.ecam_off = (bus << 20) | (dev << 15) | (fn << 12)
self.apcie = hv.adt[apcie]
self.bars = [0] * 6
self.bar_ranges = [None] * 6
self.cfg_space = self.CFGMAP(hv.u, self.apcie.get_reg(0)[0] + self.ecam_off)
self.verbose = 3
def init_state(self):
self.state.bars = [R_BAR(0) for i in range(6)]
self.state.barsize = [None] * 6
@classmethod
def _reloadcls(cls, force=False):
cls.BARMAPS = [i._reloadcls(force) if i else None for i in cls.BARMAPS]
return super()._reloadcls(force)
def r_cfg_BAR(self, val, index):
if self.state.bars[index].BASE == 0xfffffff:
size = (0x10000000 - val.BASE) << 4
self.log(f"BAR{index} size = {size:#x}")
self.state.barsize[index] = size
def w_cfg_BAR(self, val, index):
self.state.bars[index] = val
self.update_tracers(val, index)
def update_tracers(self, val = None, index = None):
self.hv.clear_tracers(self.ident)
ecam = self.apcie.get_reg(0)[0]
self.trace_regmap(ecam + self.ecam_off, 0x1000, self.CFGMAP, prefix="cfg",
mode=TraceMode.WSYNC)
i = 0
while i < 6:
idx = i
if i == index:
bar = val
else:
bar = self.cfg_space.BAR[i].reg
addr = bar.BASE << 4
if bar.ADDR64 and i != 5:
if i + 1 == index:
barh = val
else:
barh = self.cfg_space.BAR[i + 1].reg
addr |= barh.value << 32
i += 2
else:
i += 1
if addr in (0, 0xfffffff0, 0xffffffff00000000, 0xfffffffffffffff0):
continue
size = self.state.barsize[idx]
if not size:
self.log(f"BAR{idx} size is unknown!")
continue
# Add in PCIe DT addr flags to get the correct translation
start = self.apcie.translate(addr | (0x02 << 88))
self.log(f"Tracing BAR{idx} : {addr:#x} -> {start:#x}..{start+size-1:#x}")
self.bar_ranges[idx] = irange(start, size)
self.trace_bar(idx, start, size)
def trace_bar(self, idx, start, size):
if idx >= len(self.BARMAPS) or (regmap := self.BARMAPS[idx]) is None:
return
prefix = name = None
if idx < len(self.NAMES):
name = self.NAMES[i]
if idx < len(self.PREFIXES):
prefix = self.PREFIXES[i]
self.trace_regmap(start, size, regmap, name=name, prefix=prefix)
def start(self):
self.update_tracers()
|