Browse Source

Merge pull request #2204 from mmhus/mmhus/mireg-sireg-fixes

Mmhus/mireg sireg fixes #2188, #2202, #2203
pull/2205/head
Andrew Waterman 3 months ago
committed by GitHub
parent
commit
63c60931bc
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 46
      riscv/csr_init.cc
  2. 84
      riscv/csrs.cc
  3. 6
      riscv/processor.h

46
riscv/csr_init.cc

@ -80,6 +80,28 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
add_csr(CSR_MINSTRET, minstret);
add_csr(CSR_MCYCLE, mcycle);
}
if (proc->extension_enabled_const(EXT_SMCNTRPMF)) {
if (xlen == 32) {
add_csr(CSR_MCYCLECFG, std::make_shared<rv32_low_csr_t>(proc, CSR_MCYCLECFG, mcyclecfg));
add_csr(CSR_MCYCLECFGH, std::make_shared<rv32_high_csr_t>(proc, CSR_MCYCLECFGH, mcyclecfg));
add_csr(CSR_MINSTRETCFG, std::make_shared<rv32_low_csr_t>(proc, CSR_MINSTRETCFG, minstretcfg));
add_csr(CSR_MINSTRETCFGH, std::make_shared<rv32_high_csr_t>(proc, CSR_MINSTRETCFGH, minstretcfg));
} else {
add_csr(CSR_MCYCLECFG, mcyclecfg);
add_csr(CSR_MINSTRETCFG, minstretcfg);
}
if (proc->extension_enabled_const(EXT_SMCDELEG)) {
if (xlen == 32) {
cyclecfg = std::make_shared<counter_proxy_csr_t>(proc, CSR_MCYCLECFG, csrmap[CSR_MCYCLECFG]);
cyclecfgh = std::make_shared<counter_proxy_csr_t>(proc, CSR_MCYCLECFGH, csrmap[CSR_MCYCLECFGH]);
instretcfg = std::make_shared<counter_proxy_csr_t>(proc, CSR_MINSTRETCFG, csrmap[CSR_MINSTRETCFG]);
instretcfgh = std::make_shared<counter_proxy_csr_t>(proc, CSR_MINSTRETCFGH, csrmap[CSR_MINSTRETCFGH]);
} else {
instretcfg = std::make_shared<counter_proxy_csr_t>(proc, CSR_MINSTRETCFG, csrmap[CSR_MINSTRETCFG]);
cyclecfg = std::make_shared<counter_proxy_csr_t>(proc, CSR_MCYCLECFG, csrmap[CSR_MCYCLECFG]);
}
}
}
for (reg_t i = 0; i < N_HPMCOUNTERS; ++i) {
const reg_t which_mevent = CSR_MHPMEVENT3 + i;
const reg_t which_meventh = CSR_MHPMEVENT3H + i;
@ -443,8 +465,8 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
if (proc->extension_enabled(EXT_SSCCFG) || proc->extension_enabled(EXT_SMCDELEG)) {
// case CSR_SIREG
if (proc->extension_enabled_const(EXT_ZICNTR)) {
sireg->add_ireg_proxy(SISELECT_SMCDELEG_START, mcycle);
sireg->add_ireg_proxy(SISELECT_SMCDELEG_INSTRET, minstret);
sireg->add_ireg_proxy(SISELECT_SMCDELEG_START, csrmap[CSR_CYCLE]);
sireg->add_ireg_proxy(SISELECT_SMCDELEG_INSTRET, csrmap[CSR_INSTRET]);
}
if (proc->extension_enabled_const(EXT_ZIHPM)) {
for (size_t j = 0; j < (SISELECT_SMCDELEG_END - SISELECT_SMCDELEG_HPMEVENT_3 + 1); j++)
@ -478,8 +500,8 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
break;
case CSR_SIREG2:
if (proc->extension_enabled_const(EXT_ZICNTR)) {
sireg->add_ireg_proxy(SISELECT_SMCDELEG_START, mcyclecfg);
sireg->add_ireg_proxy(SISELECT_SMCDELEG_INSTRETCFG, minstretcfg);
sireg->add_ireg_proxy(SISELECT_SMCDELEG_START, cyclecfg);
sireg->add_ireg_proxy(SISELECT_SMCDELEG_INSTRETCFG, instretcfg);
}
if (proc->extension_enabled_const(EXT_ZIHPM)) {
for (size_t j = 0; j < (SISELECT_SMCDELEG_END - SISELECT_SMCDELEG_HPMEVENT_3 + 1); j++)
@ -489,8 +511,8 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
case CSR_SIREG5:
if (xlen == 32) {
if (proc->extension_enabled_const(EXT_ZICNTR)) {
sireg->add_ireg_proxy(SISELECT_SMCDELEG_START, mcycle);
sireg->add_ireg_proxy(SISELECT_SMCDELEG_INSTRET, minstret);
sireg->add_ireg_proxy(SISELECT_SMCDELEG_START, cyclecfgh);
sireg->add_ireg_proxy(SISELECT_SMCDELEG_INSTRET, instretcfgh);
}
if (proc->extension_enabled_const(EXT_ZIHPM)) {
for (size_t j = 0; j < (SISELECT_SMCDELEG_END - SISELECT_SMCDELEG_HPMEVENT_3); j++)
@ -506,18 +528,6 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
}
}
if (proc->extension_enabled_const(EXT_SMCNTRPMF)) {
if (xlen == 32) {
add_csr(CSR_MCYCLECFG, std::make_shared<rv32_low_csr_t>(proc, CSR_MCYCLECFG, mcyclecfg));
add_csr(CSR_MCYCLECFGH, std::make_shared<rv32_high_csr_t>(proc, CSR_MCYCLECFGH, mcyclecfg));
add_csr(CSR_MINSTRETCFG, std::make_shared<rv32_low_csr_t>(proc, CSR_MINSTRETCFG, minstretcfg));
add_csr(CSR_MINSTRETCFGH, std::make_shared<rv32_high_csr_t>(proc, CSR_MINSTRETCFGH, minstretcfg));
} else {
add_csr(CSR_MCYCLECFG, mcyclecfg);
add_csr(CSR_MINSTRETCFG, minstretcfg);
}
}
const reg_t srmcfg_mask = SRMCFG_MCID | SRMCFG_RCID;
add_const_ext_csr(EXT_SSQOSID, CSR_SRMCFG, std::make_shared<srmcfg_csr_t>(proc, CSR_SRMCFG, srmcfg_mask, 0));

84
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());
}
}
}
}
}
}
@ -1919,7 +1922,16 @@ void sscsrind_reg_csr_t::verify_permissions(insn_t insn, bool write) const {
csr_t_p proxy_csr = get_reg();
if (proxy_csr == nullptr) {
throw trap_illegal_instruction(insn.bits());
// An attempt from VS-mode to access any inaccessible sireg* causes virtual instruction exception when AIA is enabled
if (proc->extension_enabled_const(EXT_SMAIA)) {
if (state->prv == PRV_S && state->v) {
throw trap_virtual_instruction(insn.bits());
} else {
throw trap_illegal_instruction(insn.bits());
}
} else {
throw trap_illegal_instruction(insn.bits());
}
}
proxy_csr->verify_permissions(insn, write);
}

6
riscv/processor.h

@ -179,6 +179,12 @@ struct state_t
time_counter_csr_t_p time;
csr_t_p time_proxy;
csr_t_p instretcfg;
csr_t_p instretcfgh;
csr_t_p cyclecfg;
csr_t_p cyclecfgh;
csr_t_p stimecmp;
csr_t_p vstimecmp;

Loading…
Cancel
Save