From fd98ad95f6f417fdfa0e5f8686f84b8cf32eceac Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 9 Nov 2021 15:55:22 +0100 Subject: [PATCH] rework PMP check and fix MISA for TGC_D --- gen_input/TGC_D.core_desc | 2 +- incl/iss/arch/riscv_hart_mu_p.h | 54 +++++++++++++++------------------ 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/gen_input/TGC_D.core_desc b/gen_input/TGC_D.core_desc index 1187485..c4d9c54 100644 --- a/gen_input/TGC_D.core_desc +++ b/gen_input/TGC_D.core_desc @@ -7,7 +7,7 @@ Core TGC_D provides RV32I, Zicsr, Zifencei, RV32M, RV32IC { XLEN=32; // definitions for the architecture wrapper // XL ZYXWVUTSRQPONMLKJIHGFEDCBA - unsigned MISA_VAL = 0b01000000000000000001000100000100; + unsigned MISA_VAL = 0b01000000000100000011000100000100; unsigned MARCHID_VAL = 0x80000004; } } diff --git a/incl/iss/arch/riscv_hart_mu_p.h b/incl/iss/arch/riscv_hart_mu_p.h index 038c841..f9e6ab2 100644 --- a/incl/iss/arch/riscv_hart_mu_p.h +++ b/incl/iss/arch/riscv_hart_mu_p.h @@ -554,42 +554,36 @@ template bool riscv_hart_mu_p::pmp_ constexpr auto PMP_TOR =0x1U; constexpr auto PMP_NA4 =0x2U; constexpr auto PMP_NAPOT =0x3U; - reg_t base = 0; + constexpr auto pmp_num_regs = 16; + reg_t tor_base = 0; auto any_active = false; - for (size_t i = 0; i < 16; i++) { - reg_t tor = csr[pmpaddr0+i] << PMP_SHIFT; + 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 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)); + 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)); } } - base = tor; + tor_base = pmpaddr; } return !any_active || this->reg.PRIV == PRIV_M; }