Add debug test, which checks that openocd correctly switch active thread on any hart...
[riscv-tests.git] / debug / gdbserver.py
index be89d19157b07789be13bad5a105091b393569c5..528eae19a35f2e71ccaf455234397a476027f3d7 100755 (executable)
@@ -562,30 +562,48 @@ class MulticoreRunHaltStepiTest(GdbTest):
         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]
-        for _ in range(10):
-            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)
+        # 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")
@@ -615,6 +633,34 @@ class MulticoreRunAllHaltOne(GdbTest):
         time.sleep(1)
         self.gdb.p("buf", fmt="")
 
+class MulticoreRtosSwitchActiveHartTest(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 self.gdb.one_hart_per_gdb():
+            return 'not_applicable'
+
+        # 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")
+
+        # 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(GdbSingleHartTest):
     compile_args = ("programs/step.S", )
 
@@ -634,6 +680,29 @@ class StepTest(GdbSingleHartTest):
             pc = self.gdb.p("$pc")
             assertEqual("%x" % (pc - main_address), "%x" % expected)
 
+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):
@@ -674,7 +743,8 @@ class TriggerLoadAddressInstant(TriggerTest):
         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])
@@ -701,7 +771,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("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])