Save/restore mstatus, too.
authorTim Newsome <tim@sifive.com>
Tue, 3 May 2016 17:55:00 +0000 (10:55 -0700)
committerTim Newsome <tim@sifive.com>
Mon, 23 May 2016 19:12:11 +0000 (12:12 -0700)
Also read DCSR, which will be useful to figure out why we halted.

riscv/gdbserver.cc
riscv/gdbserver.h

index 15f72e84d74f69e699cc826c96ee20cad9375321..113d10d2bc8c6b15bc5b3d3a1a4e47cb0b153033 100644 (file)
@@ -272,14 +272,43 @@ class halt_op_t : public operation_t
       if (state == READ_DPC) {
         gs.saved_dpc = ((uint64_t) gs.read_debug_ram(1) << 32) | gs.read_debug_ram(0);
         gs.saved_mbadaddr = ((uint64_t) gs.read_debug_ram(3) << 32) | gs.read_debug_ram(2);
+
         gs.write_debug_ram(0, csrr(S0, CSR_MCAUSE));
-        gs.write_debug_ram(1, sd(S0, 0, (uint16_t) DEBUG_RAM_START + 16));
-        gs.write_debug_ram(2, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*2))));
+        gs.write_debug_ram(1, sd(S0, 0, (uint16_t) DEBUG_RAM_START + 0));
+        gs.write_debug_ram(2, csrr(S0, CSR_MSTATUS));
+        gs.write_debug_ram(3, sd(S0, 0, (uint16_t) DEBUG_RAM_START + 8));
+        gs.write_debug_ram(4, csrr(S0, CSR_DCSR));
+        gs.write_debug_ram(5, sd(S0, 0, (uint16_t) DEBUG_RAM_START + 16));
+        gs.write_debug_ram(6, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*6))));
         gs.set_interrupt(0);
-        state = READ_CAUSE;
+        state = READ_MCAUSE;
         return false;
+
       } else {
         gs.saved_mcause = ((uint64_t) gs.read_debug_ram(1) << 32) | gs.read_debug_ram(0);
+        gs.saved_mstatus = ((uint64_t) gs.read_debug_ram(3) << 32) | gs.read_debug_ram(2);
+        gs.dcsr = ((uint64_t) gs.read_debug_ram(5) << 32) | gs.read_debug_ram(4);
+
+#if 0
+        // TODO: This scheme doesn't work, because we're unable to write to eg.
+        // 0x108 to clear debug int with mstatus configured this way.
+
+        // Set mstatus.mprv, and mstatus.mpp to dcsr.prv.
+        // This ensures that memory accesses act as they would in whatever mode
+        // the processor was in when we interrupted it. A fancier debugger
+        // might walk page tables itself and perform its own address
+        // translation.
+        reg_t mstatus = gs.saved_mstatus;
+        mstatus = set_field(mstatus, MSTATUS_MPRV, 1);
+        mstatus = set_field(mstatus, MSTATUS_MPP, get_field(gs.dcsr, DCSR_PRV));
+        gs.write_debug_ram(0, ld(S0, 0, (uint16_t) DEBUG_RAM_START + 16));
+        gs.write_debug_ram(1, csrw(S0, CSR_MSTATUS));
+        gs.write_debug_ram(2, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*2))));
+        gs.write_debug_ram(4, mstatus);
+        gs.write_debug_ram(5, mstatus >> 32);
+        gs.set_interrupt(0);
+        state = WRITE_MSTATUS;
+#endif
         return true;
       }
     }
@@ -287,7 +316,8 @@ class halt_op_t : public operation_t
   private:
     enum {
       READ_DPC,
-      READ_CAUSE
+      READ_MCAUSE,
+      WRITE_MSTATUS
     } state;
 };
 
@@ -319,6 +349,17 @@ class continue_op_t : public operation_t
         gs.set_interrupt(0);
         state = WRITE_MBADADDR;
         return false;
+
+      } else if (state == WRITE_MBADADDR) {
+        gs.write_debug_ram(0, ld(S0, 0, (uint16_t) DEBUG_RAM_START+16));
+        gs.write_debug_ram(1, csrw(S0, CSR_MSTATUS));
+        gs.write_debug_ram(2, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*2))));
+        gs.write_debug_ram(4, gs.saved_mstatus);
+        gs.write_debug_ram(5, gs.saved_mstatus >> 32);
+        gs.set_interrupt(0);
+        state = WRITE_MSTATUS;
+        return false;
+
       } else {
         gs.write_debug_ram(0, ld(S0, 0, (uint16_t) DEBUG_RAM_START+16));
         gs.write_debug_ram(1, csrw(S0, CSR_MCAUSE));
@@ -334,7 +375,8 @@ class continue_op_t : public operation_t
   private:
     enum {
       WRITE_DPC,
-      WRITE_MBADADDR
+      WRITE_MBADADDR,
+      WRITE_MSTATUS
     } state;
 };
 
index acd68b3b4351b176eb8ac9a39138b8584f3b2c0d..bdf7bae77df9262e801fb0f5367c8ee3c39fb311 100644 (file)
@@ -137,6 +137,8 @@ public:
   reg_t saved_dpc;
   reg_t saved_mbadaddr;
   reg_t saved_mcause;
+  reg_t saved_mstatus;
+  reg_t dcsr;
 
 private:
   sim_t *sim;