Skip to content

When the trigger action is set to 0, there is inconsistency between SPEC and SPIKE in handling the prevention of trap re-entry #1216

@InitializerList

Description

@InitializerList

RV DEBUG SPEC says:
For native triggers:

In these cases such a trigger may cause a breakpoint exception while already in a trap handler. This might leave the hart unable to resume normal execution because state such as mcause and mepc would be overwritten.

Harts that support triggers with action=0 should implement one of the following two solutions to solve the problem of reentrancy:

  1. The hardware prevents triggers with action=0 from matching or firing while in M-mode and while MIE in mstatus is 0. If medeleg [3]=1 then it prevents triggers with action=0 from matching or firing while in S-mode and while SIE in sstatus is 0. If medeleg [3]=1 and hedeleg [3]=1 then it prevents triggers with action=0 from matching or firing while in VS-mode and while SIE in vstatus is 0.
  2. mte and mpte in tcontrol is implemented. medeleg [3] is hard-wired to 0.

Both options prevent etrigger and itrigger from having any effect on exceptions and interrupts that are handled in M-mode. They also prevent triggering during some initial portion of each handler. Debuggers should use other mechanisms to debug these cases, such as patching the handler or setting a breakpoint on the instruction after MIE is cleared.

RV SPEC implement:

auto prv = use_prev_prv ? state->prev_prv : state->prv;
  auto v = use_prev_prv ? state->prev_v : state->v;

  if (!mode_match(prv, v))
    return false;

  if (!textra_match(proc))
    return false;

  if (get_action() == ACTION_DEBUG_EXCEPTION) {
    if (proc->extension_enabled('S')) {
      // The hardware prevents triggers with action=0 from matching or firing
      // while in M-mode and while MIE in mstatus is 0. If medeleg [3]=1 then it
      // prevents triggers with action=0 from matching or firing while in S-mode
      // and while SIE in sstatus is 0. If medeleg [3]=1 and hedeleg [3]=1 then
      // it prevents triggers with action=0 from matching or firing while in
      // VS-mode and while SIE in vstatus is 0.

      const bool mstatus_mie = state->mstatus->read() & MSTATUS_MIE;
      if (prv == PRV_M && !mstatus_mie)
        return false;

      const bool sstatus_sie = state->sstatus->read() & MSTATUS_SIE;
      const bool medeleg_breakpoint = (state->medeleg->read() >> CAUSE_BREAKPOINT) & 1;
      if (prv == PRV_S && !v && medeleg_breakpoint && !sstatus_sie)
        return false;

      const bool vsstatus_sie = state->vsstatus->read() & MSTATUS_SIE;
      const bool hedeleg_breakpoint = (state->hedeleg->read() >> CAUSE_BREAKPOINT) & 1;
      if (prv == PRV_S && v && medeleg_breakpoint && hedeleg_breakpoint && !vsstatus_sie)
        return false;
    } else {
      // mte and mpte in tcontrol is implemented. medeleg [3] is hard-wired to 0.
      if (prv == PRV_M && !(tcontrol_value(state) & CSR_TCONTROL_MTE))
        return false;
}

Namely, the SPEC description and spike implementation are inconsistent,
For example: S-mode page fault enters M-mode, Mstatus. MIE=0, Mstatus. SIE=1. Simultaneously configured with action=0 and able to capture page faults using an etrigger.
According to the spec description, the etrigger should not trigger, M-mode, And Mstatus. MIE=0
The implementation of Spike uses S-mode, with Mstatus. SIE=1, so the etrigger can trigger normally.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions