-
Notifications
You must be signed in to change notification settings - Fork 48
Expand file tree
/
Copy pathcpu.py
More file actions
163 lines (124 loc) · 4.09 KB
/
cpu.py
File metadata and controls
163 lines (124 loc) · 4.09 KB
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import gdb
from .struct import GdbStructMeta
from .utils import TextTable, cast, cast_ptr, get_arch
from .cmd import UserCommand, CommandDispatcher
class TLBHi():
def __init__(self, val):
self.val = cast(val, 'unsigned long')
@property
def vpn0(self):
return self.val & 0xffffe000
@property
def vpn1(self):
return self.vpn0 + 0x1000
@property
def asid(self):
return self.val & 0x000000ff
class TLBLo():
def __init__(self, val):
self.val = cast(val, 'unsigned long')
@property
def globl(self):
return bool(self.val & 1)
@property
def valid(self):
return bool(self.val & 2)
@property
def dirty(self):
return bool(self.val & 4)
@property
def ppn(self):
return (self.val & 0x03ffffc0) << 6
@property
def xi(self):
return bool(self.val & 0x40000000)
@property
def ri(self):
return bool(self.val & 0x80000000)
def __str__(self):
return '%08x %c %s %s' % (self.ppn, '-D'[self.dirty],
['--', 'RI'][self.ri], ['--', 'XI'][self.xi])
class TLBEntry(metaclass=GdbStructMeta):
__ctype__ = 'tlbentry_t'
__cast__ = {'hi': TLBHi, 'lo0': TLBLo, 'lo1': TLBLo}
def dump(self):
if not self.lo0.valid and not self.lo1.valid:
return None
globl, lo0, lo1 = '-', '-', '-'
if self.lo0.valid:
lo0 = '%08x %s' % (self.hi.vpn0, self.lo0)
if self.lo1.valid:
lo1 = '%08x %s' % (self.hi.vpn1, self.lo1)
asid = '%02x' % self.hi.asid
if self.lo0.globl and self.lo1.globl:
asid = '-'
globl = 'G'
return [asid, globl, lo0, lo1]
class TLB(UserCommand):
"""List Translation Lookaside Buffer entries"""
def __init__(self):
super().__init__('tlb')
def __call__(self, args):
table = TextTable(align='rrrll')
table.header(["Index", "ASID", "Global", "PFN0", "PFN1"])
for idx in range(TLB.size()):
row = TLB.read(idx).dump()
if row is None:
continue
table.add_row([str(idx)] + row)
print('Current ASID = %d' % self.asid())
print(table)
@staticmethod
def read(idx):
gdb.parse_and_eval('_gdb_tlb_read_index(%d)' % idx)
return TLBEntry(gdb.parse_and_eval('_gdb_tlb_entry'))
@staticmethod
def size():
return int(gdb.parse_and_eval('_gdb_tlb_size()'))
@staticmethod
def asid():
return int(gdb.parse_and_eval('_gdb_asid'))
class Cpu(CommandDispatcher):
"""Examine processor priviliged resources."""
def __init__(self):
super().__init__('cpu', [TLB()])
class PageTableMips():
def __init__(self, pmap):
self._pmap = pmap
def print(self):
pdp = cast_ptr(self._pmap['pde'], 'pde_t')
table = TextTable(types='ttttt', align='rrrrr')
table.header(['vpn', 'pte0', 'pte1', 'pte2', 'pte3'])
for i in range(1024):
pde = TLBLo(pdp[i])
if not pde.valid:
continue
ptp = cast_ptr(pde.ppn, 'pte_t')
pte = [TLBLo(ptp[j]) for j in range(1024)]
for j in range(0, 1024, 4):
if not any(pte.valid for pte in pte[j:j+4]):
continue
pte4 = [str(pte) if pte.valid else '-' for pte in pte[j:j+4]]
table.add_row([f'{(i << 22) + (j << 12):8x}', pte4[0], pte4[1],
pte4[2], pte4[3]])
print(table)
class PageTableAArch64():
def __init__(self, pmap):
self._pmap = pmap
print("Page table not implemented for AArch64")
def print(self):
pass
class PageTableRiscv():
def __init__(self, pmap):
self._pmap = pmap
print("Page table not implemented for RISC-V")
def print(self):
pass
if get_arch() == 'mips':
PageTable = PageTableMips
elif get_arch() == 'aarch64':
PageTable = PageTableAArch64
elif get_arch() == 'riscv':
PageTable = PageTableRiscv
else:
print(f'Arch {get_arch()} not supported')