X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=riscv%2Fdebug_module.cc;h=74c302300c8c14c3df029899d5122184f190aea7;hb=9d1e10a36e771bf8cfbf515e07e856e021c1007a;hp=12956a56426fd46d577fa7ae43dfe2e919f7aba8;hpb=c746388b542eacd2586acfbc0a742b08a5c0bd6f;p=riscv-isa-sim.git diff --git a/riscv/debug_module.cc b/riscv/debug_module.cc index 12956a5..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 @@ -16,14 +16,20 @@ ///////////////////////// debug_module_t -debug_module_t::debug_module_t(sim_t *sim, unsigned progbufsize, unsigned max_bus_master_bits) : +debug_module_t::debug_module_t(sim_t *sim, unsigned progbufsize, unsigned max_bus_master_bits, + bool require_authentication) : progbufsize(progbufsize), program_buffer_bytes(4 + 4*progbufsize), max_bus_master_bits(max_bus_master_bits), + require_authentication(require_authentication), debug_progbuf_start(debug_data_start - program_buffer_bytes), 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)); @@ -61,7 +67,7 @@ void debug_module_t::reset() dmstatus = {0}; dmstatus.impebreak = true; - dmstatus.authenticated = 1; + dmstatus.authenticated = !require_authentication; dmstatus.version = 2; abstractcs = {0}; @@ -83,6 +89,8 @@ void debug_module_t::reset() sbcs.access16 = true; if (max_bus_master_bits >= 8) sbcs.access8 = true; + + challenge = random(); } void debug_module_t::add_device(bus_t *bus) { @@ -458,6 +466,9 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value) case DMI_SBDATA3: result = sbdata[3]; break; + case DMI_AUTHDATA: + result = challenge; + break; default: result = 0; D(fprintf(stderr, "Unexpected. Returning Error.")); @@ -489,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; @@ -548,6 +618,11 @@ bool debug_module_t::perform_abstract_command() bool debug_module_t::dmi_write(unsigned address, uint32_t value) { D(fprintf(stderr, "dmi_write(0x%x, 0x%x)\n", address, value)); + + if (!dmstatus.authenticated && address != DMI_AUTHDATA && + address != DMI_DMCONTROL) + return false; + if (address >= DMI_DATA0 && address < DMI_DATA0 + abstractcs.datacount) { unsigned i = address - DMI_DATA0; if (!abstractcs.busy) @@ -580,6 +655,8 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value) if (!dmcontrol.dmactive && get_field(value, DMI_DMCONTROL_DMACTIVE)) reset(); dmcontrol.dmactive = get_field(value, DMI_DMCONTROL_DMACTIVE); + if (!dmstatus.authenticated) + return true; if (dmcontrol.dmactive) { dmcontrol.haltreq = get_field(value, DMI_DMCONTROL_HALTREQ); dmcontrol.resumereq = get_field(value, DMI_DMCONTROL_RESUMEREQ); @@ -662,6 +739,18 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value) case DMI_SBDATA3: sbdata[3] = value; return true; + case DMI_AUTHDATA: + D(fprintf(stderr, "debug authentication: got 0x%x; 0x%x unlocks\n", value, + challenge + secret)); + if (require_authentication) { + if (value == challenge + secret) { + dmstatus.authenticated = true; + } else { + dmstatus.authenticated = false; + challenge = random(); + } + } + return true; } } return false;