Skip to content

Add Smdbltrp #1722

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

Merged
merged 1 commit into from
Aug 18, 2024
Merged
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Spike supports the following RISC-V ISA features:
- Sdtrig extension, v1.0-STABLE
- Smepmp extension v1.0
- Smstateen extension, v1.0
- Smdbltrp extension, v1.0
- Sscofpmf v0.5.2
- Zca extension, v1.0
- Zcb extension, v1.0
Expand Down
2 changes: 2 additions & 0 deletions disasm/isa_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
elen = std::max(elen, new_elen);
} else if (ext_str == "ssdbltrp") {
extension_table[EXT_SSDBLTRP] = true;
} 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 @@ -548,13 +548,17 @@ 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)
| (proc->extension_enabled(EXT_SSDBLTRP) ? SSTATUS_SDT : 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 @@ -569,6 +573,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 @@ -1343,6 +1348,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 @@ -1363,6 +1370,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 @@ -1382,12 +1392,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
7 changes: 5 additions & 2 deletions 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 (048218e)
*/

#ifndef RISCV_CSR_ENCODING_H
Expand Down Expand Up @@ -110,14 +110,17 @@
#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))
#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11))

#define MCONTROL_SELECT (1<<19)
#define MCONTROL_TIMING (1<<18)
#define MCONTROL_ACTION (0x3f<<12)
#define MCONTROL_ACTION (0xf<<12)
#define MCONTROL_CHAIN (1<<11)
#define MCONTROL_MATCH (0xf<<7)
#define MCONTROL_M (1<<6)
Expand Down
36 changes: 28 additions & 8 deletions riscv/execute.cc
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,11 @@ 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);
}
else if (state.dcsr->halt) {
enter_debug_mode(DCSR_CAUSE_HALT);
enter_debug_mode(DCSR_CAUSE_GROUP, 0);
} else if (state.dcsr->halt) {
enter_debug_mode(DCSR_CAUSE_HALT, 0);
}
}

Expand Down Expand Up @@ -257,7 +256,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 @@ -286,6 +285,17 @@ void processor_t::step(size_t n)
disasm(fetch.insn);
pc = execute_insn_logged(this, pc, fetch);
advance_pc();

// Resume from debug mode in critical error
if (state.critical_error && !state.debug_mode) {
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);
}
}
}
}
else while (instret < n)
Expand All @@ -311,13 +321,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 +350,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
10 changes: 9 additions & 1 deletion riscv/insns/dret.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,16 @@ if (ZICFILP_xLPE(STATE.dcsr->v, STATE.dcsr->prv)) {
STATE.elp = STATE.dcsr->pelp;
}
p->set_privilege(STATE.dcsr->prv, STATE.dcsr->v);
if (STATE.prv < PRV_M)
if (STATE.prv < PRV_M) {
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MPRV);
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MDT);
}

if (STATE.dcsr->prv == PRV_U || STATE.dcsr->v)
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_SDT);

if (STATE.dcsr->v && STATE.dcsr->prv == PRV_U)
STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT);

if (STATE.dcsr->prv == PRV_U || STATE.dcsr->v)
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_SDT);
Expand Down
1 change: 1 addition & 0 deletions riscv/insns/mret.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ 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)
Expand Down
9 changes: 9 additions & 0 deletions riscv/insns/sret.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ 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) {
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MDT);
if (prev_prv == PRV_U || prev_virt)
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_SDT);
if (prev_virt && prev_prv == PRV_U)
STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT);
}

s = set_field(s, SSTATUS_SPELP, elp_t::NO_LP_EXPECTED);

if (STATE.prv == PRV_S) {
Expand Down
1 change: 1 addition & 0 deletions riscv/isa_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ typedef enum {
EXT_ZICFILP,
EXT_ZICFISS,
EXT_SSDBLTRP,
EXT_SMDBLTRP,
EXT_SMMPM,
EXT_SMNPM,
EXT_SSNPM,
Expand Down
24 changes: 19 additions & 5 deletions riscv/processor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)

elp = elp_t::NO_LP_EXPECTED;

critical_error = false;

csr_init(proc, max_isa);
}

Expand Down Expand Up @@ -379,11 +381,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 @@ -500,18 +502,30 @@ 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;
// RNMI exception vector is implementation-defined. Since we don't model
// RNMI sources, the feature isn't very useful, so pick an invalid address.
// RNMI exception vector is implementation-defined. Since we don't model
const reg_t rnmi_trap_handler_address = 0;
const bool nmie = !(state.mnstatus && !get_field(state.mnstatus->read(), MNSTATUS_NMIE));

reg_t s = state.mstatus->read();
if ( extension_enabled(EXT_SMDBLTRP)) {
if (get_field(s, MSTATUS_MDT) || !nmie) {
// Critical error - Double trap in M-mode or trap when nmie is 0
// RNMI is not modeled else double trap in M-mode would trap to
// RNMI handler instead of leading to a critical error
state.critical_error = 1;
return;
}
s = set_field(s, MSTATUS_MDT, 1);
}

state.pc = !nmie ? rnmi_trap_handler_address : trap_handler_address;
state.mepc->write(epc);
state.mcause->write(supv_double_trap ? CAUSE_DOUBLE_TRAP : t.cause());
state.mtval->write(t.get_tval());
state.mtval2->write(supv_double_trap ? t.cause() : 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 @@ -537,7 +551,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
4 changes: 3 additions & 1 deletion riscv/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ struct state_t

elp_t elp;

bool critical_error;

private:
void csr_init(processor_t* const proc, reg_t max_isa);
};
Expand Down Expand Up @@ -405,7 +407,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
Loading