Skip to content

Commit

Permalink
triggers: Fix etrigger match on exceptions
Browse files Browse the repository at this point in the history
The etrigger match on exceptions doesn't work properly in cases like
the following:

1) M-mode delegates ECALLs to S-mode
2) A CPU hardware point mechanism is used to place a breakpoint on the
   Umode instruction that executes the ECALL from Umode to Smode. In
   effect, this creates a breakpoint etrigger based on Umode.

In the above, the expectation is that #2 will first cause an exit to
the Smode handler (stvec), and the hardware breakpoint exception will
be triggered following an entry into the handler.

However, since etrigger currently checks the current privilege mode, we
will never get a match on conditions like #2.

The patch attempts to address the issue by using the stashed version of
the previous privilege mode for the etrigger match.

cc: YenHaoChen <[email protected]>
Signed-off-by: Atul Khare <[email protected]>
  • Loading branch information
atulkharerivos committed May 24, 2023
1 parent 31f5ede commit d9e30bb
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 4 deletions.
9 changes: 6 additions & 3 deletions riscv/triggers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ 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 {
bool trigger_t::common_match(processor_t * const proc, bool use_prev_prv) const noexcept {
auto state = proc->get_state();
return mode_match(state->prv, state->v) && textra_match(proc);
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(reg_t prv, bool v) const noexcept
Expand Down Expand Up @@ -398,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();
Expand Down
2 changes: 1 addition & 1 deletion riscv/triggers.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class trigger_t {

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;

Expand Down

0 comments on commit d9e30bb

Please sign in to comment.