Skip to content

Commit a55b6f7

Browse files
committed
Add SMCDELEG extension and update encoding.h
1 parent bc7461b commit a55b6f7

File tree

7 files changed

+199
-13
lines changed

7 files changed

+199
-13
lines changed

disasm/isa_parser.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
326326
extension_table[EXT_SSCSRIND] = true;
327327
} else if (ext_str == "smcntrpmf") {
328328
extension_table[EXT_SMCNTRPMF] = true;
329+
} else if (ext_str == "smcdeleg") {
330+
extension_table[EXT_SMCDELEG] = true;
329331
} else if (ext_str == "zimop") {
330332
extension_table[EXT_ZIMOP] = true;
331333
} else if (ext_str == "zcmop") {

riscv/csr_init.cc

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
#include "processor.h"
21
#include "debug_defines.h"
2+
#include "processor.h"
3+
// clang-format off
34

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

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

41-
minstret = std::make_shared<wide_counter_csr_t>(proc, CSR_MINSTRET, minstretcfg);
42-
mcycle = std::make_shared<wide_counter_csr_t>(proc, CSR_MCYCLE, mcyclecfg);
42+
minstret = std::make_shared<wide_counter_csr_t>(proc, CSR_MINSTRET, _minstretcfg);
43+
mcycle = std::make_shared<wide_counter_csr_t>(proc, CSR_MCYCLE, _mcyclecfg);
4344
time = std::make_shared<time_counter_csr_t>(proc, CSR_TIME);
4445
if (proc->extension_enabled_const(EXT_ZICNTR)) {
4546
add_csr(CSR_INSTRET, std::make_shared<counter_proxy_csr_t>(proc, CSR_INSTRET, minstret));
@@ -251,7 +252,8 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
251252
(proc->extension_enabled(EXT_SSTC) ? MENVCFG_STCE : 0) |
252253
(proc->extension_enabled(EXT_ZICFILP) ? MENVCFG_LPE : 0) |
253254
(proc->extension_enabled(EXT_ZICFISS) ? MENVCFG_SSE : 0) |
254-
(proc->extension_enabled(EXT_SSDBLTRP) ? MENVCFG_DTE : 0);
255+
(proc->extension_enabled(EXT_SSDBLTRP) ? MENVCFG_DTE : 0) |
256+
(proc->extension_enabled(EXT_SMCDELEG) ? MENVCFG_CDE : 0);
255257
menvcfg = std::make_shared<envcfg_csr_t>(proc, CSR_MENVCFG, menvcfg_mask, 0);
256258
if (xlen == 32) {
257259
add_user_csr(CSR_MENVCFG, std::make_shared<rv32_low_csr_t>(proc, CSR_MENVCFG, menvcfg));
@@ -373,16 +375,78 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
373375

374376
if (proc->extension_enabled_const(EXT_SMCNTRPMF)) {
375377
if (xlen == 32) {
376-
add_csr(CSR_MCYCLECFG, std::make_shared<rv32_low_csr_t>(proc, CSR_MCYCLECFG, mcyclecfg));
377-
add_csr(CSR_MCYCLECFGH, std::make_shared<rv32_high_csr_t>(proc, CSR_MCYCLECFGH, mcyclecfg));
378-
add_csr(CSR_MINSTRETCFG, std::make_shared<rv32_low_csr_t>(proc, CSR_MINSTRETCFG, minstretcfg));
379-
add_csr(CSR_MINSTRETCFGH, std::make_shared<rv32_high_csr_t>(proc, CSR_MINSTRETCFGH, minstretcfg));
378+
add_csr(CSR_MCYCLECFG, mcyclecfg = std::make_shared<rv32_low_csr_t>(proc, CSR_MCYCLECFG, _mcyclecfg));
379+
add_csr(CSR_MCYCLECFGH, std::make_shared<rv32_high_csr_t>(proc, CSR_MCYCLECFGH, _mcyclecfg));
380+
add_csr(CSR_MINSTRETCFG, minstretcfg = std::make_shared<rv32_low_csr_t>(proc, CSR_MINSTRETCFG, _minstretcfg));
381+
add_csr(CSR_MINSTRETCFGH, std::make_shared<rv32_high_csr_t>(proc, CSR_MINSTRETCFGH, _minstretcfg));
380382
} else {
381-
add_csr(CSR_MCYCLECFG, mcyclecfg);
382-
add_csr(CSR_MINSTRETCFG, minstretcfg);
383+
add_csr(CSR_MCYCLECFG, mcyclecfg = _mcyclecfg);
384+
add_csr(CSR_MINSTRETCFG, minstretcfg = _minstretcfg);
383385
}
384386
}
385387

386388
const reg_t srmcfg_mask = SRMCFG_MCID | SRMCFG_RCID;
387389
add_const_ext_csr(EXT_SSQOSID, CSR_SRMCFG, std::make_shared<srmcfg_csr_t>(proc, CSR_SRMCFG, srmcfg_mask, 0));
390+
391+
if (proc->extension_enabled_const(EXT_SMCDELEG) && proc->extension_enabled_const(EXT_SSCSRIND)) {
392+
add_supervisor_csr(CSR_SCOUNTINHIBIT, std::make_shared<scountinhibit_csr_t>(proc, CSR_SCOUNTINHIBIT));
393+
auto sireg = std::dynamic_pointer_cast<virtualized_indirect_csr_t>(csrmap.at(CSR_SIREG));
394+
auto sireg2 = std::dynamic_pointer_cast<virtualized_indirect_csr_t>(csrmap.at(CSR_SIREG2));
395+
auto sireg3 = std::dynamic_pointer_cast<virtualized_indirect_csr_t>(csrmap.at(CSR_SIREG3));
396+
auto sireg4 = std::dynamic_pointer_cast<virtualized_indirect_csr_t>(csrmap.at(CSR_SIREG4));
397+
auto sireg5 = std::dynamic_pointer_cast<virtualized_indirect_csr_t>(csrmap.at(CSR_SIREG5));
398+
auto sireg6 = std::dynamic_pointer_cast<virtualized_indirect_csr_t>(csrmap.at(CSR_SIREG6));
399+
auto add_proxy = [&proc, this](std::shared_ptr<virtualized_indirect_csr_t> ireg,
400+
reg_t select,
401+
reg_t csr_proxy) {
402+
assert(ireg);
403+
const auto exists = csrmap.find(csr_proxy) != csrmap.end();
404+
const auto dummy = std::make_shared<basic_csr_t>(proc, 0xdeafbeef, 0);
405+
406+
auto smc_obj_orig = std::make_shared<smcdeleg_indir_csr_t>(
407+
proc, ireg->address, select, exists ? csrmap.at(csr_proxy) : dummy , !exists);
408+
auto orig_csr = std::dynamic_pointer_cast<sscsrind_reg_csr_t>(ireg->get_orig_csr());
409+
assert(orig_csr);
410+
orig_csr->add_ireg_proxy(select, smc_obj_orig);
411+
412+
auto smc_obj_virt = std::make_shared<smcdeleg_indir_csr_t>(
413+
proc, ireg->address + 0x100, select, exists ? csrmap.at(csr_proxy) : dummy, !exists);
414+
auto virt_csr = std::dynamic_pointer_cast<sscsrind_reg_csr_t>(ireg->get_virt_csr());
415+
assert(virt_csr);
416+
virt_csr->add_ireg_proxy(select, smc_obj_virt);
417+
};
418+
419+
// We need to add all CSRs to be able to throw virtual on them, otherwise when csrind
420+
// looks for the select value it won't find any csr and thus throw illegal.
421+
// The spec states that an access to any sireg* in VS mode should raise virtual if menvcfg.cde = 1.
422+
// Most likely the motivation for this is to not leak information about which extensions the
423+
// underlying machine has implemented.
424+
add_proxy(sireg, SISELECT_SMCDELEG_START, CSR_MCYCLE);
425+
add_proxy(sireg, SISELECT_SMCDELEG_UNUSED, 0xDEADBEEF);
426+
add_proxy(sireg, SISELECT_SMCDELEG_INSTRET, CSR_MINSTRET);
427+
428+
add_proxy(sireg2, SISELECT_SMCDELEG_START, CSR_MCYCLECFG);
429+
add_proxy(sireg2, SISELECT_SMCDELEG_UNUSED, 0xDEADBEEF);
430+
add_proxy(sireg2, SISELECT_SMCDELEG_INSTRETCFG, CSR_MINSTRETCFG);
431+
432+
add_proxy(sireg4, SISELECT_SMCDELEG_START, CSR_MCYCLEH);
433+
add_proxy(sireg4, SISELECT_SMCDELEG_UNUSED, 0xDEADBEEF);
434+
add_proxy(sireg4, SISELECT_SMCDELEG_INSTRET, CSR_MINSTRETH);
435+
436+
add_proxy(sireg5, SISELECT_SMCDELEG_START, CSR_MCYCLECFGH);
437+
add_proxy(sireg5, SISELECT_SMCDELEG_UNUSED, 0xDEADBEEF);
438+
add_proxy(sireg5, SISELECT_SMCDELEG_INSTRETCFG, CSR_MINSTRETCFGH);
439+
440+
// Dummies...
441+
for (auto i = 0; i < 32; i++){
442+
add_proxy(sireg3, SISELECT_SMCDELEG_START+i, 0xDEADBEEF);
443+
add_proxy(sireg6, SISELECT_SMCDELEG_START+i, 0xDEADBEEF);
444+
}
445+
for (auto cnt = 0; cnt < 29; cnt++) {
446+
add_proxy(sireg, SISELECT_SMCDELEG_HPMCOUNTER_3 + cnt, CSR_HPMCOUNTER3 + cnt);
447+
add_proxy(sireg2, SISELECT_SMCDELEG_HPMEVENT_3 + cnt, CSR_MHPMEVENT3 + cnt);
448+
add_proxy(sireg4, SISELECT_SMCDELEG_HPMCOUNTER_3 + cnt, CSR_HPMCOUNTER3H + cnt);
449+
add_proxy(sireg5, SISELECT_SMCDELEG_HPMEVENT_3 + cnt, CSR_MHPMEVENT3H + cnt);
450+
}
451+
}
388452
}

riscv/csrs.cc

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// See LICENSE for license details.
2+
// clang-format off
23

34
// For std::any_of
45
#include <algorithm>
@@ -1675,7 +1676,11 @@ scountovf_csr_t::scountovf_csr_t(processor_t* const proc, const reg_t addr):
16751676
void scountovf_csr_t::verify_permissions(insn_t insn, bool write) const {
16761677
if (!proc->extension_enabled(EXT_SSCOFPMF))
16771678
throw trap_illegal_instruction(insn.bits());
1679+
16781680
csr_t::verify_permissions(insn, write);
1681+
1682+
if (proc->extension_enabled_const(EXT_SMCDELEG) && state->menvcfg->read() & MENVCFG_CDE && state->v)
1683+
throw trap_virtual_instruction(insn.bits());
16791684
}
16801685

16811686
reg_t scountovf_csr_t::read() const noexcept {
@@ -1951,6 +1956,89 @@ bool hstatus_csr_t::unlogged_write(const reg_t val) noexcept {
19511956
return basic_csr_t::unlogged_write(new_hstatus);
19521957
}
19531958

1959+
smcdeleg_indir_csr_t::smcdeleg_indir_csr_t(processor_t* const proc, const reg_t addr, const reg_t select, const csr_t_p csr, bool missing) :
1960+
csr_t(proc,addr), addr(addr), select(select), orig_csr(csr), missing(missing){
1961+
assert (select >= SISELECT_SMCDELEG_START and select <= SISELECT_SMCDELEG_END);
1962+
}
1963+
1964+
bool smcdeleg_indir_csr_t::unlogged_write(const reg_t val) noexcept {
1965+
reg_t write_val = 0;
1966+
if (addr == CSR_SIREG2 || addr == CSR_SIREG5){
1967+
write_val = (orig_csr->read() & MHPMEVENT_MINH) | (val & ~MHPMEVENT_MINH);
1968+
} else {
1969+
write_val = val;
1970+
}
1971+
return orig_csr->unlogged_write(write_val);
1972+
}
1973+
1974+
reg_t smcdeleg_indir_csr_t::read() const noexcept {
1975+
// MINH masking
1976+
if (addr == CSR_SIREG2 || addr == CSR_SIREG5){
1977+
return orig_csr->read() & ~MHPMEVENT_MINH;
1978+
}
1979+
return orig_csr->read();
1980+
}
1981+
void
1982+
smcdeleg_indir_csr_t::verify_permissions(insn_t insn, bool write) const{
1983+
bool is_vsi = get_field(addr, 0x300) == PRV_HS;
1984+
auto counter_offset = select - SISELECT_SMCDELEG_START;
1985+
auto counter_enabled = (state->mcounteren->read() >> counter_offset) & 1;
1986+
const bool cde = state->menvcfg->read() & MENVCFG_CDE;
1987+
1988+
assert(counter_offset >= 0);
1989+
1990+
// Counter must be active and mencfg.cde must be set (when access comes from M or HS)
1991+
if ((state->prv >= PRV_S && !state->v) && (missing || !cde || !counter_enabled)){
1992+
throw trap_illegal_instruction(insn.bits());
1993+
}
1994+
1995+
if (is_vsi){
1996+
if (state->prv >= PRV_S && !state->v){
1997+
throw trap_illegal_instruction(insn.bits());
1998+
}
1999+
else if (state->prv == PRV_S and state->v){
2000+
if (cde){
2001+
throw trap_virtual_instruction(insn.bits());
2002+
} else {
2003+
throw trap_illegal_instruction(insn.bits());
2004+
}
2005+
}
2006+
} else { // Sireg*
2007+
// An attempt from VS-mode to access any sireg* (really vsireg*) raises an illegal instruction
2008+
// exception if menvcfg.CDE = 0, or a virtual instruction exception if menvcfg.CDE = 1
2009+
if (state->v && state->prv == PRV_S){
2010+
assert(missing);
2011+
if (cde)
2012+
throw trap_virtual_instruction(insn.bits());
2013+
else
2014+
throw trap_illegal_instruction(insn.bits());
2015+
}
2016+
}
2017+
}
2018+
2019+
scountinhibit_csr_t::scountinhibit_csr_t(processor_t* const proc, const reg_t addr) : csr_t(proc, addr){}
2020+
void scountinhibit_csr_t::verify_permissions(insn_t insn, bool write) const {
2021+
// menvcfg.cde can only be set if smcdeleg is present
2022+
if (!(state->menvcfg->read() & MENVCFG_CDE))
2023+
throw trap_illegal_instruction(insn.bits());
2024+
2025+
csr_t::verify_permissions(insn, write);
2026+
2027+
if (state->v)
2028+
throw trap_virtual_instruction(insn.bits());
2029+
}
2030+
2031+
reg_t scountinhibit_csr_t::read() const noexcept {
2032+
const auto mask = state->mcounteren->read();
2033+
return state->mcountinhibit->read() & mask;
2034+
}
2035+
2036+
bool scountinhibit_csr_t::unlogged_write(const reg_t val) noexcept {
2037+
const auto masked_val = state->mcounteren->read() & val;
2038+
state->mcountinhibit->write(val);
2039+
return false;
2040+
}
2041+
19542042
scontext_csr_t::scontext_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init) :
19552043
masked_csr_t(proc, addr, mask, init){};
19562044
void scontext_csr_t::verify_permissions(insn_t insn, bool write) const {

riscv/csrs.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// See LICENSE for license details.
22
#ifndef _RISCV_CSRS_H
33
#define _RISCV_CSRS_H
4+
// clang-format off
45

56
#include "common.h"
67
#include "encoding.h"
@@ -70,6 +71,7 @@ class csr_t {
7071
// For access to written_value() and unlogged_write():
7172
friend class rv32_high_csr_t;
7273
friend class rv32_low_csr_t;
74+
friend class smcdeleg_indir_csr_t;
7375
};
7476

7577
typedef std::shared_ptr<csr_t> csr_t_p;
@@ -832,6 +834,8 @@ class virtualized_indirect_csr_t: public virtualized_csr_t {
832834
public:
833835
virtualized_indirect_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt);
834836
virtual void verify_permissions(insn_t insn, bool write) const override;
837+
auto get_orig_csr(){return virtualized_csr_t::orig_csr;}
838+
auto get_virt_csr(){return virtualized_csr_t::virt_csr;}
835839
};
836840

837841
class sscsrind_reg_csr_t : public csr_t {
@@ -913,6 +917,29 @@ class hstatus_csr_t final: public basic_csr_t {
913917
virtual bool unlogged_write(const reg_t val) noexcept override;
914918
};
915919

920+
class smcdeleg_indir_csr_t : public csr_t {
921+
public:
922+
smcdeleg_indir_csr_t(processor_t* const proc, const reg_t addr, const reg_t select, const csr_t_p csr, bool missing);
923+
protected:
924+
virtual bool unlogged_write(const reg_t val) noexcept;
925+
virtual void verify_permissions(insn_t insn, bool write) const;
926+
virtual reg_t read() const noexcept;
927+
protected:
928+
reg_t addr;
929+
reg_t select;
930+
csr_t_p orig_csr;
931+
bool missing;
932+
};
933+
934+
class scountinhibit_csr_t: public csr_t {
935+
public:
936+
scountinhibit_csr_t(processor_t* const proc, const reg_t addr);
937+
virtual void verify_permissions(insn_t insn, bool write) const override;
938+
virtual reg_t read() const noexcept override;
939+
protected:
940+
virtual bool unlogged_write(const reg_t val) noexcept override;
941+
};
942+
916943
class scontext_csr_t: public masked_csr_t {
917944
public:
918945
scontext_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init);

riscv/encoding.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
/*
66
* This file is auto-generated by running 'make' in
7-
* https://github.com/riscv/riscv-opcodes (9f70bcd)
7+
* https://github.com/riscv/riscv-opcodes (106c942)
88
*/
99

1010
#ifndef RISCV_CSR_ENCODING_H
@@ -182,11 +182,13 @@
182182
#define MENVCFG_CBZE 0x00000080
183183
#define MENVCFG_PMM 0x0000000300000000
184184
#define MENVCFG_DTE 0x0800000000000000
185+
#define MENVCFG_CDE 0x1000000000000000
185186
#define MENVCFG_ADUE 0x2000000000000000
186187
#define MENVCFG_PBMTE 0x4000000000000000
187188
#define MENVCFG_STCE 0x8000000000000000
188189

189190
#define MENVCFGH_DTE 0x08000000
191+
#define MENVCFGH_CDE 0x10000000
190192
#define MENVCFGH_ADUE 0x20000000
191193
#define MENVCFGH_PBMTE 0x40000000
192194
#define MENVCFGH_STCE 0x80000000

riscv/isa_parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ typedef enum {
7575
EXT_SMCSRIND,
7676
EXT_SSCSRIND,
7777
EXT_SMCNTRPMF,
78+
EXT_SMCDELEG,
7879
EXT_ZIMOP,
7980
EXT_ZCMOP,
8081
EXT_ZALASR,

riscv/processor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ struct state_t
172172

173173
csr_t_p ssp;
174174

175+
csr_t_p minstretcfg, mcyclecfg;
176+
175177
bool serialized; // whether timer CSRs are in a well-defined state
176178

177179
// When true, execute a single instruction and then enter debug mode. This

0 commit comments

Comments
 (0)