Skip to content

Commit 7b5eba9

Browse files
committed
Zicfilp: Preserve expected landing pad state on traps
1 parent 5ca914b commit 7b5eba9

File tree

6 files changed

+26
-4
lines changed

6 files changed

+26
-4
lines changed

riscv/csrs.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1337,10 +1337,12 @@ bool dcsr_csr_t::unlogged_write(const reg_t val) noexcept {
13371337
return true;
13381338
}
13391339

1340-
void dcsr_csr_t::write_cause_and_prv(uint8_t cause, reg_t prv, bool v) noexcept {
1340+
void dcsr_csr_t::update_fields(const uint8_t cause, const reg_t prv,
1341+
const bool v, const elp_t pelp) noexcept {
13411342
this->cause = cause;
13421343
this->prv = prv;
13431344
this->v = v;
1345+
this->pelp = pelp;
13441346
log_write();
13451347
}
13461348

riscv/csrs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,8 @@ class dcsr_csr_t: public csr_t {
681681
dcsr_csr_t(processor_t* const proc, const reg_t addr);
682682
virtual void verify_permissions(insn_t insn, bool write) const override;
683683
virtual reg_t read() const noexcept override;
684-
void write_cause_and_prv(uint8_t cause, reg_t prv, bool v) noexcept;
684+
void update_fields(const uint8_t cause, const reg_t prv,
685+
const bool v, const elp_t pelp) noexcept;
685686
protected:
686687
virtual bool unlogged_write(const reg_t val) noexcept override;
687688
public:

riscv/insns/dret.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
require(STATE.debug_mode);
22
set_pc_and_serialize(STATE.dpc->read());
3+
if (ZICFILP_xLPE(STATE.dcsr->v, STATE.dcsr->prv)) {
4+
STATE.elp = STATE.dcsr->pelp;
5+
}
36
p->set_privilege(STATE.dcsr->prv, STATE.dcsr->v);
47
if (STATE.prv < PRV_M)
58
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MPRV);

riscv/insns/mret.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ s = set_field(s, MSTATUS_MIE, get_field(s, MSTATUS_MPIE));
99
s = set_field(s, MSTATUS_MPIE, 1);
1010
s = set_field(s, MSTATUS_MPP, p->extension_enabled('U') ? PRV_U : PRV_M);
1111
s = set_field(s, MSTATUS_MPV, 0);
12+
if (ZICFILP_xLPE(prev_virt, prev_prv)) {
13+
STATE.elp = static_cast<elp_t>(get_field(s, MSTATUS_MPELP));
14+
s = set_field(s, MSTATUS_MPELP, elp_t::NO_LP_EXPECTED);
15+
}
1216
STATE.mstatus->write(s);
1317
if (STATE.mstatush) STATE.mstatush->write(s >> 32); // log mstatush change
1418
p->set_privilege(prev_prv, prev_virt);

riscv/insns/sret.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ reg_t prev_prv = get_field(s, MSTATUS_SPP);
1313
s = set_field(s, MSTATUS_SIE, get_field(s, MSTATUS_SPIE));
1414
s = set_field(s, MSTATUS_SPIE, 1);
1515
s = set_field(s, MSTATUS_SPP, PRV_U);
16-
STATE.sstatus->write(s);
1716
bool prev_virt = STATE.v;
1817
if (!STATE.v) {
1918
if (p->extension_enabled('H')) {
@@ -24,4 +23,9 @@ if (!STATE.v) {
2423

2524
STATE.mstatus->write(set_field(STATE.mstatus->read(), MSTATUS_MPRV, 0));
2625
}
26+
if (ZICFILP_xLPE(prev_virt, prev_prv)) {
27+
STATE.elp = static_cast<elp_t>(get_field(s, SSTATUS_SPELP));
28+
s = set_field(s, SSTATUS_SPELP, elp_t::NO_LP_EXPECTED);
29+
}
30+
STATE.sstatus->write(s);
2731
p->set_privilege(prev_prv, prev_virt);

riscv/processor.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,8 +823,10 @@ const char* processor_t::get_privilege_string()
823823

824824
void processor_t::enter_debug_mode(uint8_t cause)
825825
{
826+
const bool has_zicfilp = extension_enabled(EXT_ZICFILP);
826827
state.debug_mode = true;
827-
state.dcsr->write_cause_and_prv(cause, state.prv, state.v);
828+
state.dcsr->update_fields(cause, state.prv, state.v, state.elp);
829+
state.elp = elp_t::NO_LP_EXPECTED;
828830
set_privilege(PRV_M, false);
829831
state.dpc->write(state.pc);
830832
state.pc = DEBUG_ROM_ENTRY;
@@ -893,6 +895,8 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
893895
s = set_field(s, MSTATUS_SPIE, get_field(s, MSTATUS_SIE));
894896
s = set_field(s, MSTATUS_SPP, state.prv);
895897
s = set_field(s, MSTATUS_SIE, 0);
898+
s = set_field(s, MSTATUS_SPELP, state.elp);
899+
state.elp = elp_t::NO_LP_EXPECTED;
896900
state.sstatus->write(s);
897901
set_privilege(PRV_S, true);
898902
} else if (state.prv <= PRV_S && bit < max_xlen && ((hsdeleg >> bit) & 1)) {
@@ -909,6 +913,8 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
909913
s = set_field(s, MSTATUS_SPIE, get_field(s, MSTATUS_SIE));
910914
s = set_field(s, MSTATUS_SPP, state.prv);
911915
s = set_field(s, MSTATUS_SIE, 0);
916+
s = set_field(s, MSTATUS_SPELP, state.elp);
917+
state.elp = elp_t::NO_LP_EXPECTED;
912918
state.nonvirtual_sstatus->write(s);
913919
if (extension_enabled('H')) {
914920
s = state.hstatus->read();
@@ -940,6 +946,8 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
940946
s = set_field(s, MSTATUS_MIE, 0);
941947
s = set_field(s, MSTATUS_MPV, curr_virt);
942948
s = set_field(s, MSTATUS_GVA, t.has_gva());
949+
s = set_field(s, MSTATUS_MPELP, state.elp);
950+
state.elp = elp_t::NO_LP_EXPECTED;
943951
state.mstatus->write(s);
944952
if (state.mstatush) state.mstatush->write(s >> 32); // log mstatush change
945953
set_privilege(PRV_M, false);

0 commit comments

Comments
 (0)