Make pylint happy.
[riscv-tests.git] / debug / gdbserver.py
index d085e2ef60df5a3a2bc2fc1efb547cb4a9fc69ae..6f0f844f52a1172953fce6f899bccdfb9be57a61 100755 (executable)
@@ -12,7 +12,8 @@ import targets
 import testlib
 from testlib import assertEqual, assertNotEqual, assertIn, assertNotIn
 from testlib import assertGreater, assertRegexpMatches, assertLess
 import testlib
 from testlib import assertEqual, assertNotEqual, assertIn, assertNotIn
 from testlib import assertGreater, assertRegexpMatches, assertLess
-from testlib import GdbTest, GdbSingleHartTest, TestFailed, assertTrue
+from testlib import GdbTest, GdbSingleHartTest, TestFailed
+#from testlib import assertTrue
 
 MSTATUS_UIE = 0x00000001
 MSTATUS_SIE = 0x00000002
 
 MSTATUS_UIE = 0x00000001
 MSTATUS_SIE = 0x00000002
@@ -552,42 +553,88 @@ class MulticoreRegTest(GdbTest):
                 value = self.gdb.p("$x%d" % n)
                 assertEqual(value, hart.index * 0x800 + n - 1)
 
                 value = self.gdb.p("$x%d" % n)
                 assertEqual(value, hart.index * 0x800 + n - 1)
 
-class MulticoreRunHaltStepiTest(GdbTest):
+#class MulticoreRunHaltStepiTest(GdbTest):
+#    compile_args = ("programs/multicore.c", "-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("$mhartid")
+#            self.gdb.p("$pc=_start")
+#
+#    def test(self):
+#        previous_hart_count = [0 for h in self.target.harts]
+#        previous_interrupt_count = [0 for h in self.target.harts]
+#        # Check 10 times
+#        for i in range(10):
+#            # 3 attempts for each time we want the check to pass
+#            for attempt in range(3):
+#                self.gdb.global_command("echo round %d attempt %d\\n" % (i,
+#                    attempt))
+#                self.gdb.c_all(wait=False)
+#                time.sleep(2)
+#                self.gdb.interrupt_all()
+#                hart_count = self.gdb.p("hart_count")
+#                interrupt_count = self.gdb.p("interrupt_count")
+#                ok = True
+#                for i, h in enumerate(self.target.harts):
+#                    if hart_count[i] <= previous_hart_count[i]:
+#                        ok = False
+#                        break
+#                    if interrupt_count[i] <= previous_interrupt_count[i]:
+#                        ok = False
+#                        break
+#                    self.gdb.p("$mie")
+#                    self.gdb.p("$mip")
+#                    self.gdb.p("$mstatus")
+#                    self.gdb.p("$priv")
+#                    self.gdb.p("buf", fmt="")
+#                    self.gdb.select_hart(h)
+#                    pc = self.gdb.p("$pc")
+#                    self.gdb.stepi()
+#                    stepped_pc = self.gdb.p("$pc")
+#                    assertNotEqual(pc, stepped_pc)
+#                previous_hart_count = hart_count
+#                previous_interrupt_count = interrupt_count
+#                if ok:
+#                    break
+#            else:
+#                assert False, \
+#                        "hart count or interrupt didn't increment as expected"
+
+class MulticoreRunAllHaltOne(GdbTest):
     compile_args = ("programs/multicore.c", "-DMULTICORE")
 
     def early_applicable(self):
         return len(self.target.harts) > 1
 
     def setup(self):
     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):
         self.gdb.load()
         for hart in self.target.harts:
             self.gdb.select_hart(hart)
             self.gdb.p("$pc=_start")
 
     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):
+        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.c(wait=False)
-            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()
-                stepped_pc = self.gdb.p("$pc")
-                assertNotEqual(pc, stepped_pc)
 
 
-class MulticoreRunAllHaltOne(GdbTest):
+        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 MulticoreRtosSwitchActiveHartTest(GdbTest):
     compile_args = ("programs/multicore.c", "-DMULTICORE")
 
     def early_applicable(self):
     compile_args = ("programs/multicore.c", "-DMULTICORE")
 
     def early_applicable(self):
@@ -601,21 +648,22 @@ class MulticoreRunAllHaltOne(GdbTest):
             self.gdb.p("$pc=_start")
 
     def test(self):
             self.gdb.p("$pc=_start")
 
     def test(self):
-        if not self.gdb.one_hart_per_gdb():
+        if self.gdb.one_hart_per_gdb():
             return 'not_applicable'
 
             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)
+        # Set breakpoint near '_start' label to increase the chances of a
+        # situation when all harts hit breakpoint immediately and
+        # simultaneously.
+        self.gdb.b("set_trap_handler")
 
 
-        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="")
+        # Check that all harts hit breakpoint one by one.
+        for _ in range(len(self.target.harts)):
+            output = self.gdb.c()
+            assertIn("hit Breakpoint", output)
+            assertIn("set_trap_handler", output)
+            assertNotIn("received signal SIGTRAP", output)
 
 
-class StepTest(GdbTest):
+class StepTest(GdbSingleHartTest):
     compile_args = ("programs/step.S", )
 
     def setup(self):
     compile_args = ("programs/step.S", )
 
     def setup(self):
