From 43d7b9990516ac62bc7586cba11b92e4fcbcc32a Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 11 Nov 2021 09:58:19 +0100 Subject: [PATCH] revert pmp check implementation --- incl/iss/arch/riscv_hart_mu_p.h | 85 +++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 24 deletions(-) diff --git a/incl/iss/arch/riscv_hart_mu_p.h b/incl/iss/arch/riscv_hart_mu_p.h index b1ed4f1..2444cd7 100644 --- a/incl/iss/arch/riscv_hart_mu_p.h +++ b/incl/iss/arch/riscv_hart_mu_p.h @@ -554,37 +554,74 @@ template bool riscv_hart_mu_p::pmp_ constexpr auto PMP_TOR =0x1U; constexpr auto PMP_NA4 =0x2U; constexpr auto PMP_NAPOT =0x3U; - constexpr auto pmp_num_regs = 16; - reg_t tor_base = 0; + reg_t base = 0; auto any_active = false; - auto lower_addr = addr >>2; - auto upper_addr = (addr+len-1)>>2; - for (size_t i = 0; i < pmp_num_regs; i++) { + for (size_t i = 0; i < 16; i++) { + reg_t tor = csr[pmpaddr0+i] << PMP_SHIFT; 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) { any_active=true; - auto is_tor = bit_sub<3, 2>(cfg) == PMP_TOR; - auto is_napot = bit_sub<4, 1>(cfg) && bit_sub<3, 2>(cfg_next)!= PMP_TOR; - if(is_napot) { - reg_t mask = bit_sub<3, 1>(cfg)?~( pmpaddr & ~(pmpaddr + 1)): 0x3fffffff; - auto mpmpaddr = pmpaddr & mask; - if((lower_addr&mask) == mpmpaddr && (upper_addr&mask)==mpmpaddr) - 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)); - } else if(is_tor) { - if(lower_addr>=tor_base && upper_addr<=pmpaddr) - 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)); + auto pmp_a = (cfg & PMP_A) >> 3; + auto is_tor = pmp_a == PMP_TOR; + auto is_na4 = pmp_a == PMP_NA4; + + reg_t mask = (csr[pmpaddr0+i] << 1) | (!is_na4); + mask = ~(mask & ~(mask + 1)) << PMP_SHIFT; + + // Check each 4-byte sector of the access + auto any_match = false; + auto all_match = true; + for (reg_t offset = 0; offset < len; offset += 1 << PMP_SHIFT) { + reg_t cur_addr = addr + offset; + auto napot_match = ((cur_addr ^ tor) & mask) == 0; + auto tor_match = base <= cur_addr && cur_addr < tor; + auto match = is_tor ? tor_match : napot_match; + any_match |= match; + 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)); } } - tor_base = pmpaddr; + base = tor; } +// constexpr auto pmp_num_regs = 16; +// reg_t tor_base = 0; +// auto any_active = false; +// auto lower_addr = addr >>2; +// 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_next = i==(pmp_num_regs-1)? 0 : csr[pmpcfg0+((i+1)/4)]>>((i+1)%4); +// auto pmpaddr = csr[pmpaddr0+i]; +// if (cfg & PMP_A) { +// any_active=true; +// auto is_tor = bit_sub<3, 2>(cfg) == PMP_TOR; +// auto is_napot = bit_sub<4, 1>(cfg) && bit_sub<3, 2>(cfg_next)!= PMP_TOR; +// if(is_napot) { +// reg_t mask = bit_sub<3, 1>(cfg)?~( pmpaddr & ~(pmpaddr + 1)): 0x3fffffff; +// auto mpmpaddr = pmpaddr & mask; +// if((lower_addr&mask) == mpmpaddr && (upper_addr&mask)==mpmpaddr) +// 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)); +// } else if(is_tor) { +// if(lower_addr>=tor_base && upper_addr<=pmpaddr) +// 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)); +// } +// } +// tor_base = pmpaddr; +// } return !any_active || this->reg.PRIV == PRIV_M; }