Skip to content

Commit

Permalink
Add Smdbltrp
Browse files Browse the repository at this point in the history
  • Loading branch information
ved-rivos committed Jul 4, 2024
1 parent 98d2c29 commit a1f582e
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 15 deletions.
2 changes: 2 additions & 0 deletions disasm/isa_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
if (new_elen != 32 && new_elen != 64)
bad_isa_string(str, ("Invalid Zve string: " + ext_str).c_str());
elen = std::max(elen, new_elen);
} else if (ext_str == "smdbltrp") {
extension_table[EXT_SMDBLTRP] = true;
} else if (ext_str[0] == 'x') {
extension_table['X'] = true;
if (ext_str.size() == 1) {
Expand Down
16 changes: 14 additions & 2 deletions riscv/csrs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -505,12 +505,16 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept {
| (has_page ? MSTATUS_TVM : 0)
| (has_gva ? MSTATUS_GVA : 0)
| (has_mpv ? MSTATUS_MPV : 0)
| (proc->extension_enabled(EXT_SMDBLTRP) ? MSTATUS_MDT : 0)
| (proc->extension_enabled(EXT_ZICFILP) ? (MSTATUS_SPELP | MSTATUS_MPELP) : 0)
;

const reg_t requested_mpp = proc->legalize_privilege(get_field(val, MSTATUS_MPP));
const reg_t adjusted_val = set_field(val, MSTATUS_MPP, requested_mpp);
const reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask);
reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask);
if (new_mstatus & MSTATUS_MDT) {
new_mstatus = new_mstatus & ~MSTATUS_MIE;
}
maybe_flush_tlb(new_mstatus);
this->val = adjust_sd(new_mstatus);
return true;
Expand All @@ -525,6 +529,7 @@ reg_t mstatus_csr_t::compute_mstatus_initial_value() const noexcept {
| (proc->extension_enabled_const('U') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_UXL, xlen_to_uxl(proc->get_const_xlen())) : 0)
| (proc->extension_enabled_const('S') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_SXL, xlen_to_uxl(proc->get_const_xlen())) : 0)
| (proc->get_mmu()->is_target_big_endian() ? big_endian_bits : 0)
| (proc->extension_enabled(EXT_SMDBLTRP) ? MSTATUS_MDT : 0)
| 0; // initial value for mstatus
}

Expand Down Expand Up @@ -1295,6 +1300,8 @@ dcsr_csr_t::dcsr_csr_t(processor_t* const proc, const reg_t addr):
halt(false),
v(false),
cause(0),
ext_cause(0),
cetrig(0),
pelp(elp_t::NO_LP_EXPECTED) {
}

Expand All @@ -1315,6 +1322,9 @@ reg_t dcsr_csr_t::read() const noexcept {
result = set_field(result, DCSR_STOPCOUNT, 0);
result = set_field(result, DCSR_STOPTIME, 0);
result = set_field(result, DCSR_CAUSE, cause);
result = set_field(result, DCSR_EXTCAUSE, ext_cause);
if (proc->extension_enabled(EXT_SMDBLTRP))
result = set_field(result, DCSR_CETRIG, cetrig);
result = set_field(result, DCSR_STEP, step);
result = set_field(result, DCSR_PRV, prv);
result = set_field(result, CSR_DCSR_V, v);
Expand All @@ -1335,12 +1345,14 @@ bool dcsr_csr_t::unlogged_write(const reg_t val) noexcept {
v = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_V) : false;
pelp = proc->extension_enabled(EXT_ZICFILP) ?
static_cast<elp_t>(get_field(val, DCSR_PELP)) : elp_t::NO_LP_EXPECTED;
cetrig = proc->extension_enabled(EXT_SMDBLTRP) ? get_field(val, DCSR_CETRIG) : false;
return true;
}

