Skip to content

Commit e7fd2e8

Browse files
committed
Add Smdbltrp
1 parent 98d2c29 commit e7fd2e8

File tree

11 files changed

+101
-16
lines changed

11 files changed

+101
-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 == "smdbltrp") {
351+
extension_table[EXT_SMDBLTRP] = true;
350352
} else if (ext_str[0] == 'x') {
351353
extension_table['X'] = true;
352354
if (ext_str.size() == 1) {

riscv/csrs.cc

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -505,12 +505,16 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept {
505505
| (has_page ? MSTATUS_TVM : 0)
506506
| (has_gva ? MSTATUS_GVA : 0)
507507
| (has_mpv ? MSTATUS_MPV : 0)
508+
| (proc->extension_enabled(EXT_SMDBLTRP) ? MSTATUS_MDT : 0)
508509
| (proc->extension_enabled(EXT_ZICFILP) ? (MSTATUS_SPELP | MSTATUS_MPELP) : 0)
509510
;
510511

511512
const reg_t requested_mpp = proc->legalize_privilege(get_field(val, MSTATUS_MPP));
512513
const reg_t adjusted_val = set_field(val, MSTATUS_MPP, requested_mpp);
513-
const reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask);
514+
reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask);
515+
if (new_mstatus & MSTATUS_MDT) {
516+
new_mstatus = new_mstatus & ~MSTATUS_MIE;
517+
}
514518
maybe_flush_tlb(new_mstatus);
515519
this->val = adjust_sd(new_mstatus);
516520
return true;
@@ -525,6 +529,7 @@ reg_t mstatus_csr_t::compute_mstatus_initial_value() const noexcept {
525529
| (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)
526530
| (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)
527531
| (proc->get_mmu()->is_target_big_endian() ? big_endian_bits : 0)
532+
| (proc->extension_enabled(EXT_SMDBLTRP) ? MSTATUS_MDT : 0)
528533
| 0; // initial value for mstatus
529534
}
530535

@@ -1295,6 +1300,8 @@ dcsr_csr_t::dcsr_csr_t(processor_t* const proc, const reg_t addr):
12951300
halt(false),
12961301
v(false),
12971302
cause(0),
1303+
ext_cause(0),
1304+
cetrig(0),
12981305
pelp(elp_t::NO_LP_EXPECTED) {
12991306
}
13001307

@@ -1315,6 +1322,9 @@ reg_t dcsr_csr_t::read() const noexcept {
13151322
result = set_field(result, DCSR_STOPCOUNT, 0);
13161323
result = set_field(result, DCSR_STOPTIME, 0);
13171324
result = set_field(result, DCSR_CAUSE, cause);
1325+
result = set_field(result, DCSR_EXTCAUSE, ext_cause);
1326+
if (proc->extension_enabled(EXT_SMDBLTRP))
1327+
result = set_field(result, DCSR_CETRIG, cetrig);
13181328
result = set_field(result, DCSR_STEP, step);
13191329
result = set_field(result, DCSR_PRV, prv);
13201330
result = set_field(result, CSR_DCSR_V, v);
@@ -1335,12 +1345,14 @@ bool dcsr_csr_t::unlogged_write(const reg_t val) noexcept {
13351345
v = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_V) : false;
13361346
pelp = proc->extension_enabled(EXT_ZICFILP) ?
13371347
static_cast<elp_t>(get_field(val, DCSR_PELP)) : elp_t::NO_LP_EXPECTED;
1348+
cetrig = proc->extension_enabled(EXT_SMDBLTRP) ? get_field(val, DCSR_CETRIG) : false;
13381349
return true;
13391350
}
13401351

1341-
void dcsr_csr_t::update_fields(const uint8_t cause, const reg_t prv,
1352+
void dcsr_csr_t::update_fields(const uint8_t cause, uint8_t ext_cause, const reg_t prv,
13421353
const bool v, const elp_t pelp) noexcept {
13431354
this->cause = cause;
1355+
this->ext_cause = ext_cause;
13441356
this->prv = prv;
13451357
this->v = v;
13461358
this->pelp = pelp;

riscv/csrs.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ class dcsr_csr_t: public csr_t {
684684
dcsr_csr_t(processor_t* const proc, const reg_t addr);
685685
virtual void verify_permissions(insn_t insn, bool write) const override;
686686
virtual reg_t read() const noexcept override;
687-
void update_fields(const uint8_t cause, const reg_t prv,
687+
void update_fields(const uint8_t cause, const uint8_t ext_cause, const reg_t prv,
688688
const bool v, const elp_t pelp) noexcept;
689689
protected:
690690
virtual bool unlogged_write(const reg_t val) noexcept override;
@@ -699,6 +699,8 @@ class dcsr_csr_t: public csr_t {
699699
bool halt;
700700
bool v;
701701
uint8_t cause;
702+
uint8_t ext_cause;
703+
bool cetrig;
702704
elp_t pelp;
703705
};
704706

riscv/encoding.h

Lines changed: 4 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 (c55d30f)
7+
* https://github.com/riscv/riscv-opcodes (23a394b)
88
*/
99

1010
#ifndef RISCV_CSR_ENCODING_H
@@ -110,6 +110,9 @@
110110
#define DCSR_CAUSE_STEP 4
111111
#define DCSR_CAUSE_HALT 5
112112
#define DCSR_CAUSE_GROUP 6
113+
#define DCSR_CAUSE_EXTCAUSE 7
114+
115+
#define DCSR_EXTCAUSE_CRITERR 0
113116

114117
#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4))
115118
#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5))

riscv/execute.cc

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,12 @@ void processor_t::step(size_t n)
213213
{
214214
if (!state.debug_mode) {
215215
if (halt_request == HR_REGULAR) {
216-
enter_debug_mode(DCSR_CAUSE_DEBUGINT);
216+
enter_debug_mode(DCSR_CAUSE_DEBUGINT, 0);
217217
} else if (halt_request == HR_GROUP) {
218-
enter_debug_mode(DCSR_CAUSE_GROUP);
218+
enter_debug_mode(DCSR_CAUSE_GROUP, 0);
219219
} // !!!The halt bit in DCSR is deprecated.
220220
else if (state.dcsr->halt) {
221-
enter_debug_mode(DCSR_CAUSE_HALT);
221+
enter_debug_mode(DCSR_CAUSE_HALT, 0);
222222
}
223223
}
224224

@@ -257,7 +257,7 @@ void processor_t::step(size_t n)
257257
if (unlikely(!state.serialized && state.single_step == state.STEP_STEPPED)) {
258258
state.single_step = state.STEP_NONE;
259259
if (!state.debug_mode) {
260-
enter_debug_mode(DCSR_CAUSE_STEP);
260+
enter_debug_mode(DCSR_CAUSE_STEP, 0);
261261
// enter_debug_mode changed state.pc, so we can't just continue.
262262
break;
263263
}
@@ -286,6 +286,17 @@ void processor_t::step(size_t n)
286286
disasm(fetch.insn);
287287
pc = execute_insn_logged(this, pc, fetch);
288288
advance_pc();
289+
290+
// Resume from debug mode in critical error
291+
if (state.critical_error && !state.debug_mode) {
292+
if (state.dcsr->read() & DCSR_CETRIG) {
293+
enter_debug_mode(DCSR_CAUSE_EXTCAUSE, DCSR_EXTCAUSE_CRITERR);
294+
} else {
295+
// Handling of critical error is implementation defined
296+
// For now just enter debug mode
297+
enter_debug_mode(DCSR_CAUSE_HALT, 0);
298+
}
299+
}
289300
}
290301
}
291302
else while (instret < n)
@@ -311,13 +322,23 @@ void processor_t::step(size_t n)
311322
take_trap(t, pc);
312323
n = instret;
313324

325+
// If critical error then enter debug mode critical error trigger enabled
326+
if (state.critical_error) {
327+
if (state.dcsr->read() & DCSR_CETRIG) {
328+
enter_debug_mode(DCSR_CAUSE_EXTCAUSE, DCSR_EXTCAUSE_CRITERR);
329+
} else {
330+
// Handling of critical error is implementation defined
331+
// For now just enter debug mode
332+
enter_debug_mode(DCSR_CAUSE_HALT, 0);
333+
}
334+
}
314335
// Trigger action takes priority over single step
315336
auto match = TM.detect_trap_match(t);
316337
if (match.has_value())
317338
take_trigger_action(match->action, 0, state.pc, 0);
318339
else if (unlikely(state.single_step == state.STEP_STEPPED)) {
319340
state.single_step = state.STEP_NONE;
320-
enter_debug_mode(DCSR_CAUSE_STEP);
341+
enter_debug_mode(DCSR_CAUSE_STEP, 0);
321342
}
322343
}
323344
catch (triggers::matched_t& t)
@@ -330,7 +351,7 @@ void processor_t::step(size_t n)
330351
}
331352
catch(trap_debug_mode&)
332353
{
333-
enter_debug_mode(DCSR_CAUSE_SWBP);
354+
enter_debug_mode(DCSR_CAUSE_SWBP, 0);
334355
}
335356
catch (wait_for_interrupt_t &t)
336357
{

riscv/insns/dret.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,16 @@ if (ZICFILP_xLPE(STATE.dcsr->v, STATE.dcsr->prv)) {
44
STATE.elp = STATE.dcsr->pelp;
55
}
66
p->set_privilege(STATE.dcsr->prv, STATE.dcsr->v);
7-
if (STATE.prv < PRV_M)
7+
if (STATE.prv < PRV_M) {
88
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MPRV);
9+
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MDT);
10+
}
11+
12+
if (STATE.dcsr->prv == PRV_U || STATE.dcsr->v)
13+
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_SDT);
14+
15+
if (STATE.dcsr->v && STATE.dcsr->prv == PRV_U)
16+
STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT);
917

