rework PMP check and fix MISA for TGC_D

This commit is contained in:
Eyck Jentzsch 2021-11-09 15:55:22 +01:00
parent bfa8166223
commit fd98ad95f6
2 changed files with 25 additions and 31 deletions

View File

@ -7,7 +7,7 @@ Core TGC_D provides RV32I, Zicsr, Zifencei, RV32M, RV32IC {
XLEN=32; XLEN=32;
// definitions for the architecture wrapper // definitions for the architecture wrapper
// XL ZYXWVUTSRQPONMLKJIHGFEDCBA // XL ZYXWVUTSRQPONMLKJIHGFEDCBA
unsigned MISA_VAL = 0b01000000000000000001000100000100; unsigned MISA_VAL = 0b01000000000100000011000100000100;
unsigned MARCHID_VAL = 0x80000004; unsigned MARCHID_VAL = 0x80000004;
} }
} }

View File

@ -554,42 +554,36 @@ template <typename BASE, features_e FEAT> bool riscv_hart_mu_p<BASE, FEAT>::pmp_
constexpr auto PMP_TOR =0x1U; constexpr auto PMP_TOR =0x1U;
constexpr auto PMP_NA4 =0x2U; constexpr auto PMP_NA4 =0x2U;
constexpr auto PMP_NAPOT =0x3U; constexpr auto PMP_NAPOT =0x3U;
reg_t base = 0; constexpr auto pmp_num_regs = 16;
reg_t tor_base = 0;
auto any_active = false; auto any_active = false;
for (size_t i = 0; i < 16; i++) { auto lower_addr = addr >>2;
reg_t tor = csr[pmpaddr0+i] << PMP_SHIFT; auto upper_addr = (addr+len-1)>>2;
for (size_t i = 0; i < pmp_num_regs; i++) {
uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4); uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4);
uint8_t cfg_next = i==(pmp_num_regs-1)? 0 : csr[pmpcfg0+((i+1)/4)]>>((i+1)%4);
auto pmpaddr = csr[pmpaddr0+i];
if (cfg & PMP_A) { if (cfg & PMP_A) {
any_active=true; any_active=true;
auto pmp_a = (cfg & PMP_A) >> 3; auto is_tor = bit_sub<3, 2>(cfg) == PMP_TOR;
auto is_tor = pmp_a == PMP_TOR; auto is_napot = bit_sub<4, 1>(cfg) && bit_sub<3, 2>(cfg_next)!= PMP_TOR;
auto is_na4 = pmp_a == PMP_NA4; if(is_napot) {
reg_t mask = bit_sub<3, 1>(cfg)?~( pmpaddr & ~(pmpaddr + 1)): 0x3fffffff;
reg_t mask = (csr[pmpaddr0+i] << 1) | (!is_na4); auto mpmpaddr = pmpaddr & mask;
mask = ~(mask & ~(mask + 1)) << PMP_SHIFT; if((lower_addr&mask) == mpmpaddr && (upper_addr&mask)==mpmpaddr)
return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) ||
// Check each 4-byte sector of the access (type == access_type::READ && (cfg & PMP_R)) ||
auto any_match = false; (type == access_type::WRITE && (cfg & PMP_W)) ||
auto all_match = true; (type == access_type::FETCH && (cfg & PMP_X));
for (reg_t offset = 0; offset < len; offset += 1 << PMP_SHIFT) { } else if(is_tor) {
reg_t cur_addr = addr + offset; if(lower_addr>=tor_base && upper_addr<=pmpaddr)
auto napot_match = ((cur_addr ^ tor) & mask) == 0; return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) ||
auto tor_match = base <= cur_addr && cur_addr < tor; (type == access_type::READ && (cfg & PMP_R)) ||
auto match = is_tor ? tor_match : napot_match; (type == access_type::WRITE && (cfg & PMP_W)) ||
any_match |= match; (type == access_type::FETCH && (cfg & PMP_X));
all_match &= match;
}
if (any_match) {
// If the PMP matches only a strict subset of the access, fail it
if (!all_match)
return false;
return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) ||
(type == access_type::READ && (cfg & PMP_R)) ||
(type == access_type::WRITE && (cfg & PMP_W)) ||
(type == access_type::FETCH && (cfg & PMP_X));
} }
} }
base = tor; tor_base = pmpaddr;
} }
return !any_active || this->reg.PRIV == PRIV_M; return !any_active || this->reg.PRIV == PRIV_M;
} }