From: Tim Newsome Date: Wed, 13 Sep 2017 01:48:44 +0000 (-0700) Subject: Test debugging code with interrupts. X-Git-Url: https://git.libre-soc.org/?p=riscv-tests.git;a=commitdiff_plain;h=6c2ad1c5c27f5e19e005541f7665a32814d32e0f Test debugging code with interrupts. --- diff --git a/debug/gdbserver.py b/debug/gdbserver.py index 21eea4e..9fedbca 100755 --- a/debug/gdbserver.py +++ b/debug/gdbserver.py @@ -419,6 +419,49 @@ class UserInterrupt(DebugTest): self.gdb.p("i=0") self.exit() +class InterruptTest(GdbSingleHartTest): + compile_args = ("programs/interrupt.c",) + + def early_applicable(self): + return self.target.supports_clint_mtime + + def setup(self): + self.gdb.load() + + def test(self): + self.gdb.b("main") + output = self.gdb.c() + assertIn(" main ", output) + self.gdb.b("trap_entry") + output = self.gdb.c() + assertIn(" trap_entry ", output) + assertEqual(self.gdb.p("$mip") & 0x80, 0x80) + assertEqual(self.gdb.p("interrupt_count"), 0) + # You'd expect local to still be 0, but it looks like spike doesn't + # jump to the interrupt handler immediately after the write to + # mtimecmp. + assertLess(self.gdb.p("local"), 1000) + self.gdb.command("delete breakpoints") + for _ in range(10): + self.gdb.c(wait=False) + time.sleep(2) + self.gdb.interrupt() + interrupt_count = self.gdb.p("interrupt_count") + local = self.gdb.p("local") + if interrupt_count > 1000 and \ + local > 1000: + return + + assertGreater(interrupt_count, 1000) + assertGreater(local, 1000) + + def postMortem(self): + GdbSingleHartTest.postMortem(self) + self.gdb.p("*((long long*) 0x200bff8)") + self.gdb.p("*((long long*) 0x2004000)") + self.gdb.p("interrupt_count") + self.gdb.p("local") + class MulticoreRegTest(GdbTest): compile_args = ("programs/infinite_loop.S", "-DMULTICORE") diff --git a/debug/programs/entry.S b/debug/programs/entry.S index a2ea955..97b62a3 100755 --- a/debug/programs/entry.S +++ b/debug/programs/entry.S @@ -1,8 +1,6 @@ #include "encoding.h" -// Enough stack to store every register in case a trap handler is executed, -// plus 33 more values. -#define STACK_SIZE (64 * XLEN / 8) +#define STACK_SIZE (74 * XLEN / 8) #if XLEN == 64 # define LREG ld diff --git a/debug/programs/init.c b/debug/programs/init.c index 9933c23..8b047de 100644 --- a/debug/programs/init.c +++ b/debug/programs/init.c @@ -17,7 +17,7 @@ void enable_timer_interrupts() set_csr(mstatus, MSTATUS_MIE); } -void handle_trap(unsigned int mcause, unsigned int mepc, unsigned int sp) +void handle_trap(unsigned int mcause, void *mepc, void *sp) { unsigned hartid = csr_read(mhartid); if (trap_handler[hartid]) { diff --git a/debug/programs/interrupt.c b/debug/programs/interrupt.c new file mode 100644 index 0000000..c2dd5ec --- /dev/null +++ b/debug/programs/interrupt.c @@ -0,0 +1,32 @@ +#include "init.h" +#include "encoding.h" + +static volatile unsigned interrupt_count; +static volatile unsigned local; + +static unsigned delta = 0x100; +void *increment_count(unsigned hartid, unsigned mcause, void *mepc, void *sp) +{ + interrupt_count++; + // There is no guarantee that the interrupt is cleared immediately when + // MTIMECMP is written, so stick around here until that happens. + while (csr_read(mip) & MIP_MTIP) { + MTIMECMP[hartid] = MTIME + delta; + } + return mepc; +} + +int main() +{ + interrupt_count = 0; + local = 0; + unsigned hartid = csr_read(mhartid); + + set_trap_handler(increment_count); + MTIMECMP[hartid] = MTIME - 1; + enable_timer_interrupts(); + + while (1) { + local++; + } +} diff --git a/debug/targets.py b/debug/targets.py index db8d917..d661d14 100644 --- a/debug/targets.py +++ b/debug/targets.py @@ -67,6 +67,9 @@ class Target(object): # before starting the test. gdb_setup = [] + # Supports mtime at 0x2004000 + supports_clint_mtime = True + # Internal variables: directory = None temporary_files = []