diff --git a/debug_rom/debug_rom.S b/debug_rom/debug_rom.S index 2d361397..378c5683 100755 --- a/debug_rom/debug_rom.S +++ b/debug_rom/debug_rom.S @@ -7,6 +7,19 @@ .global entry .global exception +// This macro handles mem access with proper management of the MPRVEN +// Usage: MEMORY_ACCESS_WITH_MPRV() +#define MEMORY_ACCESS_WITH_MPRV(...) \ + csrrci s0, CSR_DCSR, DCSR_MPRVEN; \ + andi s0, s0, DCSR_MPRVEN; \ + bnez s0, 1f; \ + __VA_ARGS__; \ + j 2f; \ +1: \ + __VA_ARGS__; \ + csrrsi zero, CSR_DCSR, DCSR_MPRVEN; \ +2: + // Entry location on ebreak, Halt, or Breakpoint // It is the same for all harts. They branch when // their GO or RESUME bit is set. @@ -30,13 +43,22 @@ _entry: // We keep checking both whether there is something the debugger wants // us to do, or whether we should resume. entry_loop: - csrr s0, CSR_MHARTID - sw s0, DEBUG_ROM_HALTED(zero) - lbu s0, DEBUG_ROM_FLAGS(s0) // 1 byte flag per hart. Only one hart advances here. + // 1 byte flag per hart. Only one hart advances here. + MEMORY_ACCESS_WITH_MPRV( + csrr s0, CSR_MHARTID; + sw s0, DEBUG_ROM_HALTED(zero); + lbu s0, DEBUG_ROM_FLAGS(s0); + ) + andi s0, s0, (1 << DEBUG_ROM_FLAG_GO) bnez s0, going - csrr s0, CSR_MHARTID - lbu s0, DEBUG_ROM_FLAGS(s0) // multiple harts can resume here + + // multiple harts can resume here + MEMORY_ACCESS_WITH_MPRV( + csrr s0, CSR_MHARTID; + lbu s0, DEBUG_ROM_FLAGS(s0); + ) + andi s0, s0, (1 << DEBUG_ROM_FLAG_RESUME) bnez s0, _resume wfi @@ -46,13 +68,23 @@ _exception: // Restore S0, which we always save to dscratch. // We need this in case the user tried an abstract write to a // non-existent CSR. - csrr s0, CSR_DSCRATCH0 - sw zero, DEBUG_ROM_EXCEPTION(zero) // Let debug module know you got an exception. + + + // Let debug module know you got an exception. + MEMORY_ACCESS_WITH_MPRV( + csrr s0, CSR_DSCRATCH0; + sw zero, DEBUG_ROM_EXCEPTION(zero); + ) + ebreak going: - csrr s0, CSR_MHARTID - sw s0, DEBUG_ROM_GOING(zero) // When debug module sees this write, the GO flag is reset. + // When debug module sees this write, the GO flag is reset. + MEMORY_ACCESS_WITH_MPRV( + csrr s0, CSR_MHARTID; + sw s0, DEBUG_ROM_GOING(zero); + ) + csrr s0, CSR_DSCRATCH0 // Restore s0 here fence fence.i @@ -61,8 +93,12 @@ going: // because jalr is special there) _resume: - csrr s0, CSR_MHARTID - sw s0, DEBUG_ROM_RESUMING(zero) // When Debug Module sees this write, the RESUME flag is reset. + // When Debug Module sees this write, the RESUME flag is reset. + MEMORY_ACCESS_WITH_MPRV( + csrr s0, CSR_MHARTID; + sw s0, DEBUG_ROM_RESUMING(zero); + ) + csrr s0, CSR_DSCRATCH0 // Restore s0 dret diff --git a/debug_rom/debug_rom.h b/debug_rom/debug_rom.h index 7edd5f68..d3d89a28 100644 --- a/debug_rom/debug_rom.h +++ b/debug_rom/debug_rom.h @@ -1,13 +1,25 @@ static const unsigned char debug_rom_raw[] = { - 0x6f, 0x00, 0xc0, 0x00, 0x6f, 0x00, 0x00, 0x06, 0x6f, 0x00, 0x80, 0x03, - 0x0f, 0x00, 0xf0, 0x0f, 0x73, 0x10, 0x24, 0x7b, 0x73, 0x24, 0x40, 0xf1, - 0x23, 0x20, 0x80, 0x10, 0x03, 0x44, 0x04, 0x40, 0x13, 0x74, 0x14, 0x00, - 0x63, 0x14, 0x04, 0x02, 0x73, 0x24, 0x40, 0xf1, 0x03, 0x44, 0x04, 0x40, - 0x13, 0x74, 0x24, 0x00, 0x63, 0x18, 0x04, 0x02, 0x73, 0x00, 0x50, 0x10, - 0x6f, 0xf0, 0x9f, 0xfd, 0x73, 0x24, 0x20, 0x7b, 0x23, 0x26, 0x00, 0x10, - 0x73, 0x00, 0x10, 0x00, 0x73, 0x24, 0x40, 0xf1, 0x23, 0x22, 0x80, 0x10, - 0x73, 0x24, 0x20, 0x7b, 0x0f, 0x00, 0xf0, 0x0f, 0x0f, 0x10, 0x00, 0x00, - 0x67, 0x00, 0x00, 0x30, 0x73, 0x24, 0x40, 0xf1, 0x23, 0x24, 0x80, 0x10, + 0x6f, 0x00, 0xc0, 0x00, 0x6f, 0x00, 0x40, 0x0d, 0x6f, 0x00, 0x40, 0x07, + 0x0f, 0x00, 0xf0, 0x0f, 0x73, 0x10, 0x24, 0x7b, 0x73, 0x74, 0x08, 0x7b, + 0x13, 0x74, 0x04, 0x01, 0x63, 0x1a, 0x04, 0x00, 0x73, 0x24, 0x40, 0xf1, + 0x23, 0x20, 0x80, 0x10, 0x03, 0x44, 0x04, 0x40, 0x6f, 0x00, 0x40, 0x01, + 0x73, 0x24, 0x40, 0xf1, 0x23, 0x20, 0x80, 0x10, 0x03, 0x44, 0x04, 0x40, + 0x73, 0x60, 0x08, 0x7b, 0x13, 0x74, 0x14, 0x00, 0x63, 0x10, 0x04, 0x06, + 0x73, 0x74, 0x08, 0x7b, 0x13, 0x74, 0x04, 0x01, 0x63, 0x18, 0x04, 0x00, + 0x73, 0x24, 0x40, 0xf1, 0x03, 0x44, 0x04, 0x40, 0x6f, 0x00, 0x00, 0x01, + 0x73, 0x24, 0x40, 0xf1, 0x03, 0x44, 0x04, 0x40, 0x73, 0x60, 0x08, 0x7b, + 0x13, 0x74, 0x24, 0x00, 0x63, 0x14, 0x04, 0x06, 0x73, 0x00, 0x50, 0x10, + 0x6f, 0xf0, 0xdf, 0xf9, 0x73, 0x74, 0x08, 0x7b, 0x13, 0x74, 0x04, 0x01, + 0x63, 0x18, 0x04, 0x00, 0x73, 0x24, 0x20, 0x7b, 0x23, 0x26, 0x00, 0x10, + 0x6f, 0x00, 0x00, 0x01, 0x73, 0x24, 0x20, 0x7b, 0x23, 0x26, 0x00, 0x10, + 0x73, 0x60, 0x08, 0x7b, 0x73, 0x00, 0x10, 0x00, 0x73, 0x74, 0x08, 0x7b, + 0x13, 0x74, 0x04, 0x01, 0x63, 0x18, 0x04, 0x00, 0x73, 0x24, 0x40, 0xf1, + 0x23, 0x22, 0x80, 0x10, 0x6f, 0x00, 0x00, 0x01, 0x73, 0x24, 0x40, 0xf1, + 0x23, 0x22, 0x80, 0x10, 0x73, 0x60, 0x08, 0x7b, 0x73, 0x24, 0x20, 0x7b, + 0x0f, 0x00, 0xf0, 0x0f, 0x0f, 0x10, 0x00, 0x00, 0x67, 0x00, 0x00, 0x30, + 0x73, 0x74, 0x08, 0x7b, 0x13, 0x74, 0x04, 0x01, 0x63, 0x18, 0x04, 0x00, + 0x73, 0x24, 0x40, 0xf1, 0x23, 0x24, 0x80, 0x10, 0x6f, 0x00, 0x00, 0x01, + 0x73, 0x24, 0x40, 0xf1, 0x23, 0x24, 0x80, 0x10, 0x73, 0x60, 0x08, 0x7b, 0x73, 0x24, 0x20, 0x7b, 0x73, 0x00, 0x20, 0x7b }; -static const unsigned int debug_rom_raw_len = 116; +static const unsigned int debug_rom_raw_len = 260; diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 49717e55..3a327126 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1421,6 +1421,7 @@ dcsr_csr_t::dcsr_csr_t(processor_t* const proc, const reg_t addr): ebreakvs(false), ebreakvu(false), v(false), + mprven(false), cause(0), ext_cause(0), cetrig(0), @@ -1450,6 +1451,7 @@ reg_t dcsr_csr_t::read() const noexcept { result = set_field(result, DCSR_STEP, step); result = set_field(result, DCSR_PRV, prv); result = set_field(result, CSR_DCSR_V, v); + result = set_field(result, DCSR_MPRVEN, mprven); result = set_field(result, DCSR_PELP, pelp); return result; } @@ -1464,6 +1466,7 @@ bool dcsr_csr_t::unlogged_write(const reg_t val) noexcept { ebreakvs = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_EBREAKVS) : false; ebreakvu = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_EBREAKVU) : false; v = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_V) : false; + mprven = get_field(val, CSR_DCSR_MPRVEN); pelp = proc->extension_enabled(EXT_ZICFILP) ? static_cast(get_field(val, DCSR_PELP)) : elp_t::NO_LP_EXPECTED; cetrig = proc->extension_enabled(EXT_SMDBLTRP) ? get_field(val, DCSR_CETRIG) : false; diff --git a/riscv/csrs.h b/riscv/csrs.h index 97fd0f18..f076aaab 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -725,6 +725,7 @@ class dcsr_csr_t: public csr_t { bool ebreakvs; bool ebreakvu; bool v; + bool mprven; uint8_t cause; uint8_t ext_cause; bool cetrig; diff --git a/riscv/mmu.h b/riscv/mmu.h index 305d502c..94f3a97f 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -508,7 +508,7 @@ private: { return proc != nullptr && !(proc->state.mnstatus && !get_field(proc->state.mnstatus->read(), MNSTATUS_NMIE)) - && !proc->state.debug_mode + && (!proc->state.debug_mode || get_field(proc->state.dcsr->read(), DCSR_MPRVEN)) && get_field(proc->state.mstatus->read(), MSTATUS_MPRV); }