Skip to content

Add feature Smcdeleg #1913

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions disasm/isa_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
extension_table[EXT_SSCSRIND] = true;
} else if (ext_str == "smcntrpmf") {
extension_table[EXT_SMCNTRPMF] = true;
} else if (ext_str == "smcdeleg") {
extension_table[EXT_SMCDELEG] = true;
} else if (ext_str == "zimop") {
extension_table[EXT_ZIMOP] = true;
} else if (ext_str == "zcmop") {
Expand Down
107 changes: 88 additions & 19 deletions riscv/csr_init.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "processor.h"
#include "debug_defines.h"
#include "processor.h"
// clang-format off

void state_t::add_csr(reg_t addr, const csr_t_p& csr)
{
Expand Down Expand Up @@ -35,11 +36,11 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)

const reg_t minstretcfg_mask = !proc->extension_enabled_const(EXT_SMCNTRPMF) ? 0 :
MHPMEVENT_MINH | MHPMEVENT_SINH | MHPMEVENT_UINH | MHPMEVENT_VSINH | MHPMEVENT_VUINH;
auto minstretcfg = std::make_shared<smcntrpmf_csr_t>(proc, CSR_MINSTRETCFG, minstretcfg_mask, 0);
auto mcyclecfg = std::make_shared<smcntrpmf_csr_t>(proc, CSR_MCYCLECFG, minstretcfg_mask, 0);
auto _minstretcfg = std::make_shared<smcntrpmf_csr_t>(proc, CSR_MINSTRETCFG, minstretcfg_mask, 0);
auto _mcyclecfg = std::make_shared<smcntrpmf_csr_t>(proc, CSR_MCYCLECFG, minstretcfg_mask, 0);

minstret = std::make_shared<wide_counter_csr_t>(proc, CSR_MINSTRET, minstretcfg);
mcycle = std::make_shared<wide_counter_csr_t>(proc, CSR_MCYCLE, mcyclecfg);
minstret = std::make_shared<wide_counter_csr_t>(proc, CSR_MINSTRET, _minstretcfg);
mcycle = std::make_shared<wide_counter_csr_t>(proc, CSR_MCYCLE, _mcyclecfg);
time = std::make_shared<time_counter_csr_t>(proc, CSR_TIME);
if (proc->extension_enabled_const(EXT_ZICNTR)) {
add_csr(CSR_INSTRET, std::make_shared<counter_proxy_csr_t>(proc, CSR_INSTRET, minstret));
Expand Down Expand Up @@ -179,6 +180,7 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
(1 << CAUSE_SOFTWARE_CHECK_FAULT) |
(1 << CAUSE_HARDWARE_ERROR_FAULT);
add_hypervisor_csr(CSR_HEDELEG, hedeleg = std::make_shared<masked_csr_t>(proc, CSR_HEDELEG, hedeleg_mask, 0));
add_hypervisor_csr(CSR_HEDELEGH, std::make_shared<hedelegh_csr_t>(proc, CSR_HEDELEGH, 0));
add_hypervisor_csr(CSR_HCOUNTEREN, hcounteren = std::make_shared<masked_csr_t>(proc, CSR_HCOUNTEREN, counteren_mask, 0));
htimedelta = std::make_shared<basic_csr_t>(proc, CSR_HTIMEDELTA, 0);
if (xlen == 32) {
Expand Down Expand Up @@ -215,9 +217,9 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
add_csr(CSR_TINFO, std::make_shared<const_csr_t>(proc, CSR_TINFO, 0));
}
unsigned scontext_length = (xlen == 32 ? 16 : 32); // debug spec suggests 16-bit for RV32 and 32-bit for RV64
add_supervisor_csr(CSR_SCONTEXT, scontext = std::make_shared<masked_csr_t>(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0));
add_supervisor_csr(CSR_SCONTEXT, scontext = std::make_shared<scontext_csr_t>(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0));
unsigned hcontext_length = (xlen == 32 ? 6 : 13) + (proc->extension_enabled('H') ? 1 : 0); // debug spec suggest 7-bit (6-bit) for RV32 and 14-bit (13-bit) for RV64 with (without) H extension
auto hcontext = std::make_shared<masked_csr_t>(proc, CSR_HCONTEXT, (reg_t(1) << hcontext_length) - 1, 0);
auto hcontext = std::make_shared<hcontext_csr_t>(proc, CSR_HCONTEXT, (reg_t(1) << hcontext_length) - 1, 0);
add_hypervisor_csr(CSR_HCONTEXT, hcontext);
add_csr(CSR_MCONTEXT, mcontext = std::make_shared<proxy_csr_t>(proc, CSR_MCONTEXT, hcontext));
add_csr(CSR_MSECCFG, mseccfg = std::make_shared<mseccfg_csr_t>(proc, CSR_MSECCFG));
Expand Down Expand Up @@ -250,7 +252,8 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
(proc->extension_enabled(EXT_SSTC) ? MENVCFG_STCE : 0) |
(proc->extension_enabled(EXT_ZICFILP) ? MENVCFG_LPE : 0) |
(proc->extension_enabled(EXT_ZICFISS) ? MENVCFG_SSE : 0) |
(proc->extension_enabled(EXT_SSDBLTRP) ? MENVCFG_DTE : 0);
(proc->extension_enabled(EXT_SSDBLTRP) ? MENVCFG_DTE : 0) |
(proc->extension_enabled(EXT_SMCDELEG) ? MENVCFG_CDE : 0);
menvcfg = std::make_shared<envcfg_csr_t>(proc, CSR_MENVCFG, menvcfg_mask, 0);
if (xlen == 32) {
add_user_csr(CSR_MENVCFG, std::make_shared<rv32_low_csr_t>(proc, CSR_MENVCFG, menvcfg));
Expand Down Expand Up @@ -284,8 +287,11 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
const reg_t sstateen0_mask = (proc->extension_enabled(EXT_ZFINX) ? SSTATEEN0_FCSR : 0) |
(proc->extension_enabled(EXT_ZCMT) ? SSTATEEN0_JVT : 0) |
SSTATEEN0_CS;
const reg_t hstateen0_mask = sstateen0_mask | HSTATEEN0_SENVCFG | HSTATEEN_SSTATEEN;
const reg_t mstateen0_mask = hstateen0_mask | (proc->extension_enabled(EXT_SSQOSID) ? MSTATEEN0_PRIV114 : 0);
const reg_t hstateen0_mask = sstateen0_mask | HSTATEEN0_SENVCFG | HSTATEEN_SSTATEEN |
(proc->extension_enabled(EXT_SSCSRIND) ? HSTATEEN0_CSRIND : 0) |
(proc->get_cfg().trigger_count > 0 ? HSTATEEN0_SCONTEXT : 0);
const reg_t mstateen0_mask = hstateen0_mask | MSTATEEN0_PRIV113 |
(proc->extension_enabled(EXT_SSQOSID) ? MSTATEEN0_PRIV114 : 0);
for (int i = 0; i < 4; i++) {
const reg_t mstateen_mask = i == 0 ? mstateen0_mask : MSTATEEN_HSTATEEN;
mstateen[i] = std::make_shared<masked_csr_t>(proc, CSR_MSTATEEN0 + i, mstateen_mask, 0);
Expand Down Expand Up @@ -349,11 +355,12 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
}

if (proc->extension_enabled_const(EXT_SSCSRIND)) {
csr_t_p vsiselect = std::make_shared<basic_csr_t>(proc, CSR_VSISELECT, 0);
auto vsiselect = std::make_shared<sscsrind_select_csr_t>(proc, CSR_VSISELECT, 0);
add_hypervisor_csr(CSR_VSISELECT, vsiselect);

csr_t_p siselect = std::make_shared<basic_csr_t>(proc, CSR_SISELECT, 0);
add_supervisor_csr(CSR_SISELECT, std::make_shared<virtualized_csr_t>(proc, siselect, vsiselect));
auto siselect = std::make_shared<sscsrind_select_csr_t>(proc, CSR_SISELECT, 0);
// Correct virtualized type?
add_supervisor_csr(CSR_SISELECT, std::make_shared<virtualized_select_indirect_csr_t>(proc, siselect, vsiselect));

const reg_t vsireg_csrs[] = { CSR_VSIREG, CSR_VSIREG2, CSR_VSIREG3, CSR_VSIREG4, CSR_VSIREG5, CSR_VSIREG6 };
const reg_t sireg_csrs[] = { CSR_SIREG, CSR_SIREG2, CSR_SIREG3, CSR_SIREG4, CSR_SIREG5, CSR_SIREG6 };
Expand All @@ -368,16 +375,78 @@ 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));
add_csr(CSR_MCYCLECFG, 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, 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);
add_csr(CSR_MCYCLECFG, mcyclecfg = _mcyclecfg);
add_csr(CSR_MINSTRETCFG, 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));

if (proc->extension_enabled_const(EXT_SMCDELEG) && proc->extension_enabled_const(EXT_SSCSRIND)) {
add_supervisor_csr(CSR_SCOUNTINHIBIT, std::make_shared<scountinhibit_csr_t>(proc, CSR_SCOUNTINHIBIT));
auto sireg = std::dynamic_pointer_cast<virtualized_indirect_csr_t>(csrmap.at(CSR_SIREG));
auto sireg2 = std::dynamic_pointer_cast<virtualized_indirect_csr_t>(csrmap.at(CSR_SIREG2));
auto sireg3 = std::dynamic_pointer_cast<virtualized_indirect_csr_t>(csrmap.at(CSR_SIREG3));
auto sireg4 = std::dynamic_pointer_cast<virtualized_indirect_csr_t>(csrmap.at(CSR_SIREG4));
auto sireg5 = std::dynamic_pointer_cast<virtualized_indirect_csr_t>(csrmap.at(CSR_SIREG5));
auto sireg6 = std::dynamic_pointer_cast<virtualized_indirect_csr_t>(csrmap.at(CSR_SIREG6));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like addition of sireg* should depend only on Sscsrind, not Smcdeleg (or Ssccfg). I assume we'll eventually add support for things like Smctr/Ssctr, which also use sireg*.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! Thanks for reviewing. This doesn't add sireg* as a csr it only casts the existing sireg* CSRs to the correct type to be able to use them. Sireg* is not directly available in this scope which is why I retrieve them from the csrmap.

auto add_proxy = [&proc, this](std::shared_ptr<virtualized_indirect_csr_t> ireg,
reg_t select,
reg_t csr_proxy) {
assert(ireg);
const auto exists = csrmap.find(csr_proxy) != csrmap.end();
const auto dummy = std::make_shared<basic_csr_t>(proc, 0xdeafbeef, 0);

auto smc_obj_orig = std::make_shared<smcdeleg_indir_csr_t>(
proc, ireg->address, select, exists ? csrmap.at(csr_proxy) : dummy , !exists);
auto orig_csr = std::dynamic_pointer_cast<sscsrind_reg_csr_t>(ireg->get_orig_csr());
assert(orig_csr);
orig_csr->add_ireg_proxy(select, smc_obj_orig);

auto smc_obj_virt = std::make_shared<smcdeleg_indir_csr_t>(
proc, ireg->address + 0x100, select, exists ? csrmap.at(csr_proxy) : dummy, !exists);
auto virt_csr = std::dynamic_pointer_cast<sscsrind_reg_csr_t>(ireg->get_virt_csr());
assert(virt_csr);
virt_csr->add_ireg_proxy(select, smc_obj_virt);
};

// We need to add all CSRs to be able to throw virtual on them, otherwise when csrind
// looks for the select value it won't find any csr and thus throw illegal.
// The spec states that an access to any sireg* in VS mode should raise virtual if menvcfg.cde = 1.
// Most likely the motivation for this is to not leak information about which extensions the
// underlying machine has implemented.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The VIE also allows the hypervisor to emulate the state (counter, in this case) access

add_proxy(sireg, SISELECT_SMCDELEG_START, CSR_MCYCLE);
add_proxy(sireg, SISELECT_SMCDELEG_UNUSED, 0xDEADBEEF);
add_proxy(sireg, SISELECT_SMCDELEG_INSTRET, CSR_MINSTRET);

add_proxy(sireg2, SISELECT_SMCDELEG_START, CSR_MCYCLECFG);
add_proxy(sireg2, SISELECT_SMCDELEG_UNUSED, 0xDEADBEEF);
add_proxy(sireg2, SISELECT_SMCDELEG_INSTRETCFG, CSR_MINSTRETCFG);

add_proxy(sireg4, SISELECT_SMCDELEG_START, CSR_MCYCLEH);
add_proxy(sireg4, SISELECT_SMCDELEG_UNUSED, 0xDEADBEEF);
add_proxy(sireg4, SISELECT_SMCDELEG_INSTRET, CSR_MINSTRETH);

add_proxy(sireg5, SISELECT_SMCDELEG_START, CSR_MCYCLECFGH);
add_proxy(sireg5, SISELECT_SMCDELEG_UNUSED, 0xDEADBEEF);
add_proxy(sireg5, SISELECT_SMCDELEG_INSTRETCFG, CSR_MINSTRETCFGH);

// Dummies...
for (auto i = 0; i < 32; i++){
add_proxy(sireg3, SISELECT_SMCDELEG_START+i, 0xDEADBEEF);
add_proxy(sireg6, SISELECT_SMCDELEG_START+i, 0xDEADBEEF);
}
for (auto cnt = 0; cnt < 29; cnt++) {
add_proxy(sireg, SISELECT_SMCDELEG_HPMCOUNTER_3 + cnt, CSR_HPMCOUNTER3 + cnt);
add_proxy(sireg2, SISELECT_SMCDELEG_HPMEVENT_3 + cnt, CSR_MHPMEVENT3 + cnt);
add_proxy(sireg4, SISELECT_SMCDELEG_HPMCOUNTER_3 + cnt, CSR_HPMCOUNTER3H + cnt);
add_proxy(sireg5, SISELECT_SMCDELEG_HPMEVENT_3 + cnt, CSR_MHPMEVENT3H + cnt);
}
}
}
Loading