X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=debug%2Fgdbserver.py;h=0c3cee4b3328fd12bb0c045482923c2c532a51d4;hb=6513bdb6f8ed77cd6a333ebc166e964e15357065;hp=51c6ab6b09d550e2d1fbce5d4b8ee81ef09c5d35;hpb=452853f0f96be65cde0900265b654c01b35f321d;p=riscv-tests.git diff --git a/debug/gdbserver.py b/debug/gdbserver.py index 51c6ab6..0c3cee4 100755 --- a/debug/gdbserver.py +++ b/debug/gdbserver.py @@ -65,15 +65,19 @@ def readable_binary_string(s): return "".join("%02x" % ord(c) for c in s) class SimpleRegisterTest(GdbTest): - def check_reg(self, name): + def check_reg(self, name, alias): a = random.randrange(1< 1 -# -# def setup(self): -# self.gdb.load() -# for hart in self.target.harts: -# self.gdb.select_hart(hart) -# self.gdb.p("$pc=_start") -# -# def test(self): -# # Run to main -# # Hart 0 is the first to be resumed, so we have to set the breakpoint -# # there. gdb won't actually set the breakpoint until we tell it to -# # resume. -# self.gdb.select_hart(self.target.harts[0]) -# self.gdb.b("main") -# self.gdb.c_all() -# for hart in self.target.harts: -# self.gdb.select_hart(hart) -# assertIn("main", self.gdb.where()) -# self.gdb.select_hart(self.target.harts[0]) -# self.gdb.command("delete breakpoints") -# -# # Run through the entire loop. -# self.gdb.b("main_end") -# self.gdb.c_all() -# -# hart_ids = [] -# for hart in self.target.harts: -# self.gdb.select_hart(hart) -# assertIn("main_end", self.gdb.where()) -# # Check register values. -# hart_id = self.gdb.p("$x1") -# assertNotIn(hart_id, hart_ids) -# hart_ids.append(hart_id) -# for n in range(2, 32): -# value = self.gdb.p("$x%d" % n) -# assertEqual(value, hart_ids[-1] + n - 1) -# -# # Confirmed that we read different register values for different harts. -# # Write a new value to x1, and run through the add sequence again. -# -# for hart in self.target.harts: -# self.gdb.select_hart(hart) -# self.gdb.p("$x1=0x%x" % (hart.index * 0x800)) -# self.gdb.p("$pc=main_post_csrr") -# self.gdb.c_all() -# for hart in self.target.harts: -# 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 MulticoreRegTest(GdbTest): + compile_args = ("programs/infinite_loop.S", "-DMULTICORE") + + def early_applicable(self): + return len(self.target.harts) > 1 + + def setup(self): + self.gdb.load() + for hart in self.target.harts: + self.gdb.select_hart(hart) + self.gdb.p("$pc=_start") + + def test(self): + # Run to main + 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. + 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 hart in self.target.harts: + self.gdb.select_hart(hart) + # Check register values. + hart_id = self.gdb.p("$x1") + assertNotIn(hart_id, hart_ids) + hart_ids.append(hart_id) + for n in range(2, 32): + value = self.gdb.p("$x%d" % n) + assertEqual(value, hart_ids[-1] + n - 1) + + # Confirmed that we read different register values for different harts. + # Write a new value to x1, and run through the add sequence again. + + for hart in self.target.harts: + 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 hart in self.target.harts: + 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 MulticoreRunHaltStepiTest(GdbTest): compile_args = ("programs/multicore.c", "-DMULTICORE") @@ -559,7 +589,35 @@ class MulticoreRunHaltStepiTest(GdbTest): stepped_pc = self.gdb.p("$pc") assertNotEqual(pc, stepped_pc) -class StepTest(GdbTest): +class MulticoreRunAllHaltOne(GdbTest): + compile_args = ("programs/multicore.c", "-DMULTICORE") + + def early_applicable(self): + return len(self.target.harts) > 1 + + def setup(self): + self.gdb.select_hart(self.target.harts[0]) + self.gdb.load() + for hart in self.target.harts: + self.gdb.select_hart(hart) + self.gdb.p("$pc=_start") + + def test(self): + if not self.gdb.one_hart_per_gdb(): + return 'not_applicable' + + # Run harts in reverse order + for h in reversed(self.target.harts): + self.gdb.select_hart(h) + self.gdb.c(wait=False) + + self.gdb.interrupt() + # Give OpenOCD time to call poll() on both harts, which is what causes + # the bug. + time.sleep(1) + self.gdb.p("buf", fmt="") + +class StepTest(GdbSingleHartTest): compile_args = ("programs/step.S", ) def setup(self): @@ -578,7 +636,7 @@ class StepTest(GdbTest): pc = self.gdb.p("$pc") assertEqual("%x" % (pc - main_address), "%x" % expected) -class TriggerTest(GdbTest): +class TriggerTest(GdbSingleHartTest): compile_args = ("programs/trigger.S", ) def setup(self): self.gdb.load() @@ -617,12 +675,17 @@ class TriggerLoadAddressInstant(TriggerTest): self.gdb.command("b just_before_read_loop") self.gdb.c() read_loop = self.gdb.p("&read_loop") + read_again = self.gdb.p("&read_again") self.gdb.command("rwatch data") self.gdb.c() # Accept hitting the breakpoint before or after the load instruction. assertIn(self.gdb.p("$pc"), [read_loop, read_loop + 4]) assertEqual(self.gdb.p("$a0"), self.gdb.p("&data")) + self.gdb.c() + assertIn(self.gdb.p("$pc"), [read_again, read_again + 4]) + assertEqual(self.gdb.p("$a0"), self.gdb.p("&data")) + # FIXME: Triggers aren't quite working yet #class TriggerStoreAddress(TriggerTest): # def test(self): @@ -692,7 +755,7 @@ class TriggerDmode(TriggerTest): assertIn("clear_triggers", output) self.check_triggers((1<<6) | (1<<0), 0xfeedac00) -class RegsTest(GdbTest): +class RegsTest(GdbSingleHartTest): compile_args = ("programs/regs.S", ) def setup(self): self.gdb.load() @@ -772,13 +835,27 @@ class DownloadTest(GdbTest): self.gdb.command("file %s" % self.binary) def test(self): - self.gdb.load() - self.gdb.command("b _exit") - self.gdb.c(timeout=60) + # Some hart will compete the CRC calculation first! + # Let them race in RTOS mode. + # In non-RTOS mode, only one hart will continue. + # This loop will fail because the others won't know + # about '_start'. But if that is the case, they + # won't run on the `continue` either, so we don't really care. + try: + self.gdb.load() + for hart in self.target.harts: + self.gdb.select_hart(hart) + self.gdb.p("$pc=_start") + except ValueError: #invalid literal for int() with base 0: 'No symbol table is loaded. Use the "file" command.' + pass + finally: + + self.gdb.select_hart(self.hart) + self.gdb.c() assertEqual(self.gdb.p("status"), self.crc) os.unlink(self.download_c.name) -#class MprvTest(GdbTest): +#class MprvTest(GdbSingleHartTest): # compile_args = ("programs/mprv.S", ) # def setup(self): # self.gdb.load() @@ -791,7 +868,7 @@ class DownloadTest(GdbTest): # output = self.gdb.command("p/x *(int*)(((char*)&data)-0x80000000)") # assertIn("0xbead", output) -class PrivTest(GdbTest): +class PrivTest(GdbSingleHartTest): compile_args = ("programs/priv.S", ) def setup(self): # pylint: disable=attribute-defined-outside-init @@ -810,6 +887,26 @@ class PrivTest(GdbTest): class PrivRw(PrivTest): def test(self): """Test reading/writing priv.""" + # Disable physical memory protection by allowing U mode access to all + # memory. + try: + self.gdb.p("$pmpcfg0=0xf") # TOR, R, W, X + self.gdb.p("$pmpaddr0=0x%x" % + ((self.hart.ram + self.hart.ram_size) >> 2)) + except testlib.CouldNotFetch: + # PMP registers are optional + pass + + # Ensure Virtual Memory is disabled if applicable (SATP register is not + # reset) + try: + self.gdb.p("$satp=0") + except testlib.CouldNotFetch: + # SATP only exists if you have S mode. + pass + + # Leave the PC at _start, where the first 4 instructions should be + # legal in any mode. for privilege in range(4): self.gdb.p("$priv=%d" % privilege) self.gdb.stepi() @@ -858,9 +955,7 @@ def main(): global parsed # pylint: disable=global-statement parsed = parser.parse_args() target = targets.target(parsed) - - if parsed.xlen: - target.xlen = parsed.xlen + testlib.print_log_names = parsed.print_log_names module = sys.modules[__name__]