Browse Source

Merge pull request #1350 from rivosinc/etrigger_fix_exception_match

triggers: Fix etrigger match on exceptions
pull/1367/head
Andrew Waterman 3 years ago
committed by GitHub
parent
commit
fa79c20a4e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 26
      riscv/processor.cc
  2. 2
      riscv/processor.h
  3. 18
      riscv/triggers.cc
  4. 4
      riscv/triggers.h

26
riscv/processor.cc

@ -196,8 +196,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
// mstatus_csr_t::unlogged_write()):
auto xlen = proc->get_isa().get_max_xlen();
prv = PRV_M;
v = false;
prv = prev_prv = PRV_M;
v = prev_v = false;
csrmap[CSR_MISA] = misa = std::make_shared<misa_csr_t>(proc, CSR_MISA, max_isa);
mstatus = std::make_shared<mstatus_csr_t>(proc, CSR_MSTATUS);
@ -717,6 +717,7 @@ reg_t processor_t::legalize_privilege(reg_t prv)
void processor_t::set_privilege(reg_t prv)
{
mmu->flush_tlb();
state.prev_prv = state.prv;
state.prv = legalize_privilege(prv);
}
@ -747,17 +748,16 @@ void processor_t::set_virt(bool virt)
if (state.prv == PRV_M)
return;
if (state.v != virt) {
/*
* Ideally, we should flush TLB here but we don't need it because
* set_virt() is always used in conjucter with set_privilege() and
* set_privilege() will flush TLB unconditionally.
*
* The virtualized sstatus register also relies on this TLB flush,
* since changing V might change sstatus.MXR and sstatus.SUM.
*/
state.v = virt;
}
/*
* Ideally, we should flush TLB here but we don't need it because
* set_virt() is always used in conjucter with set_privilege() and
* set_privilege() will flush TLB unconditionally.
*
* The virtualized sstatus register also relies on this TLB flush,
* since changing V might change sstatus.MXR and sstatus.SUM.
*/
state.prev_v = state.v;
state.v = virt;
}
void processor_t::enter_debug_mode(uint8_t cause)

2
riscv/processor.h

@ -83,7 +83,9 @@ struct state_t
// control and status registers
std::unordered_map<reg_t, csr_t_p> csrmap;
reg_t prv; // TODO: Can this be an enum instead?
reg_t prev_prv;
bool v;
bool prev_v;
misa_csr_t_p misa;
mstatus_csr_t_p mstatus;
csr_t_p mstatush;

18
riscv/triggers.cc

@ -55,16 +55,19 @@ void trigger_t::tdata3_write(processor_t * const proc, const reg_t val) noexcept
sselect = (sselect_t)((proc->extension_enabled_const('S') && get_field(val, CSR_TEXTRA_SSELECT(xlen)) <= SSELECT_MAXVAL) ? get_field(val, CSR_TEXTRA_SSELECT(xlen)) : SSELECT_IGNORE);
}
bool trigger_t::common_match(processor_t * const proc) const noexcept {
return mode_match(proc->get_state()) && textra_match(proc);
bool trigger_t::common_match(processor_t * const proc, bool use_prev_prv) const noexcept {
auto state = proc->get_state();
auto prv = use_prev_prv ? state->prev_prv : state->prv;
auto v = use_prev_prv ? state->prev_v : state->v;
return mode_match(prv, v) && textra_match(proc);
}
bool trigger_t::mode_match(state_t * const state) const noexcept
bool trigger_t::mode_match(reg_t prv, bool v) const noexcept
{
switch (state->prv) {
switch (prv) {
case PRV_M: return m;
case PRV_S: return state->v ? vs : s;
case PRV_U: return state->v ? vu : u;
case PRV_S: return v ? vs : s;
case PRV_U: return v ? vu : u;
default: assert(false);
}
}
@ -397,7 +400,8 @@ void itrigger_t::tdata1_write(processor_t * const proc, const reg_t val, const b
std::optional<match_result_t> trap_common_t::detect_trap_match(processor_t * const proc, const trap_t& t) noexcept
{
if (!common_match(proc))
// Use the previous privilege for matching
if (!common_match(proc, true))
return std::nullopt;
auto xlen = proc->get_xlen();

4
riscv/triggers.h

@ -90,7 +90,7 @@ public:
protected:
static action_t legalize_action(reg_t val, reg_t action_mask, reg_t dmode_mask) noexcept;
bool common_match(processor_t * const proc) const noexcept;
bool common_match(processor_t * const proc, bool use_prev_prv = false) const noexcept;
bool allow_action(const state_t * const state) const;
reg_t tdata2;
@ -102,7 +102,7 @@ protected:
private:
unsigned legalize_mhselect(bool h_enabled) const noexcept;
bool mode_match(state_t * const state) const noexcept;
bool mode_match(reg_t prv, bool v) const noexcept;
bool textra_match(processor_t * const proc) const noexcept;
struct mhselect_interpretation {

Loading…
Cancel
Save