rvcpp: fix up PMP address mask for all-ones pmpaddr, and raise instruction fault on instruction stradding two PMP regions, like the hardware
This commit is contained in:
parent
7d370292b0
commit
ebe5a44454
|
@ -127,5 +127,8 @@ public:
|
|||
return mcause;
|
||||
}
|
||||
|
||||
// Return region, or -1 for no match
|
||||
int get_pmp_match(ux_t addr);
|
||||
|
||||
uint get_pmp_xwr(ux_t addr);
|
||||
};
|
||||
|
|
|
@ -143,10 +143,15 @@ void RVCore::step(bool trace) {
|
|||
uint funct3 = instr >> 12 & 0x7;
|
||||
uint funct7 = instr >> 25 & 0x7f;
|
||||
|
||||
bool pmp_straddle = false;
|
||||
if (fetch0 && (*fetch0 & 0x3) == 0x3) {
|
||||
pmp_straddle = csr.get_pmp_match(pc) != csr.get_pmp_match(pc + 2);
|
||||
}
|
||||
|
||||
std::optional<ux_t> irq_target_pc = csr.trap_check_enter_irq(pc);
|
||||
if (irq_target_pc) {
|
||||
// Replace current instruction with IRQ entry
|
||||
} else if (!fetch0 || ((*fetch0 & 0x3) == 0x3 && !fetch1)) {
|
||||
} else if (!fetch0 || ((*fetch0 & 0x3) == 0x3 && (!fetch1 || pmp_straddle))) {
|
||||
exception_cause = XCAUSE_INSTR_FAULT;
|
||||
} else if ((instr & 0x3) == 0x3) {
|
||||
// 32-bit instruction
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "encoding/rv_csr.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
|
||||
// Inclusive msb:lsb style, like Verilog (and like the ISA manual)
|
||||
#define BITS_UPTO(msb) (~((-1u << (msb)) << 1))
|
||||
|
@ -251,27 +252,38 @@ ux_t RVCSR::trap_mret() {
|
|||
return mepc;
|
||||
}
|
||||
|
||||
uint RVCSR::get_pmp_xwr(ux_t addr) {
|
||||
bool match = false;
|
||||
uint matching_xwr = 0;
|
||||
uint matching_l = 0;
|
||||
bool trace_pmp = get_true_priv() == PRV_U && true;
|
||||
int RVCSR::get_pmp_match(ux_t addr) {
|
||||
for (int i = 0; i < PMP_REGIONS; ++i) {
|
||||
if (pmpcfg_a(i) == 0u) {
|
||||
continue;
|
||||
}
|
||||
uint32_t mask = 0xffffffffu;
|
||||
if (pmpcfg_a(i) == 2) {
|
||||
mask = 0xfffffffeu << __builtin_ctz(~pmpaddr[i]);
|
||||
ux_t mask = 0xffffffffu;
|
||||
if (pmpcfg_a(i) == 3) {
|
||||
if (pmpaddr[i] == 0xffffffffu) {
|
||||
mask = 0u;
|
||||
} else {
|
||||
mask = 0xfffffffeu << __builtin_ctz(~pmpaddr[i]);
|
||||
}
|
||||
}
|
||||
match = ((addr >> 2) & mask) == (pmpaddr[i] & mask);
|
||||
bool match = ((addr >> 2) & mask) == (pmpaddr[i] & mask);
|
||||
if (match) {
|
||||
matching_xwr = pmpcfg_xwr(i);
|
||||
matching_l = pmpcfg_l(i);
|
||||
// Lowest-numbered match determines success/failure:
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint RVCSR::get_pmp_xwr(ux_t addr) {
|
||||
int region = get_pmp_match(addr);
|
||||
bool match = false;
|
||||
uint matching_xwr = 0;
|
||||
uint matching_l = 0;
|
||||
if (region >= 0) {
|
||||
match = true;
|
||||
matching_xwr = pmpcfg_xwr(region);
|
||||
matching_l = pmpcfg_l(region);
|
||||
}
|
||||
if (match) {
|
||||
// TODO MPRV
|
||||
if (get_true_priv() == PRV_M && !matching_l) {
|
||||
|
|
Loading…
Reference in New Issue