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(1)
+ 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()
#include <stdint.h>
+#include "init.h"
+
typedef struct {
int counter;
} atomic_t;
return c;
}
-#define csr_read(csr) \
-({ \
- register unsigned long __v; \
- __asm__ __volatile__ ("csrr %0, " #csr \
- : "=r" (__v)); \
- __v; \
-})
-
static inline void mb(void)
{
__asm__ __volatile__ ("fence");
static atomic_t buf_lock = { .counter = 0 };
static char buf[32];
static int buf_initialized;
-static unsigned hart_count[2];
+static unsigned hart_count[NHARTS];
+static unsigned interrupt_count[NHARTS];
-static const char case_bit = 'a' - 'A';
-volatile int initialized;
+static unsigned delta = 0x100;
+void *increment_count(unsigned hartid, unsigned mcause, void *mepc, void *sp)
+{
+ interrupt_count[hartid]++;
+ MTIMECMP[hartid] = MTIME + delta;
+ return mepc;
+}
int main()
{
uint32_t hartid = csr_read(mhartid);
hart_count[hartid] = 0;
+ interrupt_count[hartid] = 0;
+
+ set_trap_handler(increment_count);
+ // Despite being memory-mapped, there appears to be one mtimecmp
+ // register per hart. The spec does not address this.
+ MTIMECMP[hartid] = MTIME + delta;
+ enable_timer_interrupts();
while (1) {
get_lock(&buf_lock);
- hart_count[hartid]++;
if (!buf_initialized) {
for (unsigned i = 0; i < sizeof(buf); i++) {
buf[i] = 'a' + ((i + hartid + hart_count[hartid]) % 26);
}
put_lock(&buf_lock);
+ hart_count[hartid]++;
}
}