Browse Source

Merge pull request #1882 from fk-sc/fk-sc/mprven-support

Add DCSR.MPRVEN support
pull/2029/head
Andrew Waterman 11 months ago
committed by GitHub
parent
commit
4c932cff7a
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 58
      debug_rom/debug_rom.S
  2. 32
      debug_rom/debug_rom.h
  3. 3
      riscv/csrs.cc
  4. 1
      riscv/csrs.h
  5. 2
      riscv/mmu.h

58
debug_rom/debug_rom.S

@ -7,6 +7,19 @@
.global entry .global entry
.global exception .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 // Entry location on ebreak, Halt, or Breakpoint
// It is the same for all harts. They branch when // It is the same for all harts. They branch when
// their GO or RESUME bit is set. // their GO or RESUME bit is set.
@ -30,13 +43,22 @@ _entry:
// We keep checking both whether there is something the debugger wants // We keep checking both whether there is something the debugger wants
// us to do, or whether we should resume. // us to do, or whether we should resume.
entry_loop: entry_loop:
csrr s0, CSR_MHARTID // 1 byte flag per hart. Only one hart advances here.
sw s0, DEBUG_ROM_HALTED(zero) MEMORY_ACCESS_WITH_MPRV(
lbu s0, DEBUG_ROM_FLAGS(s0) // 1 byte flag per hart. Only one hart advances here. csrr s0, CSR_MHARTID;
sw s0, DEBUG_ROM_HALTED(zero);
lbu s0, DEBUG_ROM_FLAGS(s0);
)
andi s0, s0, (1 << DEBUG_ROM_FLAG_GO) andi s0, s0, (1 << DEBUG_ROM_FLAG_GO)
bnez s0, going 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) andi s0, s0, (1 << DEBUG_ROM_FLAG_RESUME)
bnez s0, _resume bnez s0, _resume
wfi wfi
@ -46,13 +68,23 @@ _exception:
// Restore S0, which we always save to dscratch. // Restore S0, which we always save to dscratch.
// We need this in case the user tried an abstract write to a // We need this in case the user tried an abstract write to a
// non-existent CSR. // 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 ebreak
going: going:
csrr s0, CSR_MHARTID // When debug module sees this write, the GO flag is reset.
sw s0, DEBUG_ROM_GOING(zero) // 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 csrr s0, CSR_DSCRATCH0 // Restore s0 here
fence fence
fence.i fence.i
@ -61,8 +93,12 @@ going:
// because jalr is special there) // because jalr is special there)
_resume: _resume:
csrr s0, CSR_MHARTID // When Debug Module sees this write, the RESUME flag is reset.
sw s0, DEBUG_ROM_RESUMING(zero) // 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 csrr s0, CSR_DSCRATCH0 // Restore s0
dret dret

32
debug_rom/debug_rom.h

@ -1,13 +1,25 @@
static const unsigned char debug_rom_raw[] = { static const unsigned char debug_rom_raw[] = {
0x6f, 0x00, 0xc0, 0x00, 0x6f, 0x00, 0x00, 0x06, 0x6f, 0x00, 0x80, 0x03, 0x6f, 0x00, 0xc0, 0x00, 0x6f, 0x00, 0x40, 0x0d, 0x6f, 0x00, 0x40, 0x07,
0x0f, 0x00, 0xf0, 0x0f, 0x73, 0x10, 0x24, 0x7b, 0x73, 0x24, 0x40, 0xf1, 0x0f, 0x00, 0xf0, 0x0f, 0x73, 0x10, 0x24, 0x7b, 0x73, 0x74, 0x08, 0x7b,
0x23, 0x20, 0x80, 0x10, 0x03, 0x44, 0x04, 0x40, 0x13, 0x74, 0x14, 0x00, 0x13, 0x74, 0x04, 0x01, 0x63, 0x1a, 0x04, 0x00, 0x73, 0x24, 0x40, 0xf1,
0x63, 0x14, 0x04, 0x02, 0x73, 0x24, 0x40, 0xf1, 0x03, 0x44, 0x04, 0x40, 0x23, 0x20, 0x80, 0x10, 0x03, 0x44, 0x04, 0x40, 0x6f, 0x00, 0x40, 0x01,
0x13, 0x74, 0x24, 0x00, 0x63, 0x18, 0x04, 0x02, 0x73, 0x00, 0x50, 0x10, 0x73, 0x24, 0x40, 0xf1, 0x23, 0x20, 0x80, 0x10, 0x03, 0x44, 0x04, 0x40,
0x6f, 0xf0, 0x9f, 0xfd, 0x73, 0x24, 0x20, 0x7b, 0x23, 0x26, 0x00, 0x10, 0x73, 0x60, 0x08, 0x7b, 0x13, 0x74, 0x14, 0x00, 0x63, 0x10, 0x04, 0x06,
0x73, 0x00, 0x10, 0x00, 0x73, 0x24, 0x40, 0xf1, 0x23, 0x22, 0x80, 0x10, 0x73, 0x74, 0x08, 0x7b, 0x13, 0x74, 0x04, 0x01, 0x63, 0x18, 0x04, 0x00,
0x73, 0x24, 0x20, 0x7b, 0x0f, 0x00, 0xf0, 0x0f, 0x0f, 0x10, 0x00, 0x00, 0x73, 0x24, 0x40, 0xf1, 0x03, 0x44, 0x04, 0x40, 0x6f, 0x00, 0x00, 0x01,
0x67, 0x00, 0x00, 0x30, 0x73, 0x24, 0x40, 0xf1, 0x23, 0x24, 0x80, 0x10, 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 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;

3
riscv/csrs.cc

@ -1421,6 +1421,7 @@ dcsr_csr_t::dcsr_csr_t(processor_t* const proc, const reg_t addr):
ebreakvs(false), ebreakvs(false),
ebreakvu(false), ebreakvu(false),
v(false), v(false),
mprven(false),
cause(0), cause(0),
ext_cause(0), ext_cause(0),
cetrig(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_STEP, step);
result = set_field(result, DCSR_PRV, prv); result = set_field(result, DCSR_PRV, prv);
result = set_field(result, CSR_DCSR_V, v); result = set_field(result, CSR_DCSR_V, v);
result = set_field(result, DCSR_MPRVEN, mprven);
result = set_field(result, DCSR_PELP, pelp); result = set_field(result, DCSR_PELP, pelp);
return result; 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; ebreakvs = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_EBREAKVS) : false;
ebreakvu = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_EBREAKVU) : 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; 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) ? pelp = proc->extension_enabled(EXT_ZICFILP) ?
static_cast<elp_t>(get_field(val, DCSR_PELP)) : elp_t::NO_LP_EXPECTED; 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; cetrig = proc->extension_enabled(EXT_SMDBLTRP) ? get_field(val, DCSR_CETRIG) : false;

1
riscv/csrs.h

@ -725,6 +725,7 @@ class dcsr_csr_t: public csr_t {
bool ebreakvs; bool ebreakvs;
bool ebreakvu; bool ebreakvu;
bool v; bool v;
bool mprven;
uint8_t cause; uint8_t cause;
uint8_t ext_cause; uint8_t ext_cause;
bool cetrig; bool cetrig;

2
riscv/mmu.h

@ -508,7 +508,7 @@ private:
{ {
return proc != nullptr return proc != nullptr
&& !(proc->state.mnstatus && !get_field(proc->state.mnstatus->read(), MNSTATUS_NMIE)) && !(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); && get_field(proc->state.mstatus->read(), MSTATUS_MPRV);
} }

Loading…
Cancel
Save