Merge pull request #177 from riscv/debug_auth
authorTim Newsome <tim@sifive.com>
Thu, 8 Mar 2018 01:17:39 +0000 (17:17 -0800)
committerGitHub <noreply@github.com>
Thu, 8 Mar 2018 01:17:39 +0000 (17:17 -0800)
Add debug module authentication.

22 files changed:
debug_rom/Makefile
debug_rom/debug_rom.S
debug_rom/debug_rom_defines.h [deleted file]
riscv/debug_module.cc
riscv/debug_module.h
riscv/debug_rom_defines.h [new file with mode: 0644]
riscv/decode.h
riscv/execute.cc
riscv/insns/csrrc.h
riscv/insns/csrrci.h
riscv/insns/csrrs.h
riscv/insns/csrrsi.h
riscv/insns/csrrw.h
riscv/insns/csrrwi.h
riscv/interactive.cc
riscv/mmu.cc
riscv/mmu.h
riscv/processor.cc
riscv/processor.h
riscv/sim.cc
riscv/sim.h
softfloat/softfloat.mk.in

index 0a67ba102623b9861ea713ef973a447a4a3cebce..c5f2205de3bbf38baba4d600342f2277d409d098 100644 (file)
@@ -7,7 +7,7 @@ OBJCOPY = $(RISCV)/bin/riscv64-unknown-elf-objcopy
 COMPILE = $(CC) -nostdlib -nostartfiles -I.. -Tlink.ld
 
 ELFS = debug_rom
-DEPS = debug_rom.S link.ld debug_rom_defines.h
+DEPS = debug_rom.S link.ld ../riscv/debug_rom_defines.h ../riscv/encoding.h
 
 all: $(patsubst %,%.h,$(ELFS))
 
index 1342ee0520cd06b9b5be6216103308aaf0484f3c..28c7076fda5c17dc2f46d1cf2fead993ba92b6f5 100755 (executable)
@@ -1,8 +1,8 @@
 // See LICENSE.SiFive for license details.
 
 #include "riscv/encoding.h"
-#include "debug_rom_defines.h"
-        
+#include "riscv/debug_rom_defines.h"
+
         .option norvc
         .global entry
         .global exception
diff --git a/debug_rom/debug_rom_defines.h b/debug_rom/debug_rom_defines.h
deleted file mode 100644 (file)
index 616cf59..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// See LICENSE file for license details.
-
-#ifndef DEBUG_ROM_DEFINES_H
-#define DEBUG_ROM_DEFINES_H
-
-// These are implementation-specific addresses in the Debug Module
-#define DEBUG_ROM_HALTED    0x100
-#define DEBUG_ROM_GOING     0x104
-#define DEBUG_ROM_RESUMING  0x108
-#define DEBUG_ROM_EXCEPTION 0x10C
-
-// Region of memory where each hart has 1
-// byte to read.
-#define DEBUG_ROM_FLAGS 0x400
-#define DEBUG_ROM_FLAG_GO     0
-#define DEBUG_ROM_FLAG_RESUME 1
-
-// These needs to match the link.ld         
-#define DEBUG_ROM_WHERETO 0x300
-#define DEBUG_ROM_ENTRY   0x800
-#define DEBUG_ROM_TVEC    0x808
-
-#endif
index f10c866ed26e21cec0f949b82712929bce898eef..74c302300c8c14c3df029899d5122184f190aea7 100644 (file)
@@ -6,7 +6,7 @@
 #include "mmu.h"
 
 #include "debug_rom/debug_rom.h"
-#include "debug_rom/debug_rom_defines.h"
+#include "debug_rom_defines.h"
 
 #if 0
 #  define D(x) x
