X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=debug%2Fgdbserver.py;h=4d8d99a2276debf89f0cf2e30868bc3c25c4cc0a;hb=caa79b71bfc1f42e70a48980c81f8811df57811f;hp=7ae3aa3b1ba56dc57a443e367342c5b62b29fa2f;hpb=efe2f16d12c23eca1e66d2a304d89aafb22f005f;p=riscv-tests.git diff --git a/debug/gdbserver.py b/debug/gdbserver.py index 7ae3aa3..4d8d99a 100755 --- a/debug/gdbserver.py +++ b/debug/gdbserver.py @@ -12,7 +12,7 @@ import targets import testlib from testlib import assertEqual, assertNotEqual, assertIn, assertNotIn from testlib import assertGreater, assertRegexpMatches, assertLess -from testlib import GdbTest, GdbSingleHartTest +from testlib import GdbTest, GdbSingleHartTest, TestFailed, assertTrue MSTATUS_UIE = 0x00000001 MSTATUS_SIE = 0x00000002 @@ -124,8 +124,8 @@ class SimpleMemoryTest(GdbTest): assertEqual(self.gdb.p("sizeof(%s)" % data_type), size) a = 0x86753095555aaaa & ((1<<(size*8))-1) b = 0xdeadbeef12345678 & ((1<<(size*8))-1) - addrA = self.target.ram - addrB = self.target.ram + self.target.ram_size - size + addrA = self.hart.ram + addrB = self.hart.ram + self.hart.ram_size - size self.gdb.p("*((%s*)0x%x) = 0x%x" % (data_type, addrA, a)) self.gdb.p("*((%s*)0x%x) = 0x%x" % (data_type, addrB, b)) assertEqual(self.gdb.p("*((%s*)0x%x)" % (data_type, addrA)), a) @@ -171,20 +171,23 @@ class MemTest64(SimpleMemoryTest): # self.gdb.p("*((int*)0x%x)=6874742" % self.hart.ram) class MemTestBlock(GdbTest): + length = 1024 + line_length = 16 + def test(self): - length = 1024 - line_length = 16 a = tempfile.NamedTemporaryFile(suffix=".ihex") data = "" - for i in range(length / line_length): + for i in range(self.length / self.line_length): line_data = "".join(["%c" % random.randrange(256) - for _ in range(line_length)]) + for _ in range(self.line_length)]) data += line_data - a.write(ihex_line(i * line_length, 0, line_data)) + a.write(ihex_line(i * self.line_length, 0, line_data)) a.flush() + self.gdb.command("shell cat %s" % a.name) self.gdb.command("restore %s 0x%x" % (a.name, self.hart.ram)) - for offset in range(0, length, 19*4) + [length-4]: + increment = 19 * 4 + for offset in range(0, self.length, increment) + [self.length-4]: value = self.gdb.p("*((int*)0x%x)" % (self.hart.ram + offset)) written = ord(data[offset]) | \ (ord(data[offset+1]) << 8) | \ @@ -194,13 +197,17 @@ class MemTestBlock(GdbTest): b = tempfile.NamedTemporaryFile(suffix=".ihex") self.gdb.command("dump ihex memory %s 0x%x 0x%x" % (b.name, - self.hart.ram, self.hart.ram + length)) + self.hart.ram, self.hart.ram + self.length)) + self.gdb.command("shell cat %s" % b.name) for line in b: record_type, address, line_data = ihex_parse(line) if record_type == 0: - assertEqual(readable_binary_string(line_data), - readable_binary_string( - data[address:address+len(line_data)])) + written_data = data[address:address+len(line_data)] + if line_data != written_data: + raise TestFailed( + "Data mismatch at 0x%x; wrote %s but read %s" % ( + address, readable_binary_string(written_data), + readable_binary_string(line_data))) class InstantHaltTest(GdbTest): def test(self): @@ -213,7 +220,7 @@ class InstantHaltTest(GdbTest): self.gdb.thread(t) pcs.append(self.gdb.p("$pc")) for pc in pcs: - assertEqual(self.hart.reset_vector, pc) + assertIn(pc, self.hart.reset_vectors) # mcycle and minstret have no defined reset value. mstatus = self.gdb.p("$mstatus") assertEqual(mstatus & (MSTATUS_MIE | MSTATUS_MPRV | @@ -359,7 +366,7 @@ class Hwbp2(DebugTest): self.exit() class TooManyHwbp(DebugTest): - def run(self): + def test(self): for i in range(30): self.gdb.hbreak("*rot13 + %d" % (i * 4)) @@ -415,6 +422,49 @@ class UserInterrupt(DebugTest): self.gdb.p("i=0") self.exit() +class InterruptTest(GdbSingleHartTest): + compile_args = ("programs/interrupt.c",) + + def early_applicable(self): + return self.target.supports_clint_mtime + + def setup(self): + self.gdb.load() + + def test(self): + self.gdb.b("main") + output = self.gdb.c() + assertIn(" main ", output) + self.gdb.b("trap_entry") + output = self.gdb.c() + assertIn(" trap_entry ", output) + assertEqual(self.gdb.p("$mip") & 0x80, 0x80) + assertEqual(self.gdb.p("interrupt_count"), 0) + # You'd expect local to still be 0, but it looks like spike doesn't + # jump to the interrupt handler immediately after the write to + # mtimecmp. + assertLess(self.gdb.p("local"), 1000) + self.gdb.command("delete breakpoints") + for _ in range(10): + self.gdb.c(wait=False) + time.sleep(2) + self.gdb.interrupt() + interrupt_count = self.gdb.p("interrupt_count") + local = self.gdb.p("local") + if interrupt_count > 1000 and \ + local > 1000: + return + + assertGreater(interrupt_count, 1000) + assertGreater(local, 1000) + + def postMortem(self): + GdbSingleHartTest.postMortem(self) + self.gdb.p("*((long long*) 0x200bff8)") + self.gdb.p("*((long long*) 0x2004000)") + self.gdb.p("interrupt_count") + self.gdb.p("local") + class MulticoreRegTest(GdbTest): compile_args = ("programs/infinite_loop.S", "-DMULTICORE") @@ -429,21 +479,24 @@ class MulticoreRegTest(GdbTest): def test(self): # Run to main - self.gdb.b("main") - self.gdb.c() - for t in self.gdb.threads(): - assertIn("main", t.frame) - self.gdb.command("delete breakpoints") + for hart in self.target.harts: + self.gdb.select_hart(hart) + self.gdb.b("main") + self.gdb.c() + assertIn("main", self.gdb.where()) + self.gdb.command("delete breakpoints") # Run through the entire loop. - self.gdb.b("main_end") - self.gdb.c() + for hart in self.target.harts: + self.gdb.select_hart(hart) + self.gdb.b("main_end") + self.gdb.c() + assertIn("main_end", self.gdb.where()) hart_ids = [] - for t in self.gdb.threads(): - assertIn("main_end", t.frame) + for hart in self.target.harts: + self.gdb.select_hart(hart) # Check register values. - self.gdb.thread(t) hart_id = self.gdb.p("$x1") assertNotIn(hart_id, hart_ids) hart_ids.append(hart_id) @@ -458,17 +511,16 @@ class MulticoreRegTest(GdbTest): self.gdb.select_hart(hart) self.gdb.p("$x1=0x%x" % (hart.index * 0x800)) self.gdb.p("$pc=main_post_csrr") - self.gdb.c() - for t in self.gdb.threads(): - assertIn("main_end", t.frame) + self.gdb.c() for hart in self.target.harts: - # Check register values. self.gdb.select_hart(hart) + assertIn("main", self.gdb.where()) + # Check register values. for n in range(1, 32): value = self.gdb.p("$x%d" % n) assertEqual(value, hart.index * 0x800 + n - 1) -class MulticoreRunHaltTest(GdbTest): +class MulticoreRunHaltStepiTest(GdbTest): compile_args = ("programs/multicore.c", "-DMULTICORE") def early_applicable(self): @@ -482,14 +534,21 @@ class MulticoreRunHaltTest(GdbTest): def test(self): previous_hart_count = [0 for h in self.target.harts] + previous_interrupt_count = [0 for h in self.target.harts] for _ in range(10): self.gdb.c(wait=False) - time.sleep(1) + time.sleep(2) self.gdb.interrupt() + self.gdb.p("$mie") + self.gdb.p("$mip") + self.gdb.p("$mstatus") + self.gdb.p("$priv") self.gdb.p("buf", fmt="") hart_count = self.gdb.p("hart_count") + interrupt_count = self.gdb.p("interrupt_count") for i, h in enumerate(self.target.harts): assertGreater(hart_count[i], previous_hart_count[i]) + assertGreater(interrupt_count[i], previous_interrupt_count[i]) self.gdb.select_hart(h) pc = self.gdb.p("$pc") self.gdb.stepi() @@ -704,7 +763,7 @@ class DownloadTest(GdbTest): if self.crc < 0: self.crc += 2**32 - self.binary = self.hart.compile(self.download_c.name, + self.binary = self.target.compile(self.hart, self.download_c.name, "programs/checksum.c") self.gdb.command("file %s" % self.binary) @@ -715,7 +774,6 @@ class DownloadTest(GdbTest): assertEqual(self.gdb.p("status"), self.crc) os.unlink(self.download_c.name) -# FIXME: PRIV isn't implemented in the current OpenOCD #class MprvTest(GdbTest): # compile_args = ("programs/mprv.S", ) # def setup(self): @@ -728,56 +786,56 @@ class DownloadTest(GdbTest): # self.gdb.interrupt() # output = self.gdb.command("p/x *(int*)(((char*)&data)-0x80000000)") # assertIn("0xbead", output) -# -#class PrivTest(GdbTest): -# compile_args = ("programs/priv.S", ) -# def setup(self): -# # pylint: disable=attribute-defined-outside-init -# self.gdb.load() -# -# misa = self.hart.misa -# self.supported = set() -# if misa & (1<<20): -# self.supported.add(0) -# if misa & (1<<18): -# self.supported.add(1) -# if misa & (1<<7): -# self.supported.add(2) -# self.supported.add(3) -# -#class PrivRw(PrivTest): -# def test(self): -# """Test reading/writing priv.""" -# for privilege in range(4): -# self.gdb.p("$priv=%d" % privilege) -# self.gdb.stepi() -# actual = self.gdb.p("$priv") -# assertIn(actual, self.supported) -# if privilege in self.supported: -# assertEqual(actual, privilege) -# -#class PrivChange(PrivTest): -# def test(self): -# """Test that the core's privilege level actually changes.""" -# -# if 0 not in self.supported: -# return 'not_applicable' -# -# self.gdb.b("main") -# self.gdb.c() -# -# # Machine mode -# self.gdb.p("$priv=3") -# main_address = self.gdb.p("$pc") -# self.gdb.stepi() -# assertEqual("%x" % self.gdb.p("$pc"), "%x" % (main_address+4)) -# -# # User mode -# self.gdb.p("$priv=0") -# self.gdb.stepi() -# # Should have taken an exception, so be nowhere near main. -# pc = self.gdb.p("$pc") -# assertTrue(pc < main_address or pc > main_address + 0x100) + +class PrivTest(GdbTest): + compile_args = ("programs/priv.S", ) + def setup(self): + # pylint: disable=attribute-defined-outside-init + self.gdb.load() + + misa = self.hart.misa + self.supported = set() + if misa & (1<<20): + self.supported.add(0) + if misa & (1<<18): + self.supported.add(1) + if misa & (1<<7): + self.supported.add(2) + self.supported.add(3) + +class PrivRw(PrivTest): + def test(self): + """Test reading/writing priv.""" + for privilege in range(4): + self.gdb.p("$priv=%d" % privilege) + self.gdb.stepi() + actual = self.gdb.p("$priv") + assertIn(actual, self.supported) + if privilege in self.supported: + assertEqual(actual, privilege) + +class PrivChange(PrivTest): + def test(self): + """Test that the core's privilege level actually changes.""" + + if 0 not in self.supported: + return 'not_applicable' + + self.gdb.b("main") + self.gdb.c() + + # Machine mode + self.gdb.p("$priv=3") + main_address = self.gdb.p("$pc") + self.gdb.stepi() + assertEqual("%x" % self.gdb.p("$pc"), "%x" % (main_address+4)) + + # User mode + self.gdb.p("$priv=0") + self.gdb.stepi() + # Should have taken an exception, so be nowhere near main. + pc = self.gdb.p("$pc") + assertTrue(pc < main_address or pc > main_address + 0x100) parsed = None def main():