From f626ee26845b7fc92e70578d85e6ae1b75b0c704 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 5 Apr 2023 15:38:25 +0200 Subject: [PATCH] fixes privilege wrapper for M/U to cope with 64bit --- src/iss/arch/riscv_hart_mu_p.h | 88 +++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 2 deletions(-) diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 8a1ce3d..fc2f16e 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -181,6 +181,89 @@ public: #endif } }; + + // specialization 64bit + template class hart_state::value>::type> { + public: + BEGIN_BF_DECL(mstatus_t, T); + // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) + BF_FIELD(SD, 63, 1); + // value of XLEN for S-mode + BF_FIELD(SXL, 34, 2); + // value of XLEN for U-mode + BF_FIELD(UXL, 32, 2); + // Trap SRET + BF_FIELD(TSR, 22, 1); + // Timeout Wait + BF_FIELD(TW, 21, 1); + // Trap Virtual Memory + BF_FIELD(TVM, 20, 1); + // Make eXecutable Readable + BF_FIELD(MXR, 19, 1); + // permit Supervisor User Memory access + BF_FIELD(SUM, 18, 1); + // Modify PRiVilege + BF_FIELD(MPRV, 17, 1); + // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty + BF_FIELD(XS, 15, 2); + // floating-point unit status Off/Initial/Clean/Dirty + BF_FIELD(FS, 13, 2); + // machine previous privilege + BF_FIELD(MPP, 11, 2); + // supervisor previous privilege + BF_FIELD(SPP, 8, 1); + // previous machine interrupt-enable + BF_FIELD(MPIE, 7, 1); + // previous supervisor interrupt-enable + BF_FIELD(SPIE, 5, 1); + // previous user interrupt-enable + BF_FIELD(UPIE, 4, 1); + // machine interrupt-enable + BF_FIELD(MIE, 3, 1); + // supervisor interrupt-enable + BF_FIELD(SIE, 1, 1); + // user interrupt-enable + BF_FIELD(UIE, 0, 1); + END_BF_DECL(); + + mstatus_t mstatus; + + static const reg_t mstatus_reset_val = 0x1800; + + void write_mstatus(T val, unsigned priv_lvl) { + auto mask = get_mask(priv_lvl); + auto new_val = (mstatus.backing.val & ~mask) | (val & mask); + mstatus = new_val; + } + + static constexpr uint64_t get_mask(unsigned priv_lvl) { +#if __cplusplus < 201402L + return priv_lvl == PRIV_U ? 0x011ULL : priv_lvl == PRIV_S ? 0x000de133ULL : 0x007ff9ddULL; +#else + switch (priv_lvl) { + case PRIV_U: return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 + default: + // +-SD + // | +-TSR + // | |+-TW + // | ||+-TVM + // | |||+-MXR + // | ||||+-SUM + // | |||||+-MPRV + // | |||||| +-XS + // | |||||| | +-FS + // | |||||| | | +-MPP + // | |||||| | | | +-SPP + // | |||||| | | | |+-MPIE + // | |||||| | | | || +-UPIE + // | ||||||/|/|/| || |+-MIE + // | ||||||/|/|/| || || +-UIE + return 0b00000000000000000001100010011001; + } +#endif + } + }; + using hart_state_type = hart_state; constexpr reg_t get_irq_mask(size_t mode) { @@ -450,7 +533,7 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr_rd_cb[i] = &this_class::read_csr_reg; csr_wr_cb[i] = &this_class::write_csr_reg; } - for(size_t i=pmpcfg0; i<=pmpcfg3; ++i){ + for(size_t i=pmpcfg0; i bool riscv_hart_mu_p::pmp_ constexpr auto PMP_NAPOT =0x3U; reg_t base = 0; auto any_active = false; + auto const cfg_reg_size=sizeof(reg_t); 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 = csr[pmpcfg0+(i/cfg_reg_size)]>>(i%cfg_reg_size); if (cfg & PMP_A) { any_active=true; auto pmp_a = (cfg & PMP_A) >> 3;