Implement resume (untested).
authorTim Newsome <tim@sifive.com>
Wed, 15 Feb 2017 23:45:20 +0000 (15:45 -0800)
committerTim Newsome <tim@sifive.com>
Wed, 15 Feb 2017 23:45:20 +0000 (15:45 -0800)
riscv/debug_defines.h
riscv/debug_module.cc
riscv/debug_module.h
riscv/opcodes.h

index 59fa344eaa9c2a3660ae5176dcfa513fbe0a11bc..2a78bdf0a19faf1171aef9d23c1494f966668ec3 100644 (file)
 #define AC_ACCESS_REGISTER_POSTEXEC_LENGTH  1
 #define AC_ACCESS_REGISTER_POSTEXEC         (0x1 << AC_ACCESS_REGISTER_POSTEXEC_OFFSET)
 /*
-* 0: Copy data from \Rdatazero into the specified register.
+* 0: Copy data from {\tt arg0} portion of {\tt data} into the
+* specified register.
 *
-* 1: Copy data from the specified register into \Rdatazero.
-*
-* (If XLEN is greater than 32, more {\tt data} registers are involved.)
+* 1: Copy data from the specified register into {\tt arg0} portion
+* of {\tt data}.
  */
 #define AC_ACCESS_REGISTER_WRITE_OFFSET     16
 #define AC_ACCESS_REGISTER_WRITE_LENGTH     1
 #define CSR_PRIV_PRV                        (0x3 << CSR_PRIV_PRV_OFFSET)
 #define DMI_DMCONTROL                       0x00
 /*
-* Halt request signal for the hart selected by \Fhartsel.  Writes
-* apply to the new value of \Fhartsel.
+* Halt request signal for the hart selected by \Fhartsel. When 1, the
+* hart will halt if it's not currently halted.
+* Setting both \Fhaltreq and \Fresumereq leads to undefined behavior.
+*
+* Writes apply to the new value of \Fhartsel.
  */
 #define DMI_DMCONTROL_HALTREQ_OFFSET        31
 #define DMI_DMCONTROL_HALTREQ_LENGTH        1
 #define DMI_DMCONTROL_HALTREQ               (0x1 << DMI_DMCONTROL_HALTREQ_OFFSET)
 /*
-* This bit controls the reset signal from the DM to the rest of the
-* system. To perform a reset the debugger writes 1, and then writes 0
-* to deassert the reset.
- */
-#define DMI_DMCONTROL_RESET_OFFSET          30
-#define DMI_DMCONTROL_RESET_LENGTH          1
-#define DMI_DMCONTROL_RESET                 (0x1 << DMI_DMCONTROL_RESET_OFFSET)
-/*
-* This bit serves as a reset signal for the Debug Module itself.
-* When 0, the module is held in reset. When 1, it functions normally.
-* No other mechanism should exist that may result in resetting the
-* Debug Module after power up, including the platform's system reset
-* or Debug Transport reset signals.
-*
-* A debugger should pulse this bit low to ensure that the Debug
-* Module is fully reset and ready to use.
+* Resume request signal for the hart selected by \Fhartsel. When 1,
+* the hart will resume if it's currently halted.
+* Setting both \Fhaltreq and \Fresumereq leads to undefined behavior.
 *
-* Implementations may use this bit to aid debugging, for example by
-* preventing the Debug Module from being power gated while debugging
-* is active.
+* Writes apply to the new value of \Fhartsel.
  */
