Skip to content

Commit 0797c21

Browse files
committed
Add Ssdbltrp
1 parent 4a2da91 commit 0797c21

File tree

10 files changed

+93
-16
lines changed

10 files changed

+93
-16
lines changed

disasm/isa_parser.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
347347
if (new_elen != 32 && new_elen != 64)
348348
bad_isa_string(str, ("Invalid Zve string: " + ext_str).c_str());
349349
elen = std::max(elen, new_elen);
350+
} else if (ext_str == "ssdbltrp") {
351+
extension_table[EXT_SSDBLTRP] = true;
350352
} else if (ext_str[0] == 'x') {
351353
extension_table['X'] = true;
352354
if (ext_str.size() == 1) {

riscv/csrs.cc

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ reg_t base_status_csr_t::compute_sstatus_write_mask() const noexcept {
421421
| (proc->any_custom_extensions() ? SSTATUS_XS : 0)
422422
| (has_vs ? SSTATUS_VS : 0)
423423
| (proc->extension_enabled(EXT_ZICFILP) ? SSTATUS_SPELP : 0)
424+
| (proc->extension_enabled(EXT_SSDBLTRP) ? SSTATUS_SDT : 0)
424425
;
425426
}
426427

@@ -464,29 +465,50 @@ vsstatus_csr_t::vsstatus_csr_t(processor_t* const proc, const reg_t addr):
464465
}
465466

466467
bool vsstatus_csr_t::unlogged_write(const reg_t val) noexcept {
467-
const reg_t newval = (this->val & ~sstatus_write_mask) | (val & sstatus_write_mask);
468+
const reg_t hDTE = (state->henvcfg->read() & HENVCFG_DTE);
469+
const reg_t adj_write_mask = sstatus_write_mask & ~(hDTE ? 0 : SSTATUS_SDT);
470+
reg_t newval = (this->val & ~adj_write_mask) | (val & adj_write_mask);
471+
472+
newval = (newval & SSTATUS_SDT) ? (newval & ~SSTATUS_SIE) : newval;
473+
468474
if (state->v) maybe_flush_tlb(newval);
469475
this->val = adjust_sd(newval);
470476
return true;
471477
}
472478

479+
reg_t vsstatus_csr_t::read() const noexcept {
480+
const reg_t hDTE = state->henvcfg->read() & HENVCFG_DTE;
481+
const reg_t adj_read_mask = sstatus_read_mask & ~(hDTE ? 0 : SSTATUS_SDT);
482+
return this->val & adj_read_mask;
483+
}
484+
473485
// implement class sstatus_proxy_csr_t
474486
sstatus_proxy_csr_t::sstatus_proxy_csr_t(processor_t* const proc, const reg_t addr, mstatus_csr_t_p mstatus):
475487
base_status_csr_t(proc, addr),
476488
mstatus(mstatus) {
477489
}
478490

479491
bool sstatus_proxy_csr_t::unlogged_write(const reg_t val) noexcept {
480-
const reg_t new_mstatus = (mstatus->read() & ~sstatus_write_mask) | (val & sstatus_write_mask);
492+
const reg_t mDTE = (state->menvcfg->read() & MENVCFG_DTE);
493+
const reg_t adj_write_mask = sstatus_write_mask & ~(mDTE ? 0 : SSTATUS_SDT);
494+
reg_t new_mstatus = (mstatus->read() & ~adj_write_mask) | (val & adj_write_mask);
495+
496+
new_mstatus = (new_mstatus & SSTATUS_SDT) ? (new_mstatus & ~SSTATUS_SIE) : new_mstatus;
481497

482498
// On RV32 this will only log the low 32 bits, so make sure we're
483499
// not modifying anything in the upper 32 bits.
484-
assert((sstatus_write_mask & 0xffffffffU) == sstatus_write_mask);
500+
assert((adj_write_mask & 0xffffffffU) == adj_write_mask);
485501

486502
mstatus->write(new_mstatus);
487503
return false; // avoid double logging: already logged by mstatus->write()
488504
}
489505

506+
reg_t sstatus_proxy_csr_t::read() const noexcept {
507+
const reg_t mDTE = state->menvcfg->read() & MENVCFG_DTE;
508+
const reg_t adj_read_mask = sstatus_read_mask & ~(mDTE ? 0 : SSTATUS_SDT);
509+
return mstatus->read() & adj_read_mask;
510+
}
511+
490512
// implement class mstatus_csr_t
491513
mstatus_csr_t::mstatus_csr_t(processor_t* const proc, const reg_t addr):
492514
base_status_csr_t(proc, addr),
@@ -506,6 +528,7 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept {
506528
| (has_gva ? MSTATUS_GVA : 0)
507529
| (has_mpv ? MSTATUS_MPV : 0)
508530
| (proc->extension_enabled(EXT_ZICFILP) ? (MSTATUS_SPELP | MSTATUS_MPELP) : 0)
531+
| (proc->extension_enabled(EXT_SSDBLTRP) ? SSTATUS_SDT : 0)
509532
;
510533

511534
const reg_t requested_mpp = proc->legalize_privilege(get_field(val, MSTATUS_MPP));
@@ -1548,7 +1571,7 @@ void henvcfg_csr_t::verify_permissions(insn_t insn, bool write) const {
15481571
}
15491572

15501573
bool henvcfg_csr_t::unlogged_write(const reg_t val) noexcept {
1551-
const reg_t mask = menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE);
1574+
const reg_t mask = menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE | MENVCFG_DTE);
15521575
return envcfg_csr_t::unlogged_write((masked_csr_t::read() & ~mask) | (val & mask));
15531576
}
15541577

