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 @@ +---------- +-- MISC -- +---------- + +JZ.misc = {} + +function JZ.misc.enable_sram() + HW.CPM.CLKGATE1.SRAM.clr() + HW.CPM.CLKGATE1.AHB1.clr() +end + +function JZ.misc.test_sram() + DEV.write32(0xb32d0000, 0xaaaa5555) + if DEV.read32(0xb32d0000) ~= 0xaaaa5555 then + error("SRAM is not working") + end + DEV.write32(0xb32d0000, 0xdeadbeef) + if DEV.read32(0xb32d0000) ~= 0xdeadbeef then + error("SRAM is not working") + end + print("SRAM seems to be working") + size = 0 + for i=4,64*1024,4 do + DEV.write32(0xb32d0000, 0xdeadbeef) + DEV.write32(0xb32d0000 + i, 0xcafebabe) + if DEV.read32(0xb32d0000 + i) ~= 0xcafebabe or DEV.read32(0xb32d0000) == 0xcafebabe then + size = i + break + end + end + print(string.format("SRAM size: 0x%x (%d KiB)", size, size / 1024)) + -- double check + for i=0,size-1,2 do + DEV.write16(0xb32d0000 + i, i) + end + for i=0,size-1,2 do + if DEV.read16(0xb32d0000 + i) ~= i then + error(string.format("SRAM size is not confirmed: read @%x gives %d instead of %d", + 0xb32d0000 + i, DEV.read16(0xb32d0000 + i), i)) + end + end + print("SRAM size confirmed and working") +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 @@ +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, + -- ori k0,k0, + 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