@@ -26,6 +26,10 @@ debug_module_t::debug_module_t(sim_t *sim, unsigned progbufsize, unsigned max_bu
   debug_abstract_start(debug_progbuf_start - debug_abstract_size*4),
   sim(sim)
 {
+  D(fprintf(stderr, "debug_data_start=0x%x\n", debug_data_start));
+  D(fprintf(stderr, "debug_progbuf_start=0x%x\n", debug_progbuf_start));
+  D(fprintf(stderr, "debug_abstract_start=0x%x\n", debug_abstract_start));
+
   program_buffer = new uint8_t[program_buffer_bytes];
 
   memset(halted, 0, sizeof(halted));
@@ -496,51 +500,110 @@ bool debug_module_t::perform_abstract_command()
       return true;
     }
 
+    unsigned i = 0;
     if (get_field(command, AC_ACCESS_REGISTER_TRANSFER)) {
 
-      if (regno < 0x1000 || regno >= 0x1020) {
-        abstractcs.cmderr = CMDERR_NOTSUP;
-        return true;
-      }
+      if (regno < 0x1000 && progbufsize < 2) {
+        // Make the debugger use the program buffer if it's available, so it
+        // can test both use cases.
+        write32(debug_abstract, i++, csrw(S0, CSR_DSCRATCH));
+
+        if (write) {
+          switch (size) {
+            case 2:
+              write32(debug_abstract, i++, lw(S0, ZERO, debug_data_start));
+              break;
+            case 3:
+              write32(debug_abstract, i++, ld(S0, ZERO, debug_data_start));
+              break;
+            default:
+              abstractcs.cmderr = CMDERR_NOTSUP;
+              return true;
+          }
+          write32(debug_abstract, i++, csrw(S0, regno));
+
+        } else {
+          write32(debug_abstract, i++, csrr(S0, regno));
+          switch (size) {
+            case 2:
+              write32(debug_abstract, i++, sw(S0, ZERO, debug_data_start));
+              break;
+            case 3:
+              write32(debug_abstract, i++, sd(S0, ZERO, debug_data_start));
+              break;
+            default:
+              abstractcs.cmderr = CMDERR_NOTSUP;
+              return true;
+          }
+        }
+        write32(debug_abstract, i++, csrr(S0, CSR_DSCRATCH));
+
+      } else if (regno >= 0x1000 && regno < 0x1020) {
+        unsigned regnum = regno - 0x1000;
+
+        switch (size) {
+          case 2:
+            if (write)
+              write32(debug_abstract, i++, lw(regnum, ZERO, debug_data_start));
+            else
+              write32(debug_abstract, i++, sw(regnum, ZERO, debug_data_start));
+            break;
+          case 3:
+            if (write)
+              write32(debug_abstract, i++, ld(regnum, ZERO, debug_data_start));
+            else
+              write32(debug_abstract, i++, sd(regnum, ZERO, debug_data_start));
+            break;
+          default:
+            abstractcs.cmderr = CMDERR_NOTSUP;
+            return true;
+        }
 
-      unsigned regnum = regno - 0x1000;
+      } else if (regno >= 0x1020 && regno < 0x1040) {
+        // Don't force the debugger to use progbuf if it exists, so the
+        // debugger has to make the decision not to use abstract commands to
+        // access 64-bit FPRs on 32-bit targets.
+        unsigned fprnum = regno - 0x1020;
+
+        if (write) {
+          switch (size) {
+            case 2:
+              write32(debug_abstract, i++, flw(fprnum, ZERO, debug_data_start));
+              break;
+            case 3:
+              write32(debug_abstract, i++, fld(fprnum, ZERO, debug_data_start));
+              break;
+            default:
+              abstractcs.cmderr = CMDERR_NOTSUP;
+              return true;
+          }
 
-      switch (size) {
-      case 2:
-        if (write)
-          write32(debug_abstract, 0, lw(regnum, ZERO, debug_data_start));
-        else
-          write32(debug_abstract, 0, sw(regnum, ZERO, debug_data_start));
-        break;
-      case 3:
-        if (write)
-          write32(debug_abstract, 0, ld(regnum, ZERO, debug_data_start));
-        else
-          write32(debug_abstract, 0, sd(regnum, ZERO, debug_data_start));
-        break;
-        /*
-          case 4:
-          if (write)
-          write32(debug_rom_code, 0, lq(regnum, ZERO, debug_data_start));
-          else
-          write32(debug_rom_code, 0, sq(regnum, ZERO, debug_data_start));
-          break;
-        */
-      default:
+        } else {
+          switch (size) {
+            case 2:
+              write32(debug_abstract, i++, fsw(fprnum, ZERO, debug_data_start));
+              break;
+            case 3:
+              write32(debug_abstract, i++, fsd(fprnum, ZERO, debug_data_start));
+              break;
+            default:
+              abstractcs.cmderr = CMDERR_NOTSUP;
+              return true;
+          }
+        }
+
+      } else {
         abstractcs.cmderr = CMDERR_NOTSUP;
         return true;
       }
-    } else {
-      //NOP
-      write32(debug_abstract, 0, addi(ZERO, ZERO, 0));
     }
 
     if (get_field(command, AC_ACCESS_REGISTER_POSTEXEC)) {
-      // Since the next instruction is what we will use, just use nother NOP
-      // to get there.
-      write32(debug_abstract, 1, addi(ZERO, ZERO, 0));
+      write32(debug_abstract, i,
+          jal(ZERO, debug_progbuf_start - debug_abstract_start - 4 * i));
+      i++;
     } else {
-      write32(debug_abstract, 1, ebreak());
+      write32(debug_abstract, i++, ebreak());
     }
 
     debug_rom_flags[dmcontrol.hartsel] |= 1 << DEBUG_ROM_FLAG_GO;
index e554ffc8f3623863851a1a4f5fbf4192402fae69..813c6472189b00e16da5aae099bceed692ba8bf1 100644 (file)
@@ -108,7 +108,7 @@ class debug_module_t : public abstract_device_t
     static const unsigned debug_data_start = 0x380;
     unsigned debug_progbuf_start;
 
-    static const unsigned debug_abstract_size = 2;
+    static const unsigned debug_abstract_size = 5;
     unsigned debug_abstract_start;
 
     static const unsigned hartsellen = 10;
diff --git a/riscv/debug_rom_defines.h b/riscv/debug_rom_defines.h
new file mode 100644 (file)
index 0000000..616cf59
--- /dev/null
@@ -0,0 +1,23 @@
+// See LICENSE file for license details.
+
+#ifndef DEBUG_ROM_DEFINES_H
+#define DEBUG_ROM_DEFINES_H
+
+// These are implementation-specific addresses in the Debug Module
+#define DEBUG_ROM_HALTED    0x100
+#define DEBUG_ROM_GOING     0x104
+#define DEBUG_ROM_RESUMING  0x108
+#define DEBUG_ROM_EXCEPTION 0x10C
+
+// Region of memory where each hart has 1
+// byte to read.
+#define DEBUG_ROM_FLAGS 0x400
+#define DEBUG_ROM_FLAG_GO     0
+#define DEBUG_ROM_FLAG_RESUME 1
+
+// These needs to match the link.ld         
+#define DEBUG_ROM_WHERETO 0x300
+#define DEBUG_ROM_ENTRY   0x800
+#define DEBUG_ROM_TVEC    0x808
+
+#endif
index 7f5effc741933b9a3b97fba5f54992ce2dac477f..596a2ad9bfea1bfe24b38ed1b733e5a8c91bb688 100644 (file)
@@ -201,18 +201,18 @@ private:
 #define zext_xlen(x) (((reg_t)(x) << (64-xlen)) >> (64-xlen))
 
 #define set_pc(x) \
-  do { if (unlikely(((x) & 2)) && !p->supports_extension('C')) \
-         throw trap_instruction_address_misaligned(x); \
+  do { p->check_pc_alignment(x); \
        npc = sext_xlen(x); \
      } while(0)
 
 #define set_pc_and_serialize(x) \
   do { reg_t __npc = (x); \
-       set_pc(__npc); /* check alignment */ \
        npc = PC_SERIALIZE_AFTER; \
        STATE.pc = __npc; \
      } while(0)
 
+#define serialize() set_pc_and_serialize(npc)
+
 /* Sentinel PC values to serialize simulator pipeline */
 #define PC_SERIALIZE_BEFORE 3
 #define PC_SERIALIZE_AFTER 5
index e60ffd117ebeb58a0f8f16c46bb5161ce1d58053..f8f122ad2a33a758b60cbe0c69bf0a7504f9d3c6 100644 (file)
@@ -2,7 +2,6 @@
 
 #include "processor.h"
 #include "mmu.h"
-#include "sim.h"
 #include <cassert>
 
 
@@ -114,6 +113,7 @@ void processor_t::step(size_t n)
          default: abort(); \
        } \
        pc = state.pc; \
+       check_pc_alignment(pc); \
        break; \
      } else { \
        state.pc = pc; \
index eae91fe661cdab82ec3eac33948fc35f3e4ab41a..0472d80efd5164b885d99d94f7a58d8359a26037 100644 (file)
@@ -5,3 +5,4 @@ if (write) {
   p->set_csr(csr, old & ~RS1);
 }
 WRITE_RD(sext_xlen(old));
+serialize();
index 986d6013aa858bfad336e5c5f71dbd586b26e347..4d83cc0617edd871ebb9ad823d86a4663c310ce9 100644 (file)
@@ -5,3 +5,4 @@ if (write) {
   p->set_csr(csr, old & ~(reg_t)insn.rs1());
 }
 WRITE_RD(sext_xlen(old));
+serialize();
index ec61b420a6b1c3420441f4c58226aefee9131acf..4e8bde96379935755ef87b32903e5aadd81a5227 100644 (file)
@@ -5,3 +5,4 @@ if (write) {
   p->set_csr(csr, old | RS1);
 }
 WRITE_RD(sext_xlen(old));
+serialize();
index aa44dcca8543ac374400450e4cc4326fc24652bc..b673725b54d1cbc8eb0a4e27e4af7d6563eb45b6 100644 (file)
@@ -5,3 +5,4 @@ if (write) {
   p->set_csr(csr, old | insn.rs1());
 }
 WRITE_RD(sext_xlen(old));
+serialize();
index 9f2324ff6f3fc859ffb3ece63495af9e55ed914c..e45420b570bc52c8bd53e2aaaf893eb6db3b3607 100644 (file)
@@ -2,3 +2,4 @@ int csr = validate_csr(insn.csr(), true);
 reg_t old = p->get_csr(csr);
 p->set_csr(csr, RS1);
 WRITE_RD(sext_xlen(old));
+serialize();
index cf0710f1d3742447cf3dc19e999da43075de2756..decadf412141076aec92ec58c4a9101e26456c06 100644 (file)
@@ -2,3 +2,4 @@ int csr = validate_csr(insn.csr(), true);
 reg_t old = p->get_csr(csr);
 p->set_csr(csr, insn.rs1());
 WRITE_RD(sext_xlen(old));
+serialize();
index dbcd22455d5fe6fdb75388946df176d7227ca6df..b645c29e1c80a81b69a2bfea624deae41bd2eb40 100644 (file)
@@ -168,7 +168,7 @@ reg_t sim_t::get_pc(const std::vector<std::string>& args)
     throw trap_interactive();
 
   processor_t *p = get_core(args[0]);
-  return p->state.pc;
+  return p->get_state()->pc;
 }
 
 void sim_t::interactive_pc(const std::string& cmd, const std::vector<std::string>& args)
@@ -198,7 +198,7 @@ reg_t sim_t::get_reg(const std::vector<std::string>& args)
   if (r >= NXPR)
     throw trap_interactive();
 
-  return p->state.XPR[r];
+  return p->get_state()->XPR[r];
 }
 
 freg_t sim_t::get_freg(const std::vector<std::string>& args)