1018
/* We're not in Debug Mode anymore. */
1119
STATE.debug_mode = false;

riscv/insns/mret.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,17 @@ 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+
17+
s = set_field(s, MSTATUS_MDT, 0);
18+
if (prev_prv == PRV_U || prev_virt) {
19+
s = set_field(s, MSTATUS_SDT, 0);
20+
}
21+
if (prev_virt && prev_prv == PRV_U) {
22+
reg_t vs = STATE.vsstatus->read();
23+
vs = set_field(vs, SSTATUS_SDT, 0);
24+
STATE.vsstatus->write(vs);
25+
}
26+
1627
STATE.mstatus->write(s);
1728
if (STATE.mstatush) STATE.mstatush->write(s >> 32); // log mstatush change
1829
STATE.tcontrol->write((STATE.tcontrol->read() & CSR_TCONTROL_MPTE) ? (CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE) : 0);

riscv/insns/sret.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,21 @@ if (!STATE.v) {
2626
if (ZICFILP_xLPE(prev_virt, prev_prv)) {
2727
STATE.elp = static_cast<elp_t>(get_field(s, SSTATUS_SPELP));
2828
}
29+
30+
if (STATE.prv == PRV_M) {
31+
reg_t m = STATE.mstatus->read();
32+
m = set_field(m, MSTATUS_MDT, 0);
33+
if (prev_prv == PRV_U || prev_virt) {
34+
s = set_field(s, MSTATUS_SDT, 0);
35+
}
36+
STATE.mstatus->write(m);
37+
if (prev_virt && prev_prv == PRV_U) {
38+
reg_t vs = STATE.vsstatus->read();
39+
vs = set_field(vs, SSTATUS_SDT, 0);
40+
STATE.vsstatus->write(vs);
41+
}
42+
}
43+
2944
s = set_field(s, SSTATUS_SPELP, elp_t::NO_LP_EXPECTED);
3045
STATE.sstatus->write(s);
3146
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_SMDBLTRP,
8485
NUM_ISA_EXTENSIONS
8586
} isa_extension_t;
8687

