From: Tim Newsome Date: Thu, 8 Mar 2018 01:17:39 +0000 (-0800) Subject: Merge pull request #177 from riscv/debug_auth X-Git-Url: https://git.libre-soc.org/?p=riscv-isa-sim.git;a=commitdiff_plain;h=9d1e10a36e771bf8cfbf515e07e856e021c1007a;hp=aa8cbb1ccd3856fd5e0437b0e24cfd7a3b794b8e Merge pull request #177 from riscv/debug_auth Add debug module authentication. --- diff --git a/debug_rom/Makefile b/debug_rom/Makefile index 0a67ba1..c5f2205 100644 --- a/debug_rom/Makefile +++ b/debug_rom/Makefile @@ -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)) diff --git a/debug_rom/debug_rom.S b/debug_rom/debug_rom.S index 1342ee0..28c7076 100755 --- a/debug_rom/debug_rom.S +++ b/debug_rom/debug_rom.S @@ -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 index 616cf59..0000000 --- a/debug_rom/debug_rom_defines.h +++ /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 diff --git a/riscv/debug_module.cc b/riscv/debug_module.cc index f10c866..74c3023 100644 --- a/riscv/debug_module.cc +++ b/riscv/debug_module.cc @@ -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; diff --git a/riscv/debug_module.h b/riscv/debug_module.h index e554ffc..813c647 100644 --- a/riscv/debug_module.h +++ b/riscv/debug_module.h @@ -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 index 0000000..616cf59 --- /dev/null +++ b/riscv/debug_rom_defines.h @@ -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 diff --git a/riscv/decode.h b/riscv/decode.h index 7f5effc..596a2ad 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -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 diff --git a/riscv/execute.cc b/riscv/execute.cc index e60ffd1..f8f122a 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -2,7 +2,6 @@ #include "processor.h" #include "mmu.h" -#include "sim.h" #include @@ -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; \ diff --git a/riscv/insns/csrrc.h b/riscv/insns/csrrc.h index eae91fe..0472d80 100644 --- a/riscv/insns/csrrc.h +++ b/riscv/insns/csrrc.h @@ -5,3 +5,4 @@ if (write) { p->set_csr(csr, old & ~RS1); } WRITE_RD(sext_xlen(old)); +serialize(); diff --git a/riscv/insns/csrrci.h b/riscv/insns/csrrci.h index 986d601..4d83cc0 100644 --- a/riscv/insns/csrrci.h +++ b/riscv/insns/csrrci.h @@ -5,3 +5,4 @@ if (write) { p->set_csr(csr, old & ~(reg_t)insn.rs1()); } WRITE_RD(sext_xlen(old)); +serialize(); diff --git a/riscv/insns/csrrs.h b/riscv/insns/csrrs.h index ec61b42..4e8bde9 100644 --- a/riscv/insns/csrrs.h +++ b/riscv/insns/csrrs.h @@ -5,3 +5,4 @@ if (write) { p->set_csr(csr, old | RS1); } WRITE_RD(sext_xlen(old)); +serialize(); diff --git a/riscv/insns/csrrsi.h b/riscv/insns/csrrsi.h index aa44dcc..b673725 100644 --- a/riscv/insns/csrrsi.h +++ b/riscv/insns/csrrsi.h @@ -5,3 +5,4 @@ if (write) { p->set_csr(csr, old | insn.rs1()); } WRITE_RD(sext_xlen(old)); +serialize(); diff --git a/riscv/insns/csrrw.h b/riscv/insns/csrrw.h index 9f2324f..e45420b 100644 --- a/riscv/insns/csrrw.h +++ b/riscv/insns/csrrw.h @@ -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(); diff --git a/riscv/insns/csrrwi.h b/riscv/insns/csrrwi.h index cf0710f..decadf4 100644 --- a/riscv/insns/csrrwi.h +++ b/riscv/insns/csrrwi.h @@ -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(); diff --git a/riscv/interactive.cc b/riscv/interactive.cc index dbcd224..b645c29 100644 --- a/riscv/interactive.cc +++ b/riscv/interactive.cc @@ -168,7 +168,7 @@ reg_t sim_t::get_pc(const std::vector& 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& args) @@ -198,7 +198,7 @@ reg_t sim_t::get_reg(const std::vector& 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& args) @@ -213,7 +213,7 @@ freg_t sim_t::get_freg(const std::vector& 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& args) @@ -223,7 +223,7 @@ void sim_t::interactive_reg(const std::string& cmd, const std::vectorstate.XPR[r]); + fprintf(stderr, "%-4s: 0x%016" PRIx64 " ", xpr_name[r], p->get_state()->XPR[r]); if ((r + 1) % 4 == 0) fprintf(stderr, "\n"); } diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 5f054db..eca8a83 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -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), diff --git a/riscv/mmu.h b/riscv/mmu.h index d275ab2..f0bc19d 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -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; diff --git a/riscv/processor.cc b/riscv/processor.cc index 8cca490..ce04044 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -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; diff --git a/riscv/processor.h b/riscv/processor.h index 1b94b1f..51fe8d2 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -5,15 +5,16 @@ #include "decode.h" #include "config.h" #include "devices.h" +#include "trap.h" #include #include #include -#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; diff --git a/riscv/sim.cc b/riscv/sim.cc index 0e38c53..81c5f6f 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -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" diff --git a/riscv/sim.h b/riscv/sim.h index 6c6e435..9a0a10b 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -15,8 +15,19 @@ 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, diff --git a/softfloat/softfloat.mk.in b/softfloat/softfloat.mk.in index 77c1357..ff7637b 100644 --- a/softfloat/softfloat.mk.in +++ b/softfloat/softfloat.mk.in @@ -2,6 +2,7 @@ softfloat_subproject_deps = softfloat_hdrs = \ internals.h \ + platform.h \ primitives.h \ primitiveTypes.h \ softfloat.h \