@@ -213,7 +213,7 @@ freg_t sim_t::get_freg(const std::vector<std::string>& args)
   if (r >= NFPR)
     throw trap_interactive();
 
-  return p->state.FPR[r];
+  return p->get_state()->FPR[r];
 }
 
 void sim_t::interactive_reg(const std::string& cmd, const std::vector<std::string>& args)
@@ -223,7 +223,7 @@ void sim_t::interactive_reg(const std::string& cmd, const std::vector<std::strin
     processor_t *p = get_core(args[0]);
 
     for (int r = 0; r < NXPR; ++r) {
-      fprintf(stderr, "%-4s: 0x%016" PRIx64 "  ", xpr_name[r], p->state.XPR[r]);
+      fprintf(stderr, "%-4s: 0x%016" PRIx64 "  ", xpr_name[r], p->get_state()->XPR[r]);
       if ((r + 1) % 4 == 0)
         fprintf(stderr, "\n");
     }
index 5f054db64239214a3bd14b7ea238dc229accc839..eca8a8339968ef6880cba51dd08272b85a2e72a0 100644 (file)
@@ -4,7 +4,7 @@
 #include "sim.h"
 #include "processor.h"
 
-mmu_t::mmu_t(sim_t* sim, processor_t* proc)
+mmu_t::mmu_t(simif_t* sim, processor_t* proc)
  : sim(sim), proc(proc),
   check_triggers_fetch(false),
   check_triggers_load(false),
index d275ab2baa2e412319c0a6ada72f41b932058e14..f0bc19d1f546b47a999e63b61d46654da97d86a8 100644 (file)
@@ -53,7 +53,7 @@ class trigger_matched_t
 class mmu_t
 {
 public:
-  mmu_t(sim_t* sim, processor_t* proc);
+  mmu_t(simif_t* sim, processor_t* proc);
   ~mmu_t();
 
   inline reg_t misaligned_load(reg_t addr, size_t size)
@@ -240,7 +240,7 @@ public:
   void register_memtracer(memtracer_t*);
 
 private:
-  sim_t* sim;
+  simif_t* sim;
   processor_t* proc;
   memtracer_list_t tracer;
   uint16_t fetch_temp;
index 8cca49030e16ac878bcbd23e08ad3e0848a94f72..ce040443977a61faecf7d243dcbedf685574f71c 100644 (file)
@@ -19,7 +19,7 @@
 #undef STATE
 #define STATE state
 
-processor_t::processor_t(const char* isa, sim_t* sim, uint32_t id,
+processor_t::processor_t(const char* isa, simif_t* sim, uint32_t id,
         bool halt_on_reset)
   : debug(false), halt_request(false), sim(sim), ext(NULL), id(id),
   halt_on_reset(halt_on_reset), last_pc(1), executions(1)
@@ -435,12 +435,12 @@ void processor_t::set_csr(int which, reg_t val)
         state.satp = val & (SATP64_PPN | SATP64_MODE);
       break;
     }
-    case CSR_SEPC: state.sepc = val; break;
+    case CSR_SEPC: state.sepc = val & ~(reg_t)1; break;
     case CSR_STVEC: state.stvec = val >> 2 << 2; break;
     case CSR_SSCRATCH: state.sscratch = val; break;
     case CSR_SCAUSE: state.scause = val; break;
     case CSR_STVAL: state.stval = val; break;
-    case CSR_MEPC: state.mepc = val; break;
+    case CSR_MEPC: state.mepc = val & ~(reg_t)1; break;
     case CSR_MTVEC: state.mtvec = val & ~(reg_t)2; break;
     case CSR_MSCRATCH: state.mscratch = val; break;
     case CSR_MCAUSE: state.mcause = val; break;
@@ -510,7 +510,7 @@ void processor_t::set_csr(int which, reg_t val)
       state.dcsr.halt = get_field(val, DCSR_HALT);
       break;
     case CSR_DPC:
-      state.dpc = val;
+      state.dpc = val & ~(reg_t)1;
       break;
     case CSR_DSCRATCH:
       state.dscratch = val;
index 1b94b1f710e0c69d22e276318331a8e004d6e3cf..51fe8d2c8eb81a19be09c4674327c9df48d55e80 100644 (file)
@@ -5,15 +5,16 @@
 #include "decode.h"
 #include "config.h"
 #include "devices.h"
+#include "trap.h"
 #include <string>
 #include <vector>
 #include <map>
-#include "debug_rom/debug_rom_defines.h"
+#include "debug_rom_defines.h"
 
 class processor_t;
 class mmu_t;
 typedef reg_t (*insn_func_t)(processor_t*, insn_t, reg_t);
-class sim_t;
+class simif_t;
 class trap_t;
 class extension_t;
 class disassembler_t;
@@ -162,7 +163,7 @@ static int cto(reg_t val)
 class processor_t : public abstract_device_t
 {
 public:
-  processor_t(const char* isa, sim_t* sim, uint32_t id, bool halt_on_reset=false);
+  processor_t(const char* isa, simif_t* sim, uint32_t id, bool halt_on_reset=false);
   ~processor_t();
 
   void set_debug(bool value);
@@ -174,6 +175,8 @@ public:
   mmu_t* get_mmu() { return mmu; }
   state_t* get_state() { return &state; }
   unsigned get_xlen() { return xlen; }
+  unsigned get_max_xlen() { return max_xlen; }
+  std::string get_isa_string() { return isa_string; }
   unsigned get_flen() {
     return supports_extension('Q') ? 128 :
            supports_extension('D') ? 64 :
@@ -184,6 +187,10 @@ public:
     if (ext >= 'a' && ext <= 'z') ext += 'A' - 'a';
     return ext >= 'A' && ext <= 'Z' && ((isa >> (ext - 'A')) & 1);
   }
+  void check_pc_alignment(reg_t pc) {
+    if (unlikely(pc & 2) && !supports_extension('C'))
+      throw trap_instruction_address_misaligned(pc);
+  }
   reg_t legalize_privilege(reg_t);
   void set_privilege(reg_t);
   void yield_load_reservation() { state.load_reservation = (reg_t)-1; }
@@ -287,7 +294,7 @@ public:
   void trigger_updated();
 
 private:
-  sim_t* sim;
+  simif_t* sim;
   mmu_t* mmu; // main memory is always accessed via the mmu
   extension_t* ext;
   disassembler_t* disassembler;
@@ -315,7 +322,6 @@ private:
 
   void enter_debug_mode(uint8_t cause);
 
-  friend class sim_t;
   friend class mmu_t;
   friend class clint_t;
   friend class extension_t;
index 0e38c53fa96444a263f1560cbf631e21edc45497..81c5f6f1c465331a470222237f03f0261d661552 100644 (file)
@@ -248,7 +248,7 @@ void sim_t::make_dtb()
     0x297,                                      // auipc  t0,0x0
     0x28593 + (reset_vec_size * 4 << 20),       // addi   a1, t0, &dtb
     0xf1402573,                                 // csrr   a0, mhartid
-    get_core(0)->xlen == 32 ?
+    get_core(0)->get_xlen() == 32 ?
       0x0182a283u :                             // lw     t0,24(t0)
       0x0182b283u,                              // ld     t0,24(t0)
     0x28067,                                    // jr     t0
@@ -278,8 +278,8 @@ void sim_t::make_dtb()
          "      reg = <" << i << ">;\n"
          "      status = \"okay\";\n"
          "      compatible = \"riscv\";\n"
-         "      riscv,isa = \"" << procs[i]->isa_string << "\";\n"
-         "      mmu-type = \"riscv," << (procs[i]->max_xlen <= 32 ? "sv32" : "sv48") << "\";\n"
+         "      riscv,isa = \"" << procs[i]->get_isa_string() << "\";\n"
+         "      mmu-type = \"riscv," << (procs[i]->get_max_xlen() <= 32 ? "sv32" : "sv48") << "\";\n"
          "      clock-frequency = <" << CPU_HZ << ">;\n"
          "      CPU" << i << "_intc: interrupt-controller {\n"
          "        #interrupt-cells = <1>;\n"
index 6c6e4350702d62b240a42730a20f0b3efbd8f901..9a0a10b2569ba4a6aa8190fb5a540108f5a85a72 100644 (file)
 class mmu_t;
 class remote_bitbang_t;
 
+// this is the interface to the simulator used by the processors and memory
+class simif_t
+{
+public:
+  // should return NULL for MMIO addresses
+  virtual char* addr_to_mem(reg_t addr) = 0;
+  // used for MMIO addresses
+  virtual bool mmio_load(reg_t addr, size_t len, uint8_t* bytes) = 0;
+  virtual bool mmio_store(reg_t addr, size_t len, const uint8_t* bytes) = 0;
+};
+
 // this class encapsulates the processors and memory in a RISC-V machine.
-class sim_t : public htif_t
+class sim_t : public htif_t, public simif_t
 {
 public:
   sim_t(const char* isa, size_t _nprocs,  bool halted, reg_t start_pc,
index 77c13572345252a68d100aa1cf32b44029c82bfd..ff7637b13e512d2fbea29cff1504aa8c58c99f09 100644 (file)
@@ -2,6 +2,7 @@ softfloat_subproject_deps =
 
 softfloat_hdrs = \
   internals.h \
+  platform.h \
   primitives.h \
   primitiveTypes.h \
   softfloat.h \