riscv/processor.cc

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
549549
last_inst_flen = 0;
550550

551551
elp = elp_t::NO_LP_EXPECTED;
552+
critical_error = false;
552553
}
553554

554555
void processor_t::set_debug(bool value)
@@ -767,11 +768,11 @@ const char* processor_t::get_privilege_string()
767768
abort();
768769
}
769770

770-
void processor_t::enter_debug_mode(uint8_t cause)
771+
void processor_t::enter_debug_mode(uint8_t cause, uint8_t extcause)
771772
{
772773
const bool has_zicfilp = extension_enabled(EXT_ZICFILP);
773774
state.debug_mode = true;
774-
state.dcsr->update_fields(cause, state.prv, state.v, state.elp);
775+
state.dcsr->update_fields(cause, extcause, state.prv, state.v, state.elp);
775776
state.elp = elp_t::NO_LP_EXPECTED;
776777
set_privilege(PRV_M, false);
777778
state.dpc->write(state.pc);
@@ -875,6 +876,15 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
875876
// Handle the trap in M-mode
876877
const reg_t vector = (state.mtvec->read() & 1) && interrupt ? 4 * bit : 0;
877878
const reg_t trap_handler_address = (state.mtvec->read() & ~(reg_t)1) + vector;
879+
reg_t s = state.mstatus->read();
880+
if ( extension_enabled(EXT_SMDBLTRP)) {
881+
if (get_field(s, MSTATUS_MDT)) {
882+
// Critical error - Double trap in M-mode
883+
state.critical_error = 1;
884+
return;
885+
}
886+
s = set_field(s, MSTATUS_MDT, 1);
887+
}
878888
// RNMI exception vector is implementation-defined. Since we don't model
879889
// RNMI sources, the feature isn't very useful, so pick an invalid address.
880890
const reg_t rnmi_trap_handler_address = 0;
@@ -886,7 +896,6 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
886896
state.mtval2->write(t.get_tval2());
887897
state.mtinst->write(t.get_tinst());
888898

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

913922
switch (action) {
914923
case triggers::ACTION_DEBUG_MODE:
915-
enter_debug_mode(DCSR_CAUSE_HWBP);
924+
enter_debug_mode(DCSR_CAUSE_HWBP, 0);
916925
break;
917926
case triggers::ACTION_DEBUG_EXCEPTION: {
918927
trap_breakpoint trap(virt, breakpoint_tval);

riscv/processor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ struct state_t
189189
int last_inst_flen;
190190

191191
elp_t elp;
192+
bool critical_error;
192193
};
193194

194195
class opcode_cache_entry_t {
@@ -401,7 +402,7 @@ class processor_t : public abstract_device_t
401402
void register_insn(insn_desc_t, bool);
402403
int paddr_bits();
403404

404-
void enter_debug_mode(uint8_t cause);
405+
void enter_debug_mode(uint8_t cause, uint8_t ext_cause);
405406

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

0 commit comments

Comments
 (0)