mirror of
https://github.com/riscv-software-src/riscv-isa-sim.git
synced 2025-10-14 02:07:30 +08:00
Add DCSR.MPRVEN support
Adds DCSR.MPRVEN bit support, as specified in RISC-V External Debug Support Version 1.0.0-rc4 (https://github.com/riscv/riscv-debug-spec/releases/tag/1.0.0-rc4, see 4.9.1 Debug Control and Status). This bit allows to enable hardware virtual address translation when memory access is initiated by the debugger (see 4.1 Debug Mode, clause 2). This change: * Increases debug specification coverage, allows more detailed testing of external debuggers with Spike. * Decreases the number of required abstract commands to read virtual memory thus improving the user experience. Commit's changes: * Added MPRVEN field to DCSR register * Updated debug_rom.S to turn off MPRVEN on memory access To avoid unwanted address translation while debug_rom.S executed DCSR.MPRVEN bit has to be cleared before and restored after access. Signed-off-by: Farid Khaydari <f.khaydari@syntacore.com>
This commit is contained in:
@@ -7,6 +7,19 @@
|
||||
.global entry
|
||||
.global exception
|
||||
|
||||
// This macro handles mem access with proper management of the MPRVEN
|
||||
// Usage: MEMORY_ACCESS_WITH_MPRV(<your code>)
|
||||
#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
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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<elp_t>(get_field(val, DCSR_PELP)) : elp_t::NO_LP_EXPECTED;
|
||||
cetrig = proc->extension_enabled(EXT_SMDBLTRP) ? get_field(val, DCSR_CETRIG) : false;
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user