@@ -1765,3 +1788,13 @@ void ssp_csr_t::verify_permissions(insn_t insn, bool write) const {
17651788
DECLARE_XENVCFG_VARS(SSE);
17661789
require_envcfg(SSE);
17671790
}
1791+
1792+
mtval2_csr_t::mtval2_csr_t(processor_t* const proc, const reg_t addr):
1793+
hypervisor_csr_t(proc, addr) {
1794+
}
1795+
1796+
void mtval2_csr_t::verify_permissions(insn_t insn, bool write) const {
1797+
basic_csr_t::verify_permissions(insn, write);
1798+
if (!proc->extension_enabled('H') && !proc->extension_enabled(EXT_SSDBLTRP))
1799+
throw trap_illegal_instruction(insn.bits());
1800+
}

riscv/csrs.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -234,13 +234,12 @@ typedef std::shared_ptr<base_status_csr_t> base_status_csr_t_p;
234234

235235
// For vsstatus, which is its own separate architectural register
236236
// (unlike sstatus)
237+
// vstatus.sdt is read_only 0 when henvcfg.dte = 0
237238
class vsstatus_csr_t final: public base_status_csr_t {
238239
public:
239240
vsstatus_csr_t(processor_t* const proc, const reg_t addr);
240241

241-
reg_t read() const noexcept override {
242-
return val;
243-
}
242+
virtual reg_t read() const noexcept override;
244243

245244
protected:
246245
virtual bool unlogged_write(const reg_t val) noexcept override;
@@ -300,13 +299,12 @@ class rv32_high_csr_t: public csr_t {
300299
csr_t_p orig;
301300
};
302301

302+
// sstatus.sdt is read_only 0 when menvcfg.dte = 0
303303
class sstatus_proxy_csr_t final: public base_status_csr_t {
304304
public:
305305
sstatus_proxy_csr_t(processor_t* const proc, const reg_t addr, mstatus_csr_t_p mstatus);
306306

307-
reg_t read() const noexcept override {
308-
return mstatus->read() & sstatus_read_mask;
309-
}
307+
virtual reg_t read() const noexcept override;
310308

311309
protected:
312310
virtual bool unlogged_write(const reg_t val) noexcept override;
@@ -480,12 +478,13 @@ class envcfg_csr_t: public masked_csr_t {
480478
// henvcfg.pbmte is read_only 0 when menvcfg.pbmte = 0
481479
// henvcfg.stce is read_only 0 when menvcfg.stce = 0
482480
// henvcfg.hade is read_only 0 when menvcfg.hade = 0
481+
// henvcfg.dte is read_only 0 when menvcfg.dte = 0
483482
class henvcfg_csr_t final: public envcfg_csr_t {
484483
public:
485484
henvcfg_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init, csr_t_p menvcfg);
486485

487486
reg_t read() const noexcept override {
488-
return (menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE)) & masked_csr_t::read();
487+
return (menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE | MENVCFG_DTE)) & masked_csr_t::read();
489488
}
490489

491490
virtual void verify_permissions(insn_t insn, bool write) const override;
@@ -880,4 +879,11 @@ class ssp_csr_t final : public masked_csr_t {
880879
ssp_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init);
881880
virtual void verify_permissions(insn_t insn, bool write) const override;
882881
};
882+
883+
// mtval2 CSR provided by H extension - but required if Ssdbltrp is implemented
884+
class mtval2_csr_t: public hypervisor_csr_t {
885+
public:
886+
mtval2_csr_t(processor_t* const proc, const reg_t addr);
887+
virtual void verify_permissions(insn_t insn, bool write) const override;
888+
};
883889
#endif

