aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2023-07-06 14:41:39 -0700
committerTim Newsome <tim@sifive.com>2023-07-17 09:35:00 -0700
commit995fa259b95f5c1b77fe768a00a7d444162fb36f (patch)
tree77a1adf25d658c0eb242fc30a4fe6ac77c7b7675
parentba831d02bdb4249ef744bd04da6c912680c7b66e (diff)
downloadriscv-tests-995fa259b95f5c1b77fe768a00a7d444162fb36f.zip
riscv-tests-995fa259b95f5c1b77fe768a00a7d444162fb36f.tar.gz
riscv-tests-995fa259b95f5c1b77fe768a00a7d444162fb36f.tar.bz2
debug: CeaseRunTest -> UnavailableRunTest
Use new spike mechanism to test OpenOCD behavior when the current hart becomes unavailable while running. Create ThreadTerminated exception.
-rwxr-xr-xdebug/gdbserver.py21
-rw-r--r--debug/testlib.py5
2 files changed, 23 insertions, 3 deletions
diff --git a/debug/gdbserver.py b/debug/gdbserver.py
index bf04f2e..ad85e34 100755
--- a/debug/gdbserver.py
+++ b/debug/gdbserver.py
@@ -20,6 +20,7 @@ from testlib import GdbTest, GdbSingleHartTest, TestFailed
from testlib import TestNotApplicable, CompileError
from testlib import UnknownThread
from testlib import CouldNotReadRegisters, CommandException
+from testlib import ThreadTerminated
MSTATUS_UIE = 0x00000001
MSTATUS_SIE = 0x00000002
@@ -1879,11 +1880,12 @@ class CeaseStepiTest(ProgramTest):
except CouldNotReadRegisters:
pass
-class CeaseRunTest(ProgramTest):
+class UnavailableRunTest(ProgramTest):
"""Test that we work correctly when the hart we're debugging ceases to
respond."""
def early_applicable(self):
- return self.hart.support_cease
+ return self.hart.support_cease or \
+ self.target.support_unavailable_control
def test(self):
self.gdb.b("main")
@@ -1891,10 +1893,23 @@ class CeaseRunTest(ProgramTest):
assertIn("Breakpoint", output)
assertIn("main", output)
- self.gdb.p("$pc=precease")
+ if self.target.support_unavailable_control:
+ self.gdb.p("$pc=loop_forever")
+ else:
+ self.gdb.p("$pc=cease")
self.gdb.c(wait=False)
+ if self.target.support_unavailable_control:
+ self.server.wait_until_running([self.hart])
+ self.server.command(
+ f"riscv dmi_write 0x1f 0x{(~(1<<self.hart.id))&0x3:x}")
self.gdb.expect(r"\S+ became unavailable.")
self.gdb.interrupt()
+ # gdb might automatically switch to the available hart.
+ try:
+ self.gdb.select_hart(self.hart)
+ except ThreadTerminated:
+ # GDB sees that the thread is gone. Count this as success.
+ return
try:
self.gdb.p("$pc")
assert False, ("Registers shouldn't be accessible when the hart is "
diff --git a/debug/testlib.py b/debug/testlib.py
index fd9882a..63cc49c 100644
--- a/debug/testlib.py
+++ b/debug/testlib.py
@@ -555,6 +555,9 @@ class UnknownThread(Exception):
def __init__(self, explanation):
Exception.__init__(self, explanation)
+class ThreadTerminated(Exception):
+ pass
+
Thread = collections.namedtuple('Thread', ('id', 'description', 'target_id',
'name', 'frame'))
@@ -762,6 +765,8 @@ class Gdb:
output = self.command(f"thread {h['thread'].id}", ops=5)
if "Unknown" in output:
raise UnknownThread(output)
+ if f"Thread ID {h['thread'].id} has terminated" in output:
+ raise ThreadTerminated(output)
def push_state(self):
self.stack.append({