-#define DMI_DMCONTROL_DMACTIVE_OFFSET       29
-#define DMI_DMCONTROL_DMACTIVE_LENGTH       1
-#define DMI_DMCONTROL_DMACTIVE              (0x1 << DMI_DMCONTROL_DMACTIVE_OFFSET)
+#define DMI_DMCONTROL_RESUMEREQ_OFFSET      30
+#define DMI_DMCONTROL_RESUMEREQ_LENGTH      1
+#define DMI_DMCONTROL_RESUMEREQ             (0x1 << DMI_DMCONTROL_RESUMEREQ_OFFSET)
 /*
 * The status of the currently selected hart.
 *
 #define DMI_DMCONTROL_HARTSEL_LENGTH        10
 #define DMI_DMCONTROL_HARTSEL               (0x3ff << DMI_DMCONTROL_HARTSEL_OFFSET)
 /*
+* This bit serves as a reset signal for the Debug Module itself.
+* When 0, the module is held in reset. When 1, it functions normally.
+* No other mechanism should exist that may result in resetting the
+* Debug Module after power up, including the platform's system reset
+* or Debug Transport reset signals.
+*
+* A debugger should pulse this bit low to ensure that the Debug
+* Module is fully reset and ready to use.
+*
+* Implementations may use this bit to aid debugging, for example by
+* preventing the Debug Module from being power gated while debugging
+* is active.
+ */
+#define DMI_DMCONTROL_DMACTIVE_OFFSET       9
+#define DMI_DMCONTROL_DMACTIVE_LENGTH       1
+#define DMI_DMCONTROL_DMACTIVE              (0x1 << DMI_DMCONTROL_DMACTIVE_OFFSET)
+/*
+* This bit controls the reset signal from the DM to the rest of the
+* system. To perform a reset the debugger writes 1, and then writes 0
+* to deassert the reset.
+ */
+#define DMI_DMCONTROL_RESET_OFFSET          8
+#define DMI_DMCONTROL_RESET_LENGTH          1
+#define DMI_DMCONTROL_RESET                 (0x1 << DMI_DMCONTROL_RESET_OFFSET)
+/*
 * 0 when authentication is required before using the DM.  1 when the
 * authentication check has passed. On components that don't implement
 * authentication, this bit must be preset as 1.
 *
 * 3: There was some other error (eg. alignment).
 *
-* 4: The system bus master was busy when a one of the {\tt sbaddress} or
-* {\tt sbdata} registers was written.
+* 4: The system bus master was busy when a one of the
+* {\tt sbaddress} or {\tt sbdata} registers was written,
+* or the {\tt sbdata} register was read when it had
+* stale data.
  */
 #define DMI_SBCS_SBERROR_OFFSET             12
 #define DMI_SBCS_SBERROR_LENGTH             3
index f672a892bcc0a38ef033a446d69e94eecf48e137..df3f1f995f435297d86dfb0dda1cfdd14ab0237d 100644 (file)
@@ -111,7 +111,7 @@ void debug_module_t::add_device(bus_t *bus) {
 
 bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
 {
-  D(fprintf(stderr, "load 0x%lx bytes at 0x%lx\n",
+  D(fprintf(stderr, "debug_module_t load 0x%lx bytes at 0x%lx\n",
         len, addr));
   addr = DEBUG_START + addr;
 
@@ -140,6 +140,12 @@ bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
 
   if (addr >= DEBUG_ROM_CODE &&
       addr < DEBUG_ROM_CODE + DEBUG_ROM_CODE_SIZE) {
+
+    if (read32(debug_rom_code, 0) == dret()) {
+      abstractcs.busy = false;
+      halted[dmcontrol.hartsel] = false;
+    }
+
     memcpy(bytes, debug_rom_code + addr - DEBUG_ROM_CODE, len);
     return true;
   }
@@ -363,6 +369,7 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value)
           dmcontrol.dmactive = get_field(value, DMI_DMCONTROL_DMACTIVE);
           if (dmcontrol.dmactive) {
             dmcontrol.haltreq = get_field(value, DMI_DMCONTROL_HALTREQ);
+            dmcontrol.resumereq = get_field(value, DMI_DMCONTROL_RESUMEREQ);
             dmcontrol.reset = get_field(value, DMI_DMCONTROL_RESET);
             dmcontrol.hartsel = get_field(value, DMI_DMCONTROL_HARTSEL);
           } else {
@@ -371,6 +378,12 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value)
           processor_t *proc = current_proc();
           if (proc) {
             proc->halt_request = dmcontrol.haltreq;
+            if (dmcontrol.resumereq) {
+              write32(debug_rom_code, 0, dret());
+              write32(debug_rom_entry, dmcontrol.hartsel,
+                  jal(ZERO, DEBUG_ROM_CODE - (DEBUG_ROM_ENTRY + 4 * dmcontrol.hartsel)));
+              abstractcs.busy = true;
+            }
           }
         }
         return true;
index fdeaaaccb86c8518f5029fab989ca97739393f3d..7d9b3aa646bed3a9534017a9e8ed90a0255f5769 100644 (file)
@@ -10,6 +10,7 @@ class sim_t;
 
 typedef struct {
   bool haltreq;
+  bool resumereq;
   bool reset;
   bool dmactive;
   enum {
index eb76455c3fbb5cde692a2016588f06ef5ca90f6e..34c089ebb769a1c74d672034941fc0888b8e6243 100644 (file)
@@ -168,6 +168,9 @@ static uint32_t ebreak(void) { return MATCH_EBREAK; }
 static uint32_t ebreak_c(void) __attribute__ ((unused));
 static uint32_t ebreak_c(void) { return MATCH_C_EBREAK; }
 
+static uint32_t dret(void) __attribute__ ((unused));
+static uint32_t dret(void) { return MATCH_DRET; }
+
 static uint32_t fence_i(void) __attribute__ ((unused));
 static uint32_t fence_i(void)
 {