riscv/encoding.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2891,6 +2891,7 @@
28912891
#define CAUSE_FETCH_PAGE_FAULT 0xc
28922892
#define CAUSE_LOAD_PAGE_FAULT 0xd
28932893
#define CAUSE_STORE_PAGE_FAULT 0xf
2894+
#define CAUSE_DOUBLE_TRAP 0x10
28942895
#define CAUSE_SOFTWARE_CHECK_FAULT 0x12
28952896
#define CAUSE_HARDWARE_ERROR_FAULT 0x13
28962897
#define CAUSE_FETCH_GUEST_PAGE_FAULT 0x14
@@ -4435,6 +4436,7 @@ DECLARE_CAUSE("machine ecall", CAUSE_MACHINE_ECALL)
44354436
DECLARE_CAUSE("fetch page fault", CAUSE_FETCH_PAGE_FAULT)
44364437
DECLARE_CAUSE("load page fault", CAUSE_LOAD_PAGE_FAULT)
44374438
DECLARE_CAUSE("store page fault", CAUSE_STORE_PAGE_FAULT)
4439+
DECLARE_CAUSE("double trap", CAUSE_DOUBLE_TRAP)
44384440
DECLARE_CAUSE("software check fault", CAUSE_SOFTWARE_CHECK_FAULT)
44394441
DECLARE_CAUSE("hardware error fault", CAUSE_HARDWARE_ERROR_FAULT)
44404442
DECLARE_CAUSE("fetch guest page fault", CAUSE_FETCH_GUEST_PAGE_FAULT)

riscv/insns/dret.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ p->set_privilege(STATE.dcsr->prv, STATE.dcsr->v);
77
if (STATE.prv < PRV_M)
88
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MPRV);
99

10+
if (STATE.dcsr->prv == PRV_U || STATE.dcsr->v)
11+
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_SDT);
12+
13+
if (STATE.dcsr->v && STATE.dcsr->prv == PRV_U)
14+
STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT);
15+
1016
/* We're not in Debug Mode anymore. */
1117
STATE.debug_mode = false;
1218

riscv/insns/mret.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ if (ZICFILP_xLPE(prev_virt, prev_prv)) {
1313
STATE.elp = static_cast<elp_t>(get_field(s, MSTATUS_MPELP));
1414
}
1515
s = set_field(s, MSTATUS_MPELP, elp_t::NO_LP_EXPECTED);
16+
if (prev_prv == PRV_U || prev_virt)
17+
s = set_field(s, MSTATUS_SDT, 0);
18+
if (prev_virt && prev_prv == PRV_U)
19+
STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT);
1620
STATE.mstatus->write(s);
1721
if (STATE.mstatush) STATE.mstatush->write(s >> 32); // log mstatush change
1822
STATE.tcontrol->write((STATE.tcontrol->read() & CSR_TCONTROL_MPTE) ? (CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE) : 0);

