diff --git a/src/emulate.c b/src/emulate.c index 33bee74a7..9f05b4fc5 100644 --- a/src/emulate.c +++ b/src/emulate.c @@ -236,6 +236,7 @@ void rv_debug(riscv_t *rv) } rv->breakpoint_map = breakpoint_map_new(); + rv->is_interrupt = false; if (!gdbstub_run(&rv->gdbstub, (void *) rv)) return; diff --git a/src/gdbstub.c b/src/gdbstub.c index 70c1d8a6c..dc12f4100 100644 --- a/src/gdbstub.c +++ b/src/gdbstub.c @@ -55,18 +55,26 @@ static void rv_write_mem(void *args, size_t addr, size_t len, void *val) rv->io.mem_write_b(rv, addr + i, *((uint8_t *) val + i)); } +static inline bool rv_is_interrupt(riscv_t *rv) +{ + return __atomic_load_n(&rv->is_interrupt, __ATOMIC_RELAXED); +} + static gdb_action_t rv_cont(void *args) { riscv_t *rv = (riscv_t *) args; const uint32_t cycles_per_step = 1; - for (; !rv_has_halted(rv);) { + for (; !rv_has_halted(rv) && !rv_is_interrupt(rv);) { if (breakpoint_map_find(rv->breakpoint_map, rv_get_pc(rv))) break; rv_step(rv, cycles_per_step); } + /* Clear the interrupt if it's pending */ + __atomic_store_n(&rv->is_interrupt, false, __ATOMIC_RELAXED); + return ACT_RESUME; } @@ -97,6 +105,14 @@ static bool rv_del_bp(void *args, size_t addr, bp_type_t type) return true; } +static void rv_on_interrupt(void *args) +{ + riscv_t *rv = (riscv_t *) args; + + /* Notify the emulator to break out the for loop in rv_cont */ + __atomic_store_n(&rv->is_interrupt, true, __ATOMIC_RELAXED); +} + const struct target_ops gdbstub_ops = { .read_reg = rv_read_reg, .write_reg = rv_write_reg, @@ -106,4 +122,5 @@ const struct target_ops gdbstub_ops = { .stepi = rv_stepi, .set_bp = rv_set_bp, .del_bp = rv_del_bp, + .on_interrupt = rv_on_interrupt, }; diff --git a/src/mini-gdbstub b/src/mini-gdbstub index 4acb4c5d7..2bc7f1972 160000 --- a/src/mini-gdbstub +++ b/src/mini-gdbstub @@ -1 +1 @@ -Subproject commit 4acb4c5d79e02532c642509f476f975465632863 +Subproject commit 2bc7f1972eb1b11bd13d50cfe0eebf00fe15b06f diff --git a/src/riscv_private.h b/src/riscv_private.h index 680dd2cc0..39c8ffc9b 100644 --- a/src/riscv_private.h +++ b/src/riscv_private.h @@ -89,6 +89,10 @@ struct riscv_internal { /* GDB instruction breakpoint */ breakpoint_map_t breakpoint_map; + + /* The flag to notify interrupt from GDB client: it should + * be accessed by atomic operation when starting the GDBSTUB. */ + bool is_interrupt; #endif #if RV32_HAS(EXT_F)