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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
|
XBURST = {}
function XBURST.read_cp0(reg, sel)
return DEV.read32_cop({0, reg, sel})
end
function XBURST.write_cp0(reg, sel, val)
DEV.write32_cop({0, reg, sel}, val)
end
XBURST.prid_table = {
[0x0ad0024f] = "JZ4740",
[0x1ed0024f] = "JZ4755",
[0x2ed0024f] = "JZ4760(B)",
[0x3ee1024f] = "JZ4780"
}
XBURST.at_table = {
[0] = "MIPS32",
[1] = "MIPS64 with 32-bit segments",
[2] = "MIPS64"
}
XBURST.ar_table = {
[0] = "Release 1",
[1] = "Release 2 (or more)"
}
XBURST.mt_table = {
[0] = "None",
[1] = "Standard TLB",
[2] = "BAT",
[3] = "Fixed Mapping",
[4] = "Dual VTLB and FTLB"
}
XBURST.is_table = {
[0] = 64,
[1] = 128,
[2] = 256,
[3] = 512,
[4] = 1024,
[5] = 2048,
[6] = 4096,
[7] = 32
}
XBURST.il_table = {
[0] = 0,
[1] = 4,
[2] = 8,
[3] = 16,
[4] = 32,
[5] = 64,
[6] = 128
}
function XBURST.get_table_or(tbl, index, dflt)
if tbl[index] ~= nil then
return tbl[index]
else
return dflt
end
end
function XBURST.do_ebase_test()
XBURST.write_cp0(15, 1, 0x80000000)
print(string.format(" Value after writing 0x80000000: 0x%x", XBURST.read_cp0(15, 1)))
if XBURST.read_cp0(15, 1) ~= 0x80000000 then
return "Value 0x8000000 does not stick, EBASE is probably not working"
end
XBURST.write_cp0(15, 1, 0x80040000)
print(string.format(" Value after writing 0x80040000: 0x%x", XBURST.read_cp0(15, 1)))
if XBURST.read_cp0(15, 1) ~= 0x80040000 then
return "Value 0x80040000 does not stick, EBASE is probably not working"
end
return "EBase seems to work"
end
function XBURST.do_ebase_cfg7gate_test()
-- test gate in config7
config7_old = XBURST.read_cp0(16, 7)
XBURST.write_cp0(16, 7, bit32.replace(config7_old, 0, 7)) -- disable EBASE[30] modification
print(string.format(" Disable config7 gate: write 0x%x to Config7", bit32.replace(config7_old, 0, 7)))
XBURST.write_cp0(15, 1, 0xfffff000)
print(string.format(" Value after writing 0xfffff000: 0x%x", XBURST.read_cp0(15, 1)))
if XBURST.read_cp0(15, 1) == 0xfffff000 then
return "Config7 gate has no effect but modifications are allowed anyway"
end
XBURST.write_cp0(16, 7, bit32.replace(config7_old, 1, 7)) -- enable EBASE[30] modification
print(string.format(" Enable config7 gate: write 0x%x to Config7", bit32.replace(config7_old, 1, 7)))
XBURST.write_cp0(15, 1, 0xc0000000)
print(string.format(" Value after writing 0xc0000000: 0x%x", XBURST.read_cp0(15, 1)))
if XBURST.read_cp0(15, 1) ~= 0xc0000000 then
return "Config7 gate does not work"
end
XBURST.write_cp0(16, 7, config7_old)
return "Config7 gate seems to work"
end
function XBURST.do_ebase_exc_test(mem_addr)
if (mem_addr % 0x1000) ~= 0 then
return " memory address for exception test must aligned on a 0x1000 boundary";
end
print(string.format("Exception test with EBASE at 0x%x...", mem_addr))
print(" Writing instructions to memory")
-- create instructions in memory
exc_addr = mem_addr + 0x180 -- general exception vector
data_addr = mem_addr + 0x300
-- lui k0,<low part of data_addr>
-- ori k0,k0,<high part>
DEV.write32(exc_addr + 0, 0x3c1a0000 + bit32.rshift(data_addr, 16))
DEV.write32(exc_addr + 4, 0x375a0000 + bit32.band(data_addr, 0xffff))
-- lui k1,0xdead
-- ori k1,k1,0xbeef
DEV.write32(exc_addr + 8, 0x3c1bdead)
DEV.write32(exc_addr + 12, 0x377bbeef)
-- sw k1,0(k0)
DEV.write32(exc_addr + 16, 0xaf5b0000)
-- mfc0 k0,c0_epc
-- addi k0,k0,4
-- mtc0 k0,c0_epc
DEV.write32(exc_addr + 20, 0x401a7000)
DEV.write32(exc_addr + 24, 0x235a0004)
DEV.write32(exc_addr + 28, 0x409a7000)
-- eret
-- nop
DEV.write32(exc_addr + 32, 0x42000018)
DEV.write32(exc_addr + 36, 0)
-- fill data with some initial value
DEV.write32(data_addr, 0xcafebabe)
-- write instructions to trigger an interrupt
bug_addr = mem_addr
-- syscall
DEV.write32(bug_addr + 0, 0x0000000c)
-- jr ra
-- nop
DEV.write32(bug_addr + 4, 0x03e00008)
DEV.write32(bug_addr + 8, 0)
-- make sure we are the right shape for the test: SR should have BEV cleared,
-- mask all interrupts, enable interrupts
old_sr = XBURST.read_cp0(12, 0)
print(string.format(" Old SR: 0x%x", old_sr))
XBURST.write_cp0(12, 0, 0xfc00) -- BEV set to 0, all interrupts masked and interrupt disabled
print(string.format(" New SR: 0x%x", XBURST.read_cp0(12, 0)))
-- change EBASE
old_ebase = XBURST.read_cp0(15, 1)
XBURST.write_cp0(15, 1, mem_addr)
print(string.format(" EBASE: %x", XBURST.read_cp0(15, 1)))
-- test
print(string.format(" Before: %x", DEV.read32(data_addr)))
DEV.call(bug_addr)
print(string.format(" After: %x", DEV.read32(data_addr)))
success = DEV.read32(data_addr) == 0xdeadbeef
-- restore SR and EBASE
XBURST.write_cp0(12, 0, old_sr)
XBURST.write_cp0(15, 1, ebase_old)
return success and "Exception and EBASE are working" or "Exception and EBASE are NOT working"
end
function XBURST.test_ebase(mem_addr)
-- EBase
ebase_old = XBURST.read_cp0(15, 1)
sr_old = XBURST.read_cp0(12, 0)
print("Testing EBASE...")
print(" Disable BEV")
XBURST.write_cp0(12, 0, bit32.replace(sr_old, 0, 22)) -- clear BEV
print(string.format(" SR value: 0x%x", XBURST.read_cp0(12, 0)))
print(string.format(" EBASE value: 0x%x", ebase_old))
print(" Test result: " .. XBURST.do_ebase_test())
print(" Config7 result: " .. XBURST.do_ebase_cfg7gate_test())
XBURST.write_cp0(12, 0, sr_old)
XBURST.write_cp0(15, 1, ebase_old)
-- now try with actual exceptions
if mem_addr == nil then
print(" Not doing exception test, please specify memory to use: sram, ram")
return
end
print(" Exception result: " .. XBURST.do_ebase_exc_test(mem_addr))
end
function XBURST.init()
-- enable CP1 in SR
sr_old = XBURST.read_cp0(12, 0)
XBURST.write_cp0(12, 0, bit32.replace(sr_old, 1, 29)) -- set CU1
print("XBurst:")
-- PRId
XBURST.prid = XBURST.read_cp0(15, 0)
print(string.format(" PRId: 0x%x", XBURST.prid))
print(" CPU: " .. XBURST.get_table_or(XBURST.prid_table, XBURST.prid, "unknown"))
-- Config
XBURST.config = XBURST.read_cp0(16, 0)
print(string.format(" Config: 0x%x", XBURST.config))
print(" Architecture Type: " .. XBURST.get_table_or(XBURST.at_table,
bit32.extract(XBURST.config, 13, 2), "unknown"))
print(" Architecture Level: " .. XBURST.get_table_or(XBURST.ar_table,
bit32.extract(XBURST.config, 10, 3), "unknown"))
print(" MMU Type: " .. XBURST.get_table_or(XBURST.mt_table,
bit32.extract(XBURST.config, 7, 3), "unknown"))
-- Config1
XBURST.config1 = XBURST.read_cp0(16, 1)
print(string.format(" Config1: 0x%x", XBURST.config1))
-- don't print of no MMU
if bit32.extract(XBURST.config, 7, 3) ~= 0 then
print(string.format(" MMU Size: %d", bit32.extract(XBURST.config1, 25, 6) + 1))
end
print(" ICache")
print(" Sets per way: " .. XBURST.get_table_or(XBURST.is_table,
bit32.extract(XBURST.config1, 22, 3), "unknown"))
print(" Ways: " .. (1 + bit32.extract(XBURST.config1, 16, 3)))
print(" Line size: " .. XBURST.get_table_or(XBURST.il_table,
bit32.extract(XBURST.config1, 19, 3), "unknown"))
print(" DCache")
print(" Sets per way: " .. XBURST.get_table_or(XBURST.is_table,
bit32.extract(XBURST.config1, 13, 3), "unknown"))
print(" Ways: " .. (1 + bit32.extract(XBURST.config1, 7, 3)))
print(" Line size: " .. XBURST.get_table_or(XBURST.il_table,
bit32.extract(XBURST.config1, 10, 3), "unknown"))
print(" FPU: " .. (bit32.extract(XBURST.config1, 0) == 1 and "yes" or "no"))
-- Config 2
XBURST.config2 = XBURST.read_cp0(16, 2)
print(string.format(" Config2: 0x%x", XBURST.config2))
-- Config 3
XBURST.config3 = XBURST.read_cp0(16, 3)
print(string.format(" Config3: 0x%x", XBURST.config3))
print(" Vectored interrupt: " .. (bit32.extract(XBURST.config2, 5) and "yes" or "no"))
-- Config 7
XBURST.config7 = XBURST.read_cp0(16, 7)
print(string.format(" Config7: 0x%x", XBURST.config7))
-- restore SR
XBURST.write_cp0(12, 0, sr_old)
end
|