void dcsr_csr_t::update_fields(const uint8_t cause, const reg_t prv,
void dcsr_csr_t::update_fields(const uint8_t cause, uint8_t ext_cause, const reg_t prv,
const bool v, const elp_t pelp) noexcept {
this->cause = cause;
this->ext_cause = ext_cause;
this->prv = prv;
this->v = v;
this->pelp = pelp;
Expand Down
4 changes: 3 additions & 1 deletion riscv/csrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ class dcsr_csr_t: public csr_t {
dcsr_csr_t(processor_t* const proc, const reg_t addr);
virtual void verify_permissions(insn_t insn, bool write) const override;
virtual reg_t read() const noexcept override;
void update_fields(const uint8_t cause, const reg_t prv,
void update_fields(const uint8_t cause, const uint8_t ext_cause, const reg_t prv,
const bool v, const elp_t pelp) noexcept;
protected:
virtual bool unlogged_write(const reg_t val) noexcept override;
Expand All @@ -699,6 +699,8 @@ class dcsr_csr_t: public csr_t {
bool halt;
bool v;
uint8_t cause;
uint8_t ext_cause;
bool cetrig;
elp_t pelp;
};

Expand Down
5 changes: 4 additions & 1 deletion riscv/encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

/*
* This file is auto-generated by running 'make' in
* https://github.com/riscv/riscv-opcodes (c55d30f)
* https://github.com/riscv/riscv-opcodes (23a394b)
*/

#ifndef RISCV_CSR_ENCODING_H
Expand Down Expand Up @@ -110,6 +110,9 @@
#define DCSR_CAUSE_STEP 4
#define DCSR_CAUSE_HALT 5
#define DCSR_CAUSE_GROUP 6
#define DCSR_CAUSE_EXTCAUSE 7

#define DCSR_EXTCAUSE_CRITERR 0

#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4))
#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5))
Expand Down
22 changes: 16 additions & 6 deletions riscv/execute.cc
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,12 @@ void processor_t::step(size_t n)
{
if (!state.debug_mode) {
if (halt_request == HR_REGULAR) {
enter_debug_mode(DCSR_CAUSE_DEBUGINT);
enter_debug_mode(DCSR_CAUSE_DEBUGINT, 0);
} else if (halt_request == HR_GROUP) {
enter_debug_mode(DCSR_CAUSE_GROUP);
enter_debug_mode(DCSR_CAUSE_GROUP, 0);
} // !!!The halt bit in DCSR is deprecated.
else if (state.dcsr->halt) {
enter_debug_mode(DCSR_CAUSE_HALT);
enter_debug_mode(DCSR_CAUSE_HALT, 0);
}
}

Expand Down Expand Up @@ -257,7 +257,7 @@ void processor_t::step(size_t n)
if (unlikely(!state.serialized && state.single_step == state.STEP_STEPPED)) {
state.single_step = state.STEP_NONE;
if (!state.debug_mode) {
enter_debug_mode(DCSR_CAUSE_STEP);
enter_debug_mode(DCSR_CAUSE_STEP, 0);
// enter_debug_mode changed state.pc, so we can't just continue.
break;
}
Expand Down Expand Up @@ -311,13 +311,23 @@ void processor_t::step(size_t n)
take_trap(t, pc);
n = instret;

// If critical error then enter debug mode critical error trigger enabled
if (state.critical_error) {
if (state.dcsr->read() & DCSR_CETRIG) {
enter_debug_mode(DCSR_CAUSE_EXTCAUSE, DCSR_EXTCAUSE_CRITERR);
} else {
// Handling of critical error is implementation defined
// For now just enter debug mode
enter_debug_mode(DCSR_CAUSE_HALT, 0);
}
}
// Trigger action takes priority over single step
auto match = TM.detect_trap_match(t);
if (match.has_value())
take_trigger_action(match->action, 0, state.pc, 0);
else if (unlikely(state.single_step == state.STEP_STEPPED)) {
state.single_step = state.STEP_NONE;
enter_debug_mode(DCSR_CAUSE_STEP);
enter_debug_mode(DCSR_CAUSE_STEP, 0);
}
}
catch (triggers::matched_t& t)
Expand All @@ -330,7 +340,7 @@ void processor_t::step(size_t n)
}
catch(trap_debug_mode&)
{
enter_debug_mode(DCSR_CAUSE_SWBP);
enter_debug_mode(DCSR_CAUSE_SWBP, 0);
}
catch (wait_for_interrupt_t &t)
{
Expand Down
11 changes: 11 additions & 0 deletions riscv/insns/mret.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ if (ZICFILP_xLPE(prev_virt, prev_prv)) {
STATE.elp = static_cast<elp_t>(get_field(s, MSTATUS_MPELP));
}
s = set_field(s, MSTATUS_MPELP, elp_t::NO_LP_EXPECTED);

s = set_field(s, MSTATUS_MDT, 0);
if (prev_prv == PRV_U || prev_virt) {
s = set_field(s, MSTATUS_SDT, 0);
}
if (prev_virt && prev_prv == PRV_U) {
reg_t vs = STATE.vsstatus->read();
vs = set_field(vs, SSTATUS_SDT, 0);
STATE.vsstatus->write(vs);
}

STATE.mstatus->write(s);
if (STATE.mstatush) STATE.mstatush->write(s >> 32); // log mstatush change
STATE.tcontrol->write((STATE.tcontrol->read() & CSR_TCONTROL_MPTE) ? (CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE) : 0);
Expand Down
15 changes: 15 additions & 0 deletions riscv/insns/sret.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,21 @@ if (!STATE.v) {
if (ZICFILP_xLPE(prev_virt, prev_prv)) {
STATE.elp = static_cast<elp_t>(get_field(s, SSTATUS_SPELP));
}

if (STATE.prv == PRV_M) {
reg_t m = STATE.mstatus->read();
m = set_field(m, MSTATUS_MDT, 0);
if (prev_prv == PRV_U || prev_virt) {
s = set_field(s, MSTATUS_SDT, 0);
}
STATE.mstatus->write(m);
if (prev_virt && prev_prv == PRV_U) {
reg_t vs = STATE.vsstatus->read();
vs = set_field(vs, SSTATUS_SDT, 0);
STATE.vsstatus->write(vs);
}
}

s = set_field(s, SSTATUS_SPELP, elp_t::NO_LP_EXPECTED);
STATE.sstatus->write(s);
p->set_privilege(prev_prv, prev_virt);
1 change: 1 addition & 0 deletions riscv/isa_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ typedef enum {
EXT_SSQOSID,
EXT_ZICFILP,
EXT_ZICFISS,
EXT_SMDBLTRP,
NUM_ISA_EXTENSIONS
} isa_extension_t;

Expand Down
17 changes: 13 additions & 4 deletions riscv/processor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
last_inst_flen = 0;

elp = elp_t::NO_LP_EXPECTED;
critical_error = false;
}

void processor_t::set_debug(bool value)
Expand Down Expand Up @@ -767,11 +768,11 @@ const char* processor_t::get_privilege_string()
abort();
}

void processor_t::enter_debug_mode(uint8_t cause)
void processor_t::enter_debug_mode(uint8_t cause, uint8_t extcause)
{
const bool has_zicfilp = extension_enabled(EXT_ZICFILP);
state.debug_mode = true;
state.dcsr->update_fields(cause, state.prv, state.v, state.elp);
state.dcsr->update_fields(cause, extcause, state.prv, state.v, state.elp);
state.elp = elp_t::NO_LP_EXPECTED;
set_privilege(PRV_M, false);
state.dpc->write(state.pc);
Expand Down Expand Up @@ -875,6 +876,15 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
// Handle the trap in M-mode
const reg_t vector = (state.mtvec->read() & 1) && interrupt ? 4 * bit : 0;
const reg_t trap_handler_address = (state.mtvec->read() & ~(reg_t)1) + vector;
reg_t s = state.mstatus->read();
if ( extension_enabled(EXT_SMDBLTRP)) {
if (get_field(s, MSTATUS_MDT)) {
// Critical error - Double trap in M-mode
state.critical_error = 1;
return;
}
s = set_field(s, MSTATUS_MDT, 1);
}
// RNMI exception vector is implementation-defined. Since we don't model
// RNMI sources, the feature isn't very useful, so pick an invalid address.
const reg_t rnmi_trap_handler_address = 0;
Expand All @@ -886,7 +896,6 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
state.mtval2->write(t.get_tval2());
state.mtinst->write(t.get_tinst());

reg_t s = state.mstatus->read();
s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_MIE));
s = set_field(s, MSTATUS_MPP, state.prv);
s = set_field(s, MSTATUS_MIE, 0);
Expand All @@ -912,7 +921,7 @@ void processor_t::take_trigger_action(triggers::action_t action, reg_t breakpoin

switch (action) {
case triggers::ACTION_DEBUG_MODE:
enter_debug_mode(DCSR_CAUSE_HWBP);
enter_debug_mode(DCSR_CAUSE_HWBP, 0);
break;
case triggers::ACTION_DEBUG_EXCEPTION: {
trap_breakpoint trap(virt, breakpoint_tval);
Expand Down
3 changes: 2 additions & 1 deletion riscv/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ struct state_t
int last_inst_flen;

elp_t elp;
bool critical_error;
};

class opcode_cache_entry_t {
Expand Down Expand Up @@ -401,7 +402,7 @@ class processor_t : public abstract_device_t
void register_insn(insn_desc_t, bool);
int paddr_bits();

void enter_debug_mode(uint8_t cause);
void enter_debug_mode(uint8_t cause, uint8_t ext_cause);

void debug_output_log(std::stringstream *s); // either output to interactive user or write to log file

Expand Down

0 comments on commit a1f582e

Please sign in to comment.