diff options
-rw-r--r-- | riscv/csrs.cc | 43 | ||||
-rw-r--r-- | riscv/csrs.h | 16 | ||||
-rw-r--r-- | riscv/processor.cc | 2 | ||||
-rw-r--r-- | riscv/processor.h | 2 |
4 files changed, 63 insertions, 0 deletions
diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 98edacf..c887c4e 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1,5 +1,8 @@ // See LICENSE for license details. +// For std::any_of +#include <algorithm> + #include "csrs.h" // For processor_t: #include "processor.h" @@ -227,6 +230,46 @@ bool pmpcfg_csr_t::unlogged_write(const reg_t val) noexcept { return write_success; } +// implement class mseccfg_csr_t +mseccfg_csr_t::mseccfg_csr_t(processor_t* const proc, const reg_t addr): + basic_csr_t(proc, addr, 0) { +} + +bool mseccfg_csr_t::get_mml() const noexcept { + return (read() & MSECCFG_MML); +} + +bool mseccfg_csr_t::get_mmwp() const noexcept { + return (read() & MSECCFG_MMWP); +} + +bool mseccfg_csr_t::get_rlb() const noexcept { + return (read() & MSECCFG_RLB); +} + +bool mseccfg_csr_t::unlogged_write(const reg_t val) noexcept { + if (proc->n_pmp == 0) + return false; + + // pmpcfg.L is 1 in any rule or entry (including disabled entries) + const bool pmplock_recorded = std::any_of(state->pmpaddr, state->pmpaddr + proc->n_pmp, + [](const pmpaddr_csr_t_p & c) { return c->is_locked(); } ); + reg_t new_val = read(); + + // When RLB is 0 and pmplock_recorded, RLB is locked to 0. + // Otherwise set the RLB bit according val + if (!(pmplock_recorded && (read() & MSECCFG_RLB) == 0)) { + new_val &= ~MSECCFG_RLB; + new_val |= (val & MSECCFG_RLB); + } + + new_val |= (val & MSECCFG_MMWP); //MMWP is sticky + new_val |= (val & MSECCFG_MML); //MML is sticky + + proc->get_mmu()->flush_tlb(); + + return basic_csr_t::unlogged_write(new_val); +} // implement class virtualized_csr_t virtualized_csr_t::virtualized_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt): diff --git a/riscv/csrs.h b/riscv/csrs.h index fb27ae6..660ddd1 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -89,6 +89,11 @@ class pmpaddr_csr_t: public csr_t { // Is the specified access allowed given the pmpcfg privileges? bool access_ok(access_type type, reg_t mode) const noexcept; + // To check lock bit status from outside like mseccfg + bool is_locked() const noexcept { + return cfg & PMP_L; + } + protected: virtual bool unlogged_write(const reg_t val) noexcept override; private: @@ -122,6 +127,17 @@ class pmpcfg_csr_t: public csr_t { virtual bool unlogged_write(const reg_t val) noexcept override; }; +class mseccfg_csr_t: public basic_csr_t { + public: + mseccfg_csr_t(processor_t* const proc, const reg_t addr); + bool get_mml() const noexcept; + bool get_mmwp() const noexcept; + bool get_rlb() const noexcept; + protected: + virtual bool unlogged_write(const reg_t val) noexcept override; +}; + +typedef std::shared_ptr<mseccfg_csr_t> mseccfg_csr_t_p; // For CSRs that have a virtualized copy under another name. Each // instance of virtualized_csr_t will read/write one of two CSRs, diff --git a/riscv/processor.cc b/riscv/processor.cc index ad9944e..9ce9287 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -358,6 +358,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) debug_mode = false; single_step = STEP_NONE; + csrmap[CSR_MSECCFG] = mseccfg = std::make_shared<mseccfg_csr_t>(proc, CSR_MSECCFG); + for (int i = 0; i < max_pmp; ++i) { csrmap[CSR_PMPADDR0 + i] = pmpaddr[i] = std::make_shared<pmpaddr_csr_t>(proc, CSR_PMPADDR0 + i); } diff --git a/riscv/processor.h b/riscv/processor.h index 8797ab1..96fdc54 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -179,6 +179,8 @@ struct state_t tdata2_csr_t_p tdata2; bool debug_mode; + mseccfg_csr_t_p mseccfg; + static const int max_pmp = 16; pmpaddr_csr_t_p pmpaddr[max_pmp]; |