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);
if (proc->extension_enabled(EXT_SMCDELEG)) {
if (address >= CSR_VSIREG && address <= CSR_VSIREG6) {
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());
} 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) {
auto iselect_val = iselect->read();
if (iselect_val >= SISELECT_SMCDELEG_START && iselect_val <= SISELECT_SMCDELEG_END) {
if (address >= CSR_VSIREG && address <= CSR_VSIREG6) {
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());
} else {
if (state->prv == PRV_S) {
// An attempt from VS-mode to access any sireg* causes illegal instruction exception if menvcfg.CDE = 0
throw trap_illegal_instruction(insn.bits());
// 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());
}
}
} 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) {
}
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) {
throw trap_illegal_instruction(insn.bits());
} else {
if (state->prv == PRV_S) {
// An attempt from VS-mode to access any sireg* causes illegal instruction exception if menvcfg.CDE = 0
throw trap_illegal_instruction(insn.bits());
} else {
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