@@ -634,7 +682,30 @@ class StepTest(GdbTest):
             pc = self.gdb.p("$pc")
             assertEqual("%x" % (pc - main_address), "%x" % expected)
 
             pc = self.gdb.p("$pc")
             assertEqual("%x" % (pc - main_address), "%x" % expected)
 
-class TriggerTest(GdbTest):
+class JumpHbreak(GdbSingleHartTest):
+    """'jump' resumes execution at location. Execution stops again immediately
+    if there is a breakpoint there.
+    That second line can be trouble."""
+    compile_args = ("programs/trigger.S", )
+
+    def early_applicable(self):
+        return self.hart.instruction_hardware_breakpoint_count >= 1
+
+    def setup(self):
+        self.gdb.load()
+        self.gdb.hbreak("main")
+        self.gdb.c()
+        self.gdb.command("delete 1")
+
+    def test(self):
+        self.gdb.b("read_loop")
+        self.gdb.command("hbreak just_before_read_loop")
+        output = self.gdb.command("jump just_before_read_loop")
+        assertRegexpMatches(output, r"Breakpoint \d, just_before_read_loop ")
+        output = self.gdb.c()
+        assertRegexpMatches(output, r"Breakpoint \d, read_loop ")
+
+class TriggerTest(GdbSingleHartTest):
     compile_args = ("programs/trigger.S", )
     def setup(self):
         self.gdb.load()
     compile_args = ("programs/trigger.S", )
     def setup(self):
         self.gdb.load()
@@ -674,7 +745,8 @@ class TriggerLoadAddressInstant(TriggerTest):
         self.gdb.c()
         read_loop = self.gdb.p("&read_loop")
         read_again = self.gdb.p("&read_again")
         self.gdb.c()
         read_loop = self.gdb.p("&read_loop")
         read_again = self.gdb.p("&read_again")
-        self.gdb.command("rwatch data")
+        data = self.gdb.p("&data")
+        self.gdb.command("rwatch *0x%x" % data)
         self.gdb.c()
         # Accept hitting the breakpoint before or after the load instruction.
         assertIn(self.gdb.p("$pc"), [read_loop, read_loop + 4])
         self.gdb.c()
         # Accept hitting the breakpoint before or after the load instruction.
         assertIn(self.gdb.p("$pc"), [read_loop, read_loop + 4])
@@ -701,7 +773,8 @@ class TriggerStoreAddressInstant(TriggerTest):
         self.gdb.command("b just_before_write_loop")
         self.gdb.c()
         write_loop = self.gdb.p("&write_loop")
         self.gdb.command("b just_before_write_loop")
         self.gdb.c()
         write_loop = self.gdb.p("&write_loop")
-        self.gdb.command("watch data")
+        data = self.gdb.p("&data")
+        self.gdb.command("watch *0x%x" % data)
         self.gdb.c()
         # Accept hitting the breakpoint before or after the store instruction.
         assertIn(self.gdb.p("$pc"), [write_loop, write_loop + 4])
         self.gdb.c()
         # Accept hitting the breakpoint before or after the store instruction.
         assertIn(self.gdb.p("$pc"), [write_loop, write_loop + 4])
@@ -753,7 +826,7 @@ class TriggerDmode(TriggerTest):
         assertIn("clear_triggers", output)
         self.check_triggers((1<<6) | (1<<0), 0xfeedac00)
 
         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()
     compile_args = ("programs/regs.S", )
     def setup(self):
         self.gdb.load()
@@ -830,16 +903,17 @@ class DownloadTest(GdbTest):
 
         self.binary = self.target.compile(self.hart, self.download_c.name,
                 "programs/checksum.c")
 
         self.binary = self.target.compile(self.hart, self.download_c.name,
                 "programs/checksum.c")
-        self.gdb.command("file %s" % self.binary)
+        self.gdb.global_command("file %s" % self.binary)
 
     def test(self):
         self.gdb.load()
 
     def test(self):
         self.gdb.load()
+        self.parkOtherHarts()
         self.gdb.command("b _exit")
         self.gdb.c()
         assertEqual(self.gdb.p("status"), self.crc)
         os.unlink(self.download_c.name)
 
         self.gdb.command("b _exit")
         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()
 #    compile_args = ("programs/mprv.S", )
 #    def setup(self):
 #        self.gdb.load()
@@ -852,7 +926,7 @@ class DownloadTest(GdbTest):
 #        output = self.gdb.command("p/x *(int*)(((char*)&data)-0x80000000)")
 #        assertIn("0xbead", output)
 
 #        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
     compile_args = ("programs/priv.S", )
     def setup(self):
         # pylint: disable=attribute-defined-outside-init
@@ -881,6 +955,14 @@ class PrivRw(PrivTest):
             # PMP registers are optional
             pass
 
             # 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):
         # Leave the PC at _start, where the first 4 instructions should be
         # legal in any mode.
         for privilege in range(4):
@@ -891,28 +973,29 @@ class PrivRw(PrivTest):
             if privilege in self.supported:
                 assertEqual(actual, privilege)
 
             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)
+# XXX temporarily disabling this test
+#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():
 
 parsed = None
 def main():