diff options
-rw-r--r-- | utils/hwstub/tools/lua/jz/misc.lua | 43 | ||||
-rw-r--r-- | utils/hwstub/tools/lua/xburst.lua | 238 |
2 files changed, 281 insertions, 0 deletions
diff --git a/utils/hwstub/tools/lua/jz/misc.lua b/utils/hwstub/tools/lua/jz/misc.lua new file mode 100644 index 0000000000..fb4185de33 --- /dev/null +++ b/utils/hwstub/tools/lua/jz/misc.lua | |||
@@ -0,0 +1,43 @@ | |||
1 | ---------- | ||
2 | -- MISC -- | ||
3 | ---------- | ||
4 | |||
5 | JZ.misc = {} | ||
6 | |||
7 | function JZ.misc.enable_sram() | ||
8 | HW.CPM.CLKGATE1.SRAM.clr() | ||
9 | HW.CPM.CLKGATE1.AHB1.clr() | ||
10 | end | ||
11 | |||
12 | function JZ.misc.test_sram() | ||
13 | DEV.write32(0xb32d0000, 0xaaaa5555) | ||
14 | if DEV.read32(0xb32d0000) ~= 0xaaaa5555 then | ||
15 | error("SRAM is not working") | ||
16 | end | ||
17 | DEV.write32(0xb32d0000, 0xdeadbeef) | ||
18 | if DEV.read32(0xb32d0000) ~= 0xdeadbeef then | ||
19 | error("SRAM is not working") | ||
20 | end | ||
21 | print("SRAM seems to be working") | ||
22 | size = 0 | ||
23 | for i=4,64*1024,4 do | ||
24 | DEV.write32(0xb32d0000, 0xdeadbeef) | ||
25 | DEV.write32(0xb32d0000 + i, 0xcafebabe) | ||
26 | if DEV.read32(0xb32d0000 + i) ~= 0xcafebabe or DEV.read32(0xb32d0000) == 0xcafebabe then | ||
27 | size = i | ||
28 | break | ||
29 | end | ||
30 | end | ||
31 | print(string.format("SRAM size: 0x%x (%d KiB)", size, size / 1024)) | ||
32 | -- double check | ||
33 | for i=0,size-1,2 do | ||
34 | DEV.write16(0xb32d0000 + i, i) | ||
35 | end | ||
36 | for i=0,size-1,2 do | ||
37 | if DEV.read16(0xb32d0000 + i) ~= i then | ||
38 | error(string.format("SRAM size is not confirmed: read @%x gives %d instead of %d", | ||
39 | 0xb32d0000 + i, DEV.read16(0xb32d0000 + i), i)) | ||
40 | end | ||
41 | end | ||
42 | print("SRAM size confirmed and working") | ||
43 | end | ||
diff --git a/utils/hwstub/tools/lua/xburst.lua b/utils/hwstub/tools/lua/xburst.lua new file mode 100644 index 0000000000..ddaf7fbc66 --- /dev/null +++ b/utils/hwstub/tools/lua/xburst.lua | |||
@@ -0,0 +1,238 @@ | |||
1 | XBURST = {} | ||
2 | |||
3 | function XBURST.read_cp0(reg, sel) | ||
4 | return DEV.read32_cop({0, reg, sel}) | ||
5 | end | ||
6 | |||
7 | function XBURST.write_cp0(reg, sel, val) | ||
8 | DEV.write32_cop({0, reg, sel}, val) | ||
9 | end | ||
10 | |||
11 | XBURST.prid_table = { | ||
12 | [0x0ad0024f] = "JZ4740", | ||
13 | [0x1ed0024f] = "JZ4755", | ||
14 | [0x2ed0024f] = "JZ4760(B)", | ||
15 | [0x3ee1024f] = "JZ4780" | ||
16 | } | ||
17 | |||
18 | XBURST.at_table = { | ||
19 | [0] = "MIPS32", | ||
20 | [1] = "MIPS64 with 32-bit segments", | ||
21 | [2] = "MIPS64" | ||
22 | } | ||
23 | |||
24 | XBURST.ar_table = { | ||
25 | [0] = "Release 1", | ||
26 | [1] = "Release 2 (or more)" | ||
27 | } | ||
28 | |||
29 | XBURST.mt_table = { | ||
30 | [0] = "None", | ||
31 | [1] = "Standard TLB", | ||
32 | [2] = "BAT", | ||
33 | [3] = "Fixed Mapping", | ||
34 | [4] = "Dual VTLB and FTLB" | ||
35 | } | ||
36 | |||
37 | XBURST.is_table = { | ||
38 | [0] = 64, | ||
39 | [1] = 128, | ||
40 | [2] = 256, | ||
41 | [3] = 512, | ||
42 | [4] = 1024, | ||
43 | [5] = 2048, | ||
44 | [6] = 4096, | ||
45 | [7] = 32 | ||
46 | } | ||
47 | |||
48 | XBURST.il_table = { | ||
49 | [0] = 0, | ||
50 | [1] = 4, | ||
51 | [2] = 8, | ||
52 | [3] = 16, | ||
53 | [4] = 32, | ||
54 | [5] = 64, | ||
55 | [6] = 128 | ||
56 | } | ||
57 | |||
58 | function XBURST.get_table_or(tbl, index, dflt) | ||
59 | if tbl[index] ~= nil then | ||
60 | return tbl[index] | ||
61 | else | ||
62 | return dflt | ||
63 | end | ||
64 | end | ||
65 | |||
66 | function XBURST.do_ebase_test() | ||
67 | XBURST.write_cp0(15, 1, 0x80000000) | ||
68 | print(string.format(" Value after writing 0x80000000: 0x%x", XBURST.read_cp0(15, 1))) | ||
69 | if XBURST.read_cp0(15, 1) ~= 0x80000000 then | ||
70 | return "Value 0x8000000 does not stick, EBASE is probably not working" | ||
71 | end | ||
72 | XBURST.write_cp0(15, 1, 0x80040000) | ||
73 | print(string.format(" Value after writing 0x80040000: 0x%x", XBURST.read_cp0(15, 1))) | ||
74 | if XBURST.read_cp0(15, 1) ~= 0x80040000 then | ||
75 | return "Value 0x80040000 does not stick, EBASE is probably not working" | ||
76 | end | ||
77 | return "EBase seems to work" | ||
78 | end | ||
79 | |||
80 | function XBURST.do_ebase_cfg7gate_test() | ||
81 | -- test gate in config7 | ||
82 | config7_old = XBURST.read_cp0(16, 7) | ||
83 | XBURST.write_cp0(16, 7, bit32.replace(config7_old, 0, 7)) -- disable EBASE[30] modification | ||
84 | print(string.format(" Disable config7 gate: write 0x%x to Config7", bit32.replace(config7_old, 0, 7))) | ||
85 | XBURST.write_cp0(15, 1, 0xfffff000) | ||
86 | print(string.format(" Value after writing 0xfffff000: 0x%x", XBURST.read_cp0(15, 1))) | ||
87 | if XBURST.read_cp0(15, 1) == 0xfffff000 then | ||
88 | return "Config7 gate has no effect but modifications are allowed anyway" | ||
89 | end | ||
90 | XBURST.write_cp0(16, 7, bit32.replace(config7_old, 1, 7)) -- enable EBASE[30] modification | ||
91 | print(string.format(" Enable config7 gate: write 0x%x to Config7", bit32.replace(config7_old, 1, 7))) | ||
92 | XBURST.write_cp0(15, 1, 0xc0000000) | ||
93 | print(string.format(" Value after writing 0xc0000000: 0x%x", XBURST.read_cp0(15, 1))) | ||
94 | if XBURST.read_cp0(15, 1) ~= 0xc0000000 then | ||
95 | return "Config7 gate does not work" | ||
96 | end | ||
97 | XBURST.write_cp0(16, 7, config7_old) | ||
98 | return "Config7 gate seems to work" | ||
99 | end | ||
100 | |||
101 | function XBURST.do_ebase_exc_test(mem_addr) | ||
102 | if (mem_addr % 0x1000) ~= 0 then | ||
103 | return " memory address for exception test must aligned on a 0x1000 boundary"; | ||
104 | end | ||
105 | print(string.format("Exception test with EBASE at 0x%x...", mem_addr)) | ||
106 | print(" Writing instructions to memory") | ||
107 | -- create instructions in memory | ||
108 | exc_addr = mem_addr + 0x180 -- general exception vector | ||
109 | data_addr = mem_addr + 0x300 | ||
110 | -- lui k0,<low part of data_addr> | ||
111 | -- ori k0,k0,<high part> | ||
112 | DEV.write32(exc_addr + 0, 0x3c1a0000 + bit32.rshift(data_addr, 16)) | ||
113 | DEV.write32(exc_addr + 4, 0x375a0000 + bit32.band(data_addr, 0xffff)) | ||
114 | -- lui k1,0xdead | ||
115 | -- ori k1,k1,0xbeef | ||
116 | DEV.write32(exc_addr + 8, 0x3c1bdead) | ||
117 | DEV.write32(exc_addr + 12, 0x377bbeef) | ||
118 | -- sw k1,0(k0) | ||
119 | DEV.write32(exc_addr + 16, 0xaf5b0000) | ||
120 | -- mfc0 k0,c0_epc | ||
121 | -- addi k0,k0,4 | ||
122 | -- mtc0 k0,c0_epc | ||
123 | DEV.write32(exc_addr + 20, 0x401a7000) | ||
124 | DEV.write32(exc_addr + 24, 0x235a0004) | ||
125 | DEV.write32(exc_addr + 28, 0x409a7000) | ||
126 | -- eret | ||
127 | -- nop | ||
128 | DEV.write32(exc_addr + 32, 0x42000018) | ||
129 | DEV.write32(exc_addr + 36, 0) | ||
130 | -- fill data with some initial value | ||
131 | DEV.write32(data_addr, 0xcafebabe) | ||
132 | -- write instructions to trigger an interrupt | ||
133 | bug_addr = mem_addr | ||
134 | -- syscall | ||
135 | DEV.write32(bug_addr + 0, 0x0000000c) | ||
136 | -- jr ra | ||
137 | -- nop | ||
138 | DEV.write32(bug_addr + 4, 0x03e00008) | ||
139 | DEV.write32(bug_addr + 8, 0) | ||
140 | |||
141 | -- make sure we are the right shape for the test: SR should have BEV cleared, | ||
142 | -- mask all interrupts, enable interrupts | ||
143 | old_sr = XBURST.read_cp0(12, 0) | ||
144 | print(string.format(" Old SR: 0x%x", old_sr)) | ||
145 | XBURST.write_cp0(12, 0, 0xfc00) -- BEV set to 0, all interrupts masked and interrupt disabled | ||
146 | print(string.format(" New SR: 0x%x", XBURST.read_cp0(12, 0))) | ||
147 | -- change EBASE | ||
148 | old_ebase = XBURST.read_cp0(15, 1) | ||
149 | XBURST.write_cp0(15, 1, mem_addr) | ||
150 | print(string.format(" EBASE: %x", XBURST.read_cp0(15, 1))) | ||
151 | -- test | ||
152 | print(string.format(" Before: %x", DEV.read32(data_addr))) | ||
153 | DEV.call(bug_addr) | ||
154 | print(string.format(" After: %x", DEV.read32(data_addr))) | ||
155 | success = DEV.read32(data_addr) == 0xdeadbeef | ||
156 | -- restore SR and EBASE | ||
157 | XBURST.write_cp0(12, 0, old_sr) | ||
158 | XBURST.write_cp0(15, 1, ebase_old) | ||
159 | |||
160 | return success and "Exception and EBASE are working" or "Exception and EBASE are NOT working" | ||
161 | end | ||
162 | |||
163 | function XBURST.test_ebase(mem_addr) | ||
164 | -- EBase | ||
165 | ebase_old = XBURST.read_cp0(15, 1) | ||
166 | sr_old = XBURST.read_cp0(12, 0) | ||
167 | print("Testing EBASE...") | ||
168 | print(" Disable BEV") | ||
169 | XBURST.write_cp0(12, 0, bit32.replace(sr_old, 0, 22)) -- clear BEV | ||
170 | print(string.format(" SR value: 0x%x", XBURST.read_cp0(12, 0))) | ||
171 | print(string.format(" EBASE value: 0x%x", ebase_old)) | ||
172 | print(" Test result: " .. XBURST.do_ebase_test()) | ||
173 | print(" Config7 result: " .. XBURST.do_ebase_cfg7gate_test()) | ||
174 | XBURST.write_cp0(12, 0, sr_old) | ||
175 | XBURST.write_cp0(15, 1, ebase_old) | ||
176 | -- now try with actual exceptions | ||
177 | if mem_addr == nil then | ||
178 | print(" Not doing exception test, please specify memory to use: sram, ram") | ||
179 | return | ||
180 | end | ||
181 | print(" Exception result: " .. XBURST.do_ebase_exc_test(mem_addr)) | ||
182 | end | ||
183 | |||
184 | function XBURST.init() | ||
185 | -- enable CP1 in SR | ||
186 | sr_old = XBURST.read_cp0(12, 0) | ||
187 | XBURST.write_cp0(12, 0, bit32.replace(sr_old, 1, 29)) -- set CU1 | ||
188 | print("XBurst:") | ||
189 | -- PRId | ||
190 | XBURST.prid = XBURST.read_cp0(15, 0) | ||
191 | print(string.format(" PRId: 0x%x", XBURST.prid)) | ||
192 | print(" CPU: " .. XBURST.get_table_or(XBURST.prid_table, XBURST.prid, "unknown")) | ||
193 | -- Config | ||
194 | XBURST.config = XBURST.read_cp0(16, 0) | ||
195 | print(string.format(" Config: 0x%x", XBURST.config)) | ||
196 | print(" Architecture Type: " .. XBURST.get_table_or(XBURST.at_table, | ||
197 | bit32.extract(XBURST.config, 13, 2), "unknown")) | ||
198 | print(" Architecture Level: " .. XBURST.get_table_or(XBURST.ar_table, | ||
199 | bit32.extract(XBURST.config, 10, 3), "unknown")) | ||
200 | print(" MMU Type: " .. XBURST.get_table_or(XBURST.mt_table, | ||
201 | bit32.extract(XBURST.config, 7, 3), "unknown")) | ||
202 | -- Config1 | ||
203 | XBURST.config1 = XBURST.read_cp0(16, 1) | ||
204 | print(string.format(" Config1: 0x%x", XBURST.config1)) | ||
205 | -- don't print of no MMU | ||
206 | if bit32.extract(XBURST.config, 7, 3) ~= 0 then | ||
207 | print(string.format(" MMU Size: %d", bit32.extract(XBURST.config1, 25, 6) + 1)) | ||
208 | end | ||
209 | print(" ICache") | ||
210 | print(" Sets per way: " .. XBURST.get_table_or(XBURST.is_table, | ||
211 | bit32.extract(XBURST.config1, 22, 3), "unknown")) | ||
212 | print(" Ways: " .. (1 + bit32.extract(XBURST.config1, 16, 3))) | ||
213 | print(" Line size: " .. XBURST.get_table_or(XBURST.il_table, | ||
214 | bit32.extract(XBURST.config1, 19, 3), "unknown")) | ||
215 | print(" DCache") | ||
216 | print(" Sets per way: " .. XBURST.get_table_or(XBURST.is_table, | ||
217 | bit32.extract(XBURST.config1, 13, 3), "unknown")) | ||
218 | print(" Ways: " .. (1 + bit32.extract(XBURST.config1, 7, 3))) | ||
219 | print(" Line size: " .. XBURST.get_table_or(XBURST.il_table, | ||
220 | bit32.extract(XBURST.config1, 10, 3), "unknown")) | ||
221 | print(" FPU: " .. (bit32.extract(XBURST.config1, 0) == 1 and "yes" or "no")) | ||
222 | |||
223 | -- Config 2 | ||
224 | XBURST.config2 = XBURST.read_cp0(16, 2) | ||
225 | print(string.format(" Config2: 0x%x", XBURST.config2)) | ||
226 | |||
227 | -- Config 3 | ||
228 | XBURST.config3 = XBURST.read_cp0(16, 3) | ||
229 | print(string.format(" Config3: 0x%x", XBURST.config3)) | ||
230 | print(" Vectored interrupt: " .. (bit32.extract(XBURST.config2, 5) and "yes" or "no")) | ||
231 | |||
232 | -- Config 7 | ||
233 | XBURST.config7 = XBURST.read_cp0(16, 7) | ||
234 | print(string.format(" Config7: 0x%x", XBURST.config7)) | ||
235 | |||
236 | -- restore SR | ||
237 | XBURST.write_cp0(12, 0, sr_old) | ||
238 | end | ||