fixes privilege wrapper for M/U to cope with 64bit

This commit is contained in:
Eyck Jentzsch 2023-04-05 15:38:25 +02:00
parent a8a2782329
commit f626ee2684
1 changed files with 86 additions and 2 deletions

View File

@ -181,6 +181,89 @@ public:
#endif #endif
} }
}; };
// specialization 64bit
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::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<reg_t>; using hart_state_type = hart_state<reg_t>;
constexpr reg_t get_irq_mask(size_t mode) { constexpr reg_t get_irq_mask(size_t mode) {
@ -450,7 +533,7 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
csr_rd_cb[i] = &this_class::read_csr_reg; csr_rd_cb[i] = &this_class::read_csr_reg;
csr_wr_cb[i] = &this_class::write_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<pmpcfg0+16/sizeof(reg_t); ++i){
csr_rd_cb[i] = &this_class::read_csr_reg; csr_rd_cb[i] = &this_class::read_csr_reg;
csr_wr_cb[i] = &this_class::write_pmpcfg_reg; csr_wr_cb[i] = &this_class::write_pmpcfg_reg;
} }
@ -627,9 +710,10 @@ template <typename BASE, features_e FEAT> bool riscv_hart_mu_p<BASE, FEAT>::pmp_
constexpr auto PMP_NAPOT =0x3U; constexpr auto PMP_NAPOT =0x3U;
reg_t base = 0; reg_t base = 0;
auto any_active = false; auto any_active = false;
auto const cfg_reg_size=sizeof(reg_t);
for (size_t i = 0; i < 16; i++) { for (size_t i = 0; i < 16; i++) {
reg_t tor = csr[pmpaddr0+i] << PMP_SHIFT; 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) { if (cfg & PMP_A) {
any_active=true; any_active=true;
auto pmp_a = (cfg & PMP_A) >> 3; auto pmp_a = (cfg & PMP_A) >> 3;