aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xdebug/gdbserver.py100
-rw-r--r--debug/testlib.py4
2 files changed, 80 insertions, 24 deletions
diff --git a/debug/gdbserver.py b/debug/gdbserver.py
index 1280878..1a74a95 100755
--- a/debug/gdbserver.py
+++ b/debug/gdbserver.py
@@ -66,6 +66,20 @@ def srec_parse(line):
if typ == b'S0':
# header
return 0, 0, 0
+ elif typ == b'S1':
+ # data with 16-bit address
+ address = int(line[4:8], 16)
+ for i in range(4, count+1):
+ data += f"{int(line[2 * i:2 * i + 2], 16):c}"
+ # Ignore the checksum.
+ return 1, address, data
+ elif typ == b'S2':
+ # data with 24-bit address
+ address = int(line[4:10], 16)
+ for i in range(5, count+1):
+ data += f"{int(line[2 * i:2 * i + 2], 16):c}"
+ # Ignore the checksum.
+ return 2, address, data
elif typ == b'S3':
# data with 32-bit address
# Any higher bits were chopped off.
@@ -74,9 +88,9 @@ def srec_parse(line):
data += f"{int(line[2 * i:2 * i + 2], 16):c}"
# Ignore the checksum.
return 3, address, data
- elif typ == b'S7':
+ elif typ in (b'S7', b'S8', b'S9'):
# ignore execution start field
- return 7, 0, 0
+ return int(typ[-1]), 0, 0
else:
raise TestFailed(f"Unsupported SREC type {typ!r}.")
@@ -389,7 +403,7 @@ class MemTestBlock(GdbTest):
highest_seen = 0
for line in b:
record_type, address, line_data = srec_parse(line)
- if record_type == 3:
+ if record_type in (1, 2, 3):
offset = address - (self.hart.ram & 0xffffffff)
written_data = data[offset:offset+len(line_data)]
highest_seen += len(line_data)
@@ -676,6 +690,47 @@ class HwbpManual(DebugTest):
return self.target.support_manual_hwbp and \
self.hart.instruction_hardware_breakpoint_count >= 1
+ # TODO: This can be removed once
+ # https://github.com/riscv-collab/riscv-openocd/pull/1111
+ # is merged.
+ def check_reserve_trigger_support(self):
+ not_supp_msg = "RESERVE_TRIGGER_NOT_SUPPORTED"
+ if not_supp_msg in self.gdb.command(
+ "monitor if [catch {riscv reserve_trigger 0 on} e] {echo " +
+ not_supp_msg + "}").splitlines():
+ raise TestNotApplicable
+
+ def set_manual_trigger(self, tdata1, tdata2):
+ for tselect in itertools.count(0):
+ self.gdb.p(f"$tselect={tselect}")
+ if self.gdb.p("$tselect") != tselect:
+ raise TestNotApplicable
+
+ self.gdb.command(
+ f"monitor riscv reserve_trigger {tselect} on")
+
+ # Need to disable the trigger before writing tdata2
+ self.gdb.p("$tdata1=0")
+ # Need to write a valid value to tdata2 before writing tdata1
+ self.gdb.p(f"$tdata2=0x{tdata2:x}")
+ self.gdb.p(f"$tdata1=0x{tdata1:x}")
+
+ tdata2_rb = self.gdb.p("$tdata2")
+ tdata1_rb = self.gdb.p("$tdata1")
+ if tdata1_rb == tdata1 and tdata2_rb == tdata2:
+ return tselect
+
+ type_rb = tdata1_rb & MCONTROL_TYPE(self.hart.xlen)
+ type_none = set_field(0, MCONTROL_TYPE(self.hart.xlen),
+ MCONTROL_TYPE_NONE)
+ if type_rb == type_none:
+ raise TestNotApplicable
+
+ self.gdb.p("$tdata1=0")
+ self.gdb.command(
+ f"monitor riscv reserve_trigger {tselect} off")
+ assert False
+
def test(self):
if not self.hart.honors_tdata1_hmode:
# Run to main before setting the breakpoint, because startup code
@@ -684,6 +739,12 @@ class HwbpManual(DebugTest):
self.gdb.c()
self.gdb.command("delete")
+
+ # TODO: This can be removed once
+ # https://github.com/riscv-collab/riscv-openocd/pull/1111
+ # is merged.
+ self.check_reserve_trigger_support()
+
#self.gdb.hbreak("rot13")
tdata1 = MCONTROL_DMODE(self.hart.xlen)
tdata1 = set_field(tdata1, MCONTROL_TYPE(self.hart.xlen),
@@ -692,26 +753,9 @@ class HwbpManual(DebugTest):
tdata1 = set_field(tdata1, MCONTROL_MATCH, MCONTROL_MATCH_EQUAL)
tdata1 |= MCONTROL_M | MCONTROL_S | MCONTROL_U | MCONTROL_EXECUTE
- tselect = 0
- while True:
- self.gdb.p(f"$tselect={tselect}")
- value = self.gdb.p("$tselect")
- if value != tselect:
- raise TestNotApplicable
- # Need to disable the trigger before writing tdata2
- self.gdb.p("$tdata1=0")
- # Need to write a valid value to tdata2 before writing tdata1
- self.gdb.p("$tdata2=&rot13")
- self.gdb.p(f"$tdata1=0x{tdata1:x}")
- value = self.gdb.p("$tdata1")
- if value == tdata1:
- break
- if value & MCONTROL_TYPE(self.hart.xlen) == MCONTROL_TYPE_NONE:
- raise TestNotApplicable
- self.gdb.p("$tdata1=0")
- tselect += 1
+ tdata2 = self.gdb.p("&rot13")
- self.gdb.command(f"monitor riscv reserve_trigger {tselect} on")
+ tselect = self.set_manual_trigger(tdata1, tdata2)
# The breakpoint should be hit exactly 2 times.
for _ in range(2):
@@ -728,14 +772,22 @@ class HwbpManual(DebugTest):
self.gdb.c()
before = self.gdb.p("$pc")
assertEqual(before, self.gdb.p("&crc32a"))
+
self.gdb.stepi()
- after = self.gdb.p("$pc")
- assertNotEqual(before, after)
+ assertEqual(before, self.gdb.p("$pc"),
+ "OpenOCD shouldn't disable a reserved trigger.")
# Remove the manual HW breakpoint.
assertEqual(tselect, self.gdb.p("$tselect"))
self.gdb.p("$tdata1=0")
+ self.gdb.stepi()
+ assertNotEqual(before, self.gdb.p("$pc"),
+ "OpenOCD should be able to step from a removed BP.")
+
+ self.gdb.command(
+ f"monitor riscv reserve_trigger {tselect} off")
+
self.gdb.b("_exit")
self.exit()
diff --git a/debug/testlib.py b/debug/testlib.py
index 0279b08..cf62863 100644
--- a/debug/testlib.py
+++ b/debug/testlib.py
@@ -65,6 +65,7 @@ def compile(args): # pylint: disable=redefined-builtin
class Spike:
# pylint: disable=too-many-instance-attributes
# pylint: disable=too-many-locals
+ # pylint: disable=too-many-positional-arguments
def __init__(self, target, halted=False, timeout=None, with_jtag_gdb=True,
isa=None, progbufsize=None, dmi_rti=None, abstract_rti=None,
support_hasel=True, support_abstract_csr=True,
@@ -300,6 +301,8 @@ class VcsSim:
class Openocd:
# pylint: disable=too-many-instance-attributes
# pylint: disable-next=consider-using-with
+ # pylint: disable=too-many-positional-arguments
+ # pylint: disable=consider-using-with
logfile = tempfile.NamedTemporaryFile(prefix='openocd', suffix='.log')
logname = logfile.name
@@ -717,6 +720,7 @@ class Gdb:
11, 149, 107, 163, 73, 47, 43, 173, 7, 109, 101, 103, 191, 2, 139,
97, 193, 157, 3, 29, 79, 113, 5, 89, 19, 37, 71, 179, 59, 137, 53)
+ # pylint: disable=too-many-positional-arguments
def __init__(self, target, ports, cmd=None, timeout=60, binaries=None,
logremote=False):
assert ports