aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2018-01-05 14:25:57 -0800
committerTim Newsome <tim@sifive.com>2018-01-05 14:25:57 -0800
commitc2e2e06836b597d983c98f33a7ea38e8e4889935 (patch)
tree054a2cf206a8f78303a110cf6114e57d12a3bb11
parent03447f08863f1f25243c52a2139d0c968157a9f8 (diff)
downloadriscv-tests-c2e2e06836b597d983c98f33a7ea38e8e4889935.zip
riscv-tests-c2e2e06836b597d983c98f33a7ea38e8e4889935.tar.gz
riscv-tests-c2e2e06836b597d983c98f33a7ea38e8e4889935.tar.bz2
Add test for multicore failure
Specifically, make sure that after resuming all cores, and halting core 0, that OpenOCD's poll() doesn't mess up the currently selected hart to the point where memory accesses intended for core 0 go to core 1.
-rwxr-xr-xdebug/gdbserver.py28
-rw-r--r--debug/testlib.py17
2 files changed, 40 insertions, 5 deletions
diff --git a/debug/gdbserver.py b/debug/gdbserver.py
index 8104fed..bf27950 100755
--- a/debug/gdbserver.py
+++ b/debug/gdbserver.py
@@ -574,6 +574,34 @@ class MulticoreRunHaltStepiTest(GdbTest):
stepped_pc = self.gdb.p("$pc")
assertNotEqual(pc, stepped_pc)
+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(GdbTest):
compile_args = ("programs/step.S", )
diff --git a/debug/testlib.py b/debug/testlib.py
index 94ee83e..c6bf59c 100644
--- a/debug/testlib.py
+++ b/debug/testlib.py
@@ -390,12 +390,18 @@ class Gdb(object):
hartid = max(self.harts) + 1
else:
hartid = 0
- self.harts[hartid] = (child, t)
+ # solo: True iff this is the only thread on this child
+ self.harts[hartid] = {'child': child,
+ 'thread': t,
+ 'solo': len(threads) == 1}
def __del__(self):
for child in self.children:
del child
+ def one_hart_per_gdb(self):
+ return all(h['solo'] for h in self.harts.itervalues())
+
def lognames(self):
return [logfile.name for logfile in self.logfiles]
@@ -403,10 +409,11 @@ class Gdb(object):
self.active_child = child
def select_hart(self, hart):
- child, thread = self.harts[hart.id]
- self.select_child(child)
- output = self.command("thread %s" % thread.id)
- assert "Unknown" not in output
+ h = self.harts[hart.id]
+ self.select_child(h['child'])
+ if not h['solo']:
+ output = self.command("thread %s" % h['thread'].id, timeout=10)
+ assert "Unknown" not in output
def push_state(self):
self.stack.append({