riscv/insns/sret.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,12 @@ if (ZICFILP_xLPE(prev_virt, prev_prv)) {
2727
STATE.elp = static_cast<elp_t>(get_field(s, SSTATUS_SPELP));
2828
}
2929
s = set_field(s, SSTATUS_SPELP, elp_t::NO_LP_EXPECTED);
30+
31+
if (STATE.prv == PRV_S) {
32+
s = set_field(s, SSTATUS_SDT, 0);
33+
if (!STATE.v && prev_virt && prev_prv == PRV_U)
34+
STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT);
35+
}
36+
3037
STATE.sstatus->write(s);
3138
p->set_privilege(prev_prv, prev_virt);

riscv/isa_parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ typedef enum {
8181
EXT_SSQOSID,
8282
EXT_ZICFILP,
8383
EXT_ZICFISS,
84+
EXT_SSDBLTRP,
8485
NUM_ISA_EXTENSIONS
8586
} isa_extension_t;
8687

riscv/processor.cc

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
295295
nonvirtual_scause = std::make_shared<cause_csr_t>(proc, CSR_SCAUSE);
296296
csrmap[CSR_VSCAUSE] = vscause = std::make_shared<cause_csr_t>(proc, CSR_VSCAUSE);
297297
csrmap[CSR_SCAUSE] = scause = std::make_shared<virtualized_csr_t>(proc, nonvirtual_scause, vscause);
298-
csrmap[CSR_MTVAL2] = mtval2 = std::make_shared<hypervisor_csr_t>(proc, CSR_MTVAL2);
298+
csrmap[CSR_MTVAL2] = mtval2 = std::make_shared<mtval2_csr_t>(proc, CSR_MTVAL2);
299299
csrmap[CSR_MTINST] = mtinst = std::make_shared<hypervisor_csr_t>(proc, CSR_MTINST);
300300
const reg_t hstatus_init = set_field((reg_t)0, HSTATUS_VSXL, xlen_to_uxl(proc->get_const_xlen()));
301301
const reg_t hstatus_mask = HSTATUS_VTSR | HSTATUS_VTW
@@ -391,7 +391,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
391391
(proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0) |
392392
(proc->extension_enabled(EXT_SSTC) ? MENVCFG_STCE : 0) |
393393
(proc->extension_enabled(EXT_ZICFILP) ? MENVCFG_LPE : 0) |
394-
(proc->extension_enabled(EXT_ZICFISS) ? MENVCFG_SSE : 0);
394+
(proc->extension_enabled(EXT_ZICFISS) ? MENVCFG_SSE : 0) |
395+
(proc->extension_enabled(EXT_SSDBLTRP) ? MENVCFG_DTE : 0);
395396
const reg_t menvcfg_init = (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0);
396397
menvcfg = std::make_shared<envcfg_csr_t>(proc, CSR_MENVCFG, menvcfg_mask, menvcfg_init);
397398
if (xlen == 32) {
@@ -411,7 +412,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
411412
(proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0) |
412413
(proc->extension_enabled(EXT_SSTC) ? HENVCFG_STCE : 0) |
413414
(proc->extension_enabled(EXT_ZICFILP) ? HENVCFG_LPE : 0) |
414-
(proc->extension_enabled(EXT_ZICFISS) ? HENVCFG_SSE : 0);
415+
(proc->extension_enabled(EXT_ZICFISS) ? HENVCFG_SSE : 0) |
416+
(proc->extension_enabled(EXT_SSDBLTRP) ? HENVCFG_DTE : 0);
415417
const reg_t henvcfg_init = (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0);
416418
henvcfg = std::make_shared<henvcfg_csr_t>(proc, CSR_HENVCFG, henvcfg_mask, henvcfg_init, menvcfg);
417419
if (xlen == 32) {
@@ -820,6 +822,7 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
820822
bool curr_virt = state.v;
821823
const reg_t interrupt_bit = (reg_t)1 << (max_xlen - 1);
822824
bool interrupt = (bit & interrupt_bit) != 0;
825+
bool supv_double_trap = false;
823826
if (interrupt) {
824827
vsdeleg = (curr_virt && state.prv <= PRV_S) ? state.hideleg->read() : 0;
825828
hsdeleg = (state.prv <= PRV_S) ? state.mideleg->read() : 0;
@@ -828,6 +831,14 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
828831
vsdeleg = (curr_virt && state.prv <= PRV_S) ? (state.medeleg->read() & state.hedeleg->read()) : 0;
829832
hsdeleg = (state.prv <= PRV_S) ? state.medeleg->read() : 0;
830833
}
834+
// An unexpected trap - a trap when SDT is 1 - traps to M-mode
835+
if ((state.prv <= PRV_S && bit < max_xlen) &&
836+
(((vsdeleg >> bit) & 1) || ((hsdeleg >> bit) & 1))) {
837+
reg_t s = curr_virt ? state.nonvirtual_sstatus->read() : state.sstatus->read();
838+
supv_double_trap = get_field(s, MSTATUS_SDT);
839+
if (supv_double_trap)
840+
vsdeleg = hsdeleg = 0;
841+
}
831842
if (state.prv <= PRV_S && bit < max_xlen && ((vsdeleg >> bit) & 1)) {
832843
// Handle the trap in VS-mode
833844
const reg_t adjusted_cause = interrupt ? bit - 1 : bit; // VSSIP -> SSIP, etc
@@ -842,6 +853,8 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
842853
s = set_field(s, MSTATUS_SPP, state.prv);
843854
s = set_field(s, MSTATUS_SIE, 0);
844855
s = set_field(s, MSTATUS_SPELP, state.elp);
856+
if ((state.menvcfg->read() & MENVCFG_DTE) && (state.henvcfg->read() & HENVCFG_DTE))
857+
s = set_field(s, MSTATUS_SDT, 1);
845858
state.elp = elp_t::NO_LP_EXPECTED;
846859
state.sstatus->write(s);
847860
set_privilege(PRV_S, true);
@@ -860,6 +873,8 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
860873
s = set_field(s, MSTATUS_SPP, state.prv);
861874
s = set_field(s, MSTATUS_SIE, 0);
862875
s = set_field(s, MSTATUS_SPELP, state.elp);
876+
if (state.menvcfg->read() & MENVCFG_DTE)
877+
s = set_field(s, MSTATUS_SDT, 1);
863878
state.elp = elp_t::NO_LP_EXPECTED;
864879
state.nonvirtual_sstatus->write(s);
865880
if (extension_enabled('H')) {
@@ -881,9 +896,9 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
881896
const bool nmie = !(state.mnstatus && !get_field(state.mnstatus->read(), MNSTATUS_NMIE));
882897
state.pc = !nmie ? rnmi_trap_handler_address : trap_handler_address;
883898
state.mepc->write(epc);
884-
state.mcause->write(t.cause());
899+
state.mcause->write(supv_double_trap ? CAUSE_DOUBLE_TRAP : t.cause());
885900
state.mtval->write(t.get_tval());
886-
state.mtval2->write(t.get_tval2());
901+
state.mtval2->write(supv_double_trap ? t.cause() : t.get_tval2());
887902
state.mtinst->write(t.get_tinst());
888903

889904
reg_t s = state.mstatus->read();

riscv/trap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ DECLARE_TRAP(CAUSE_MACHINE_ECALL, machine_ecall)
115115
DECLARE_MEM_TRAP(CAUSE_FETCH_PAGE_FAULT, instruction_page_fault)
116116
DECLARE_MEM_TRAP(CAUSE_LOAD_PAGE_FAULT, load_page_fault)
117117
DECLARE_MEM_TRAP(CAUSE_STORE_PAGE_FAULT, store_page_fault)
118+
DECLARE_TRAP(CAUSE_DOUBLE_TRAP, double_trap)
118119
DECLARE_MEM_GVA_TRAP(CAUSE_FETCH_GUEST_PAGE_FAULT, instruction_guest_page_fault)
119120
DECLARE_MEM_GVA_TRAP(CAUSE_LOAD_GUEST_PAGE_FAULT, load_guest_page_fault)
120121
DECLARE_INST_TRAP(CAUSE_VIRTUAL_INSTRUCTION, virtual_instruction)

0 commit comments

Comments
 (0)