riscv / riscv-fast-interrupt

Proposal for a RISC-V Core-Local Interrupt Controller (CLIC)
https://jira.riscv.org/browse/RVG-63
Creative Commons Attribution 4.0 International
237 stars 49 forks source link

xret pseudo Sail code #272

Closed Silabs-ArjanB closed 2 years ago

Silabs-ArjanB commented 2 years ago

I don't understand why the xret pseudo Sail code merged with https://github.com/riscv/riscv-fast-interrupt/pull/198 gets the inhv value of the previous privilege mode.

For example, assume a CPU with only machine mode and user mode that does not support user mode interrupts.

Suppose the core is either in user or machine mode and then takes a 'selective hardware vectored interrupt'. This interrupt will be taken in machine mode (as no user mode interrupts are supported in this example).

The spec states that:

When these interrupts are taken, the hart switches to the handler’s privilege mode, and besides the trap side effects described in this and the privileged specification (e.g. update xintstatus, xcause, xstatus fields including clearing xstatus.xie), also sets the hardware vectoring bit xinhv in xcause of the handler privilege mode.

So, the handler's privilege mode in above specification sentence will be machine mode and therefore mcause.minhv will be affected.

However, the mret will base its operation on prev_inhv which would be ucause.INHV in this example (although the ucause CSR would not even exist in this CPU and if it would exist it would not have been updated for the given scenario):

        Machine => match mstatus.MPP() {
           User       => prev_inhv = ucause.INHV();
           Supervisor => prev_inhv = scause.INHV();
           Machine    => prev_inhv = mcause.INHV();
         }

Shouldn't mret simply look at the xcause.xinhv bit of the current privilege mode?

dansmathers commented 2 years ago

when set, xinhv indicates that the xepc that xret will use contains the address of an address. when xinhv is not set, xpec contains the address of an instruction.
In your example, mepc contains the address of an instruction. if u-mode interrupts were supported, ucause.uinhv would be 0. I created a pull for the pseudo-code to make ucause_uinhv 0 when u-mode interrupts are not supported. so the pseudo-code in your example would treat mpec as containing the address of an instruction.

xinhv allows recovery if an exception or higher-priv interrupt occurred during previous privilege mode table vector read operation. e.g. a user-level interrupt takes a selective hardware vectored interrupt and a m-mode page-table fault occurs on the selective hardware vectored interrupt vector table access. mepc will contain the address of the u-mode vectored interrupt table. but minhv is not set because it was an m-mode exception. uinhv is set because it is a u-mode vectored interrupt page table read. so MRET has to use uinhv to know that mepc contains an address of an addresss.

Silabs-ArjanB commented 2 years ago

@dansmathers Thank you for your fast answer. I am afraid I still don't get it. Can you please tell me what is supposed to happen in the following scenario:

I assume that mcause.minhv was set (and did not get cleared) because of this, right?

I was thinking that mcause.minhv would need to be used if you want to perform an mret at this point in time, but I now see that it would not make sense to perform an mret as first the caused exception must get handled.

However, mepc at this point in time contains an address of a table entry (that contains a pointer), so executing an mret now would go horribly wrong. We can not rely on ucause.uinhv to properly indicate whether mepc contains an address to a pointer or an address to an instruction (without further software intervention). Your statement above that mepc will contain an address of an instruction must somehow be guaranteed by software (i.e. not hardware) in the triggered exception handler. Is this understanding correct?

dansmathers commented 2 years ago

For your example it is unrecoverable See the note below the pseudo-code. "horizontal traps (same privilege level) are unrecoverable." if you get a m-mode exception during a m-mode interrupt, mepc that was holding the code return address has been clobbered by the address of the hw vector table entry.

Silabs-ArjanB commented 2 years ago

@dansmathers Thank you for your explanations; it is clear to me now. Also thanks for the PR that takes care of the case in which the ucause CSR is not present.