Browse Source

fixed smcdeleg to be limited to, holds a value in the range 0x40-0x5F, from priv AIA section 9.1

pull/2204/head
muhammad.moiz.hussain 7 months ago
parent
commit
49dea04810
  1. 73
      riscv/csrs.cc

73
riscv/csrs.cc

@ -1864,54 +1864,57 @@ void sscsrind_reg_csr_t::verify_permissions(insn_t insn, bool write) const {
csr_t::verify_permissions(insn, write); csr_t::verify_permissions(insn, write);
if (proc->extension_enabled(EXT_SMCDELEG)) { if (proc->extension_enabled(EXT_SMCDELEG)) {
if (address >= CSR_VSIREG && address <= CSR_VSIREG6) { auto iselect_val = iselect->read();
if (!state->v) { if (iselect_val >= SISELECT_SMCDELEG_START && iselect_val <= SISELECT_SMCDELEG_END) {
// An attempt to access any vsireg* from M or S mode raises an illegal instruction exception. if (address >= CSR_VSIREG && address <= CSR_VSIREG6) {
throw trap_illegal_instruction(insn.bits());
} else {
if (state->prv == PRV_S) {
// An attempt from VS-mode to access any vsireg raises an illegal instruction
// exception if menvcfg.CDE = 0, or a virtual instruction exception if menvcfg.CDE = 1
if ((state->menvcfg->read() & MENVCFG_CDE) != MENVCFG_CDE) {
throw trap_illegal_instruction(insn.bits());
} else {
throw trap_virtual_instruction(insn.bits());
}
} else {
throw trap_virtual_instruction(insn.bits());
}
}
}
if (address >= CSR_SIREG && address <= CSR_SIREG6) {
// attempts to access any sireg* when menvcfg.CDE = 0;
if ((state->menvcfg->read() & MENVCFG_CDE) != MENVCFG_CDE) {
if (!state->v) { if (!state->v) {
// An attempt to access any vsireg* from M or S mode raises an illegal instruction exception.
throw trap_illegal_instruction(insn.bits()); throw trap_illegal_instruction(insn.bits());
} else { } else {
if (state->prv == PRV_S) { if (state->prv == PRV_S) {
// An attempt from VS-mode to access any sireg* causes illegal instruction exception if menvcfg.CDE = 0 // An attempt from VS-mode to access any vsireg raises an illegal instruction
throw trap_illegal_instruction(insn.bits()); // exception if menvcfg.CDE = 0, or a virtual instruction exception if menvcfg.CDE = 1
if ((state->menvcfg->read() & MENVCFG_CDE) != MENVCFG_CDE) {
throw trap_illegal_instruction(insn.bits());
} else {
throw trap_virtual_instruction(insn.bits());
}
} else { } else {
throw trap_virtual_instruction(insn.bits()); throw trap_virtual_instruction(insn.bits());
} }
} }
} else { }
// menvcfg.CDE = 1; if (address >= CSR_SIREG && address <= CSR_SIREG6) {
if (state->v) { // attempts to access any sireg* when menvcfg.CDE = 0;
// An attempt from VS-mode to access any sireg* causes a virtual instruction exception if menvcfg.CDE = 1 if ((state->menvcfg->read() & MENVCFG_CDE) != MENVCFG_CDE) {
throw trap_virtual_instruction(insn.bits()); if (!state->v) {
} throw trap_illegal_instruction(insn.bits());
// counter selected by siselect is not delegated to S-mode (the corresponding bit in mcounteren = 0). } else {
auto iselect_addr = iselect->read(); if (state->prv == PRV_S) {
if (iselect_addr >= SISELECT_SMCDELEG_START && iselect_addr <= SISELECT_SMCDELEG_END) { // An attempt from VS-mode to access any sireg* causes illegal instruction exception if menvcfg.CDE = 0
reg_t counter_id_offset = iselect_addr - SISELECT_SMCDELEG_START;
if (!(state->mcounteren->read() & (1U << counter_id_offset))) {
if (!state->v) {
throw trap_illegal_instruction(insn.bits()); throw trap_illegal_instruction(insn.bits());
} else { } else {
throw trap_virtual_instruction(insn.bits()); throw trap_virtual_instruction(insn.bits());
} }
} }
} else {
// menvcfg.CDE = 1;
if (state->v) {
// An attempt from VS-mode to access any sireg* causes a virtual instruction exception if menvcfg.CDE = 1
throw trap_virtual_instruction(insn.bits());
}
// counter selected by siselect is not delegated to S-mode (the corresponding bit in mcounteren = 0).
auto iselect_addr = iselect->read();
if (iselect_addr >= SISELECT_SMCDELEG_START && iselect_addr <= SISELECT_SMCDELEG_END) {
reg_t counter_id_offset = iselect_addr - SISELECT_SMCDELEG_START;
if (!(state->mcounteren->read() & (1U << counter_id_offset))) {
if (!state->v) {
throw trap_illegal_instruction(insn.bits());
} else {
throw trap_virtual_instruction(insn.bits());
}
}
}
} }
} }
} }

Loading…
Cancel
Save