Browse Source

Implement Smrnmi extension

We don't model any sources of RNMI, so this is mostly vestigial.
pull/1286/head
Andrew Waterman 3 years ago
parent
commit
a5fdc4efbf
  1. 20
      riscv/csrs.cc
  2. 7
      riscv/csrs.h
  3. 15
      riscv/insns/mnret.h
  4. 2
      riscv/isa_parser.cc
  5. 1
      riscv/isa_parser.h
  6. 1
      riscv/mmu.h
  7. 19
      riscv/processor.cc
  8. 2
      riscv/processor.h
  9. 4
      riscv/riscv.mk.in

20
riscv/csrs.cc

@ -516,6 +516,24 @@ reg_t mstatus_csr_t::compute_mstatus_initial_value() const noexcept {
| 0; // initial value for mstatus
}
// implement class mnstatus_csr_t
mnstatus_csr_t::mnstatus_csr_t(processor_t* const proc, const reg_t addr):
basic_csr_t(proc, addr, 0) {
}
bool mnstatus_csr_t::unlogged_write(const reg_t val) noexcept {
// NMIE can be set but not cleared
const reg_t mask = (~read() & MNSTATUS_NMIE)
| (proc->extension_enabled('H') ? MNSTATUS_MNPV : 0)
| MNSTATUS_MNPP;
const reg_t requested_mnpp = proc->legalize_privilege(get_field(val, MNSTATUS_MNPP));
const reg_t adjusted_val = set_field(val, MNSTATUS_MNPP, requested_mnpp);
const reg_t new_mnstatus = (read() & ~mask) | (adjusted_val & mask);
return basic_csr_t::unlogged_write(new_mnstatus);
}
// implement class rv32_low_csr_t
rv32_low_csr_t::rv32_low_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig):
csr_t(proc, addr),
@ -654,7 +672,9 @@ bool misa_csr_t::unlogged_write(const reg_t val) noexcept {
| (1 << CAUSE_VIRTUAL_INSTRUCTION)
| (1 << CAUSE_STORE_GUEST_PAGE_FAULT)
;
state->medeleg->write(state->medeleg->read() & ~hypervisor_exceptions);
if (state->mnstatus) state->mnstatus->write(state->mnstatus->read() & ~MNSTATUS_MNPV);
const reg_t new_mstatus = state->mstatus->read() & ~(MSTATUS_GVA | MSTATUS_MPV);
state->mstatus->write(new_mstatus);
if (state->mstatush) state->mstatush->write(new_mstatus >> 32); // log mstatush change

7
riscv/csrs.h

@ -256,6 +256,13 @@ class mstatus_csr_t final: public base_status_csr_t {
typedef std::shared_ptr<mstatus_csr_t> mstatus_csr_t_p;
class mnstatus_csr_t final: public basic_csr_t {
public:
mnstatus_csr_t(processor_t* const proc, const reg_t addr);
protected:
virtual bool unlogged_write(const reg_t val) noexcept override;
};
// For RV32 CSRs that are split into two, e.g. mstatus/mstatush
// CSRW should only modify the lower half
class rv32_low_csr_t: public csr_t {

15
riscv/insns/mnret.h

@ -0,0 +1,15 @@
require_extension(EXT_SMRNMI);
require_privilege(PRV_M);
set_pc_and_serialize(p->get_state()->mnepc->read());
reg_t s = STATE.mnstatus->read();
reg_t prev_prv = get_field(s, MNSTATUS_MNPP);
reg_t prev_virt = get_field(s, MNSTATUS_MNPV);
if (prev_prv != PRV_M) {
reg_t mstatus = STATE.mstatus->read();
mstatus = set_field(mstatus, MSTATUS_MPRV, 0);
STATE.mstatus->write(mstatus);
}
s = set_field(s, MNSTATUS_NMIE, 1);
STATE.mnstatus->write(s);
p->set_privilege(prev_prv);
p->set_virt(prev_virt);

2
riscv/isa_parser.cc

@ -211,6 +211,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
extension_table[EXT_SMEPMP] = true;
} else if (ext_str == "smstateen") {
extension_table[EXT_SMSTATEEN] = true;
} else if (ext_str == "smrnmi") {
extension_table[EXT_SMRNMI] = true;
} else if (ext_str == "sscofpmf") {
extension_table[EXT_SSCOFPMF] = true;
} else if (ext_str == "svadu") {

1
riscv/isa_parser.h

@ -41,6 +41,7 @@ typedef enum {
EXT_ZVFHMIN,
EXT_SMEPMP,
EXT_SMSTATEEN,
EXT_SMRNMI,
EXT_SSCOFPMF,
EXT_SVADU,
EXT_SVNAPOT,

1
riscv/mmu.h

@ -406,6 +406,7 @@ private:
inline bool in_mprv()
{
return proc != nullptr
&& !(proc->state.mnstatus && !get_field(proc->state.mnstatus->read(), MNSTATUS_NMIE))
&& !proc->state.debug_mode
&& get_field(proc->state.mstatus->read(), MSTATUS_MPRV);
}

19
riscv/processor.cc

@ -494,6 +494,13 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
}
}
if (proc->extension_enabled_const(EXT_SMRNMI)) {
csrmap[CSR_MNSCRATCH] = std::make_shared<basic_csr_t>(proc, CSR_MNSCRATCH, 0);
csrmap[CSR_MNEPC] = mnepc = std::make_shared<epc_csr_t>(proc, CSR_MNEPC);
csrmap[CSR_MNCAUSE] = std::make_shared<const_csr_t>(proc, CSR_MNCAUSE, (reg_t)1 << (xlen - 1));
csrmap[CSR_MNSTATUS] = mnstatus = std::make_shared<mnstatus_csr_t>(proc, CSR_MNSTATUS);
}
if (proc->extension_enabled_const(EXT_SSTC)) {
stimecmp = std::make_shared<stimecmp_csr_t>(proc, CSR_STIMECMP, MIP_STIP);
vstimecmp = std::make_shared<stimecmp_csr_t>(proc, CSR_VSTIMECMP, MIP_VSTIP);
@ -660,7 +667,8 @@ void processor_t::take_interrupt(reg_t pending_interrupts)
}
}
if (!state.debug_mode && enabled_interrupts) {
const bool nmie = !(state.mnstatus && !get_field(state.mnstatus->read(), MNSTATUS_NMIE));
if (!state.debug_mode && nmie && enabled_interrupts) {
// nonstandard interrupts have highest priority
if (enabled_interrupts >> (IRQ_M_EXT + 1))
enabled_interrupts = enabled_interrupts >> (IRQ_M_EXT + 1) << (IRQ_M_EXT + 1);
@ -849,8 +857,13 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
} else {
// Handle the trap in M-mode
set_virt(false);
reg_t vector = (state.mtvec->read() & 1) && interrupt ? 4 * bit : 0;
state.pc = (state.mtvec->read() & ~(reg_t)1) + vector;
const reg_t vector = (state.mtvec->read() & 1) && interrupt ? 4 * bit : 0;
const reg_t trap_handler_address = (state.mtvec->read() & ~(reg_t)1) + vector;
// RNMI exception vector is implementation-defined. Since we don't model
// RNMI sources, the feature isn't very useful, so pick an invalid address.
const reg_t rnmi_trap_handler_address = 0;
const bool nmie = !(state.mnstatus && !get_field(state.mnstatus->read(), MNSTATUS_NMIE));
state.pc = !nmie ? rnmi_trap_handler_address : trap_handler_address;
state.mepc->write(epc);
state.mcause->write(t.cause());
state.mtval->write(t.get_tval());

2
riscv/processor.h

@ -99,6 +99,8 @@ struct state_t
csr_t_p mideleg;
csr_t_p mcounteren;
csr_t_p mevent[N_HPMCOUNTERS];
csr_t_p mnstatus;
csr_t_p mnepc;
csr_t_p scounteren;
csr_t_p sepc;
csr_t_p stval;

4
riscv/riscv.mk.in

@ -1265,6 +1265,9 @@ riscv_insn_priv = \
sret \
wfi \
riscv_insn_smrnmi = \
mnret \
riscv_insn_svinval = \
sfence_w_inval \
sfence_inval_ir \
@ -1329,6 +1332,7 @@ riscv_insn_list = \
$(riscv_insn_ext_p) \
$(riscv_insn_priv) \
$(riscv_insn_svinval) \
$(riscv_insn_smrnmi) \
$(riscv_insn_ext_cmo) \
$(riscv_insn_ext_zicond) \

Loading…
Cancel
Save