Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

For interrupt and exception triggers with action = 0, what value for mcause? #890

Closed
jhauser-us opened this issue Oct 1, 2023 · 14 comments · Fixed by #901
Closed

For interrupt and exception triggers with action = 0, what value for mcause? #890

jhauser-us opened this issue Oct 1, 2023 · 14 comments · Fixed by #901
Labels

Comments

@jhauser-us
Copy link

Section 5.6.14, "Interrupt Trigger", says:

When the trigger fires, all CSRs are updated for the interrupt trap as defined by the Privileged Spec, and the requested action is taken just before the first instruction of the trap handler is executed. If the trigger fires with action =0 then zero is written to the tval CSR on the breakpoint trap.

If a trigger fires on an interrupt trap that is taken into M mode, and itrigger.action = 0, what value is required to end up in the mcause CSR? To indicate a breakpoint exception, it needs to be the value 3, but the quoted text suggests it will rather be the value that the interrupt handler would normally see.

Much the same question arises in the next subsection, "Exception Trigger", which has almost identical text. If a trigger fires on an exception trap that is taken into M mode, and etrigger.action = 0, what value is required to be in the mcause CSR? Is it 3 for the breakpoint exception, or is it the code for the exception that caused the trigger to fire?

Note, if the answer for an exception trigger is 3, then the cause code for the original triggering exception is lost, unless the trigger is configured with only one bit set in tdata2 (or the subset of possible exception causes can be proved to be a singleton by some other means).

@pdonahue-ventana
Copy link
Collaborator

If a trigger fires on an interrupt trap that is taken into M mode, and itrigger.action = 0, what value is required to end up in the mcause CSR?

If a trap is taken to M mode (either due to an exception or interrupt) then it normally has these effects:

  1. mcause has the exception or interrupt number
  2. mepc points to the exception PC or the next PC that would have executed if we didn't take the interrupt
  3. mstatus.MIE=0 (and the old value is in MPIE)
  4. if tcontrol is implemented then mte=0 (and the old value is in mpte)

Per section 5.4, item 3 and/or 4 should cause the itrigger/etrigger to not fire (since these triggers are defined to happen after the trap). This is also mentioned in non-normative text: "Both options prevent etrigger and itrigger from having any effect on exceptions and interrupts that are handled in M-mode."

Since the itrigger/etrigger doesn't fire, mcause should behave as required in the priv spec.

@timsifive
Copy link
Contributor

I agree this is confusing. I don't see the language that Paul references from Section 5.4.

I think what the existing text is trying to say is:

When the trigger fires:

  1. All actions caused by the original interrupt occur (including any CSR and PC updates).
  2. Then the action specified in the action field is taken. If action=0, this might overwrite some CSRs that were just updated in step 1, losing their value. See Section 5.4 for more discussion about this.

@pdonahue-ventana
Copy link
Collaborator

I don't see the language that Paul references from Section 5.4.

https://github.com/riscv/riscv-debug-spec/blob/master/Sdtrig.tex#L239

@timsifive
Copy link
Contributor

Fair enough, but that's just a conclusion in a commentary. I think we can be more clear about this. Do you agree with my 2-step interpretation above? If so, I can turn it into a PR.

@pdonahue-ventana
Copy link
Collaborator

5.4 says "Harts that support triggers with action =0 should implement one of the following two solutions..." If a hart does not follow that recommendation then I agree with your 2-step interpretation. If a hart does follow that recommendation then only your first step applies and the second step is skipped.

@jhauser-us
Copy link
Author

If a hart does follow that recommendation then only your first step applies and the second step is skipped.

I don't understand how this solves the problem originally raised by this issue. If an exception trigger has m = 1 and action = 0, it may fire when executing in M mode, and then the question remains, what value does the hardware write to mcause? Likewise for an interrupt trigger that fires when executing in M mode with mstatus.MIE = 1.

@pdonahue-ventana
Copy link
Collaborator

You quoted the "If a hart does follow that recommendation" line so I'm assuming that your question is about that. If a hart does follow that recommendation then it is impossible for an exception trigger with action=0 to fire when executing in M mode. See my first comment above for what will happen.

If your question is about a hart that doesn't follow that recommendation then presumably the hart writes mcause for the original exception, then the etrigger fires and the and the hart writes mcause=3 and mepc=mtvec (just as it would have written mcause=3 and mepc=stvec if the etrigger fired on a trap to S/HS mode). Note that the debugger will not be able to resume execution if the hart doesn't follow that recommendation so this whole mechanism is not very useful except in desperation.

@jhauser-us
Copy link
Author

You quoted the "If a hart does follow that recommendation" line [...]

Okay, sorry, I think I get it now. But we agree the spec still needs clarification for the case that a hart "does not follow that recommendation".

timsifive added a commit that referenced this issue Oct 9, 2023
Specifically, make clear that itrigger fires *after* the original
exception has finished updating all the CSRs.

Hopefully resolves #890.
timsifive added a commit that referenced this issue Oct 9, 2023
Specifically, make clear that itrigger fires *after* the original
exception has finished updating all the CSRs.

Hopefully resolves #890.
@pdonahue-ventana
Copy link
Collaborator

Yes. #901 will address this concern.

timsifive added a commit that referenced this issue Oct 9, 2023
Specifically, make clear that itrigger fires *after* the original
exception has finished updating all the CSRs.

Hopefully resolves #890.
@gagachang
Copy link

Per section 5.4, item 3 and/or 4 should cause the itrigger/etrigger to not fire (since these triggers are defined to happen after the trap). This is also mentioned in non-normative text: "Both options prevent etrigger and itrigger from having any effect on exceptions and interrupts that are handled in M-mode."

Hello @pdonahue-ventana
Does this imply that itrigger/etrigger will not fire in M-mode, until we mret to less privilege modes from this trap?
So itrigger/etrigger fires at first instruction after mret, am I correct?

@pdonahue-ventana
Copy link
Collaborator

Does this imply that itrigger/etrigger will not fire in M-mode, until we mret to less privilege modes from this trap?
So itrigger/etrigger fires at first instruction after mret, am I correct?

The spec says, "The hardware prevents triggers with action=0 from matching or firing while in M-mode
and while MIE in mstatus is 0." Your question seems to be whether it matches in M mode, sets a hidden pending bit*, and fires later. It doesn't match at all so it never fires. This complete lack of firing is why this mechanism will "prevent etrigger and itrigger from having any effect on exceptions and interrupts that are handled in M-mode."

* Hidden architectural state is generally a bad idea.

@gagachang
Copy link

Does this imply that itrigger/etrigger will not fire in M-mode, until we mret to less privilege modes from this trap?
So itrigger/etrigger fires at first instruction after mret, am I correct?

The spec says, "The hardware prevents triggers with action=0 from matching or firing while in M-mode and while MIE in mstatus is 0." Your question seems to be whether it matches in M mode, sets a hidden pending bit*, and fires later. It doesn't match at all so it never fires. This complete lack of firing is why this mechanism will "prevent etrigger and itrigger from having any effect on exceptions and interrupts that are handled in M-mode."

  • Hidden architectural state is generally a bad idea.

Hi @pdonahue-ventana Thanks for response.
Let me detail my problem:
I want to track "ecall from U-mode", my system is M/U only system, so this U-mode ecall will trap into M-mode.
Therefore, I prepare an etrigger as following:

  • tdata1: type=5, u=1, action=0
  • tdata2: 0x100, since mcause value of "Environment call from U-mode" is 8, I assert bit 8
  • tdata3: 0

In my M-mode ecall trap handler, mstatus.MIE and tcontrol.MTE are always 0, until mret to U-mode.
So, when will this etrigger breakpoint exception be taken ?

@pdonahue-ventana
Copy link
Collaborator

So, when will this etrigger breakpoint exception be taken ?

etrigger and itrigger will never fire in a M+U hart or in a M-only hart because all exceptions and interrupts are handled in M mode. "Both options prevent etrigger and itrigger from having any effect on exceptions and interrupts that are handled in M-mode."

If your handler is not ROM, try this: "Debuggers should use other mechanisms to debug these cases, such as patching the handler..." Or use an external debugger (which is normally how you'd have to debug a hart where the handlers are in ROM).

@gagachang
Copy link

etrigger and itrigger will never fire in a M+U hart or in a M-only hart because all exceptions and interrupts are handled in M mode. "Both options prevent etrigger and itrigger from having any effect on exceptions and interrupts that are handled in M-mode."

Now I understand it. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants