risc-v

Definition

Exception (RISC-V)

An exception is an event detected by the processor that transfers control to an exception handler.

In RISC-V, the handler address is stored in mtvec. The handler uses mcause to identify the cause of the exception, may save registers in mscratch, and can use mepc to resume execution after handling.

Handling

When the processor detects an exception:

  • it jumps to the exception handler address in mtvec
  • the handler saves registers, often using mscratch
  • the handler reads mcause to determine the cause
  • the handler processes the exception
  • if execution should resume, the handler may increment mepc by 4
  • the handler restores registers and returns with mret

If the exception cannot be recovered from, the handler may abort the program instead of returning.

Examples

Simple exception return

A handler can simply skip the faulting instruction and return.

# exception handler
csrr t0, mepc      # load faulting PC
addi t0, t0, 4     # skip the faulting instruction
csrw mepc, t0      # write back updated PC
mret               # return to program

This is useful when the exception is recoverable and the program should continue at the next instruction.

Example exception handler code

The following handler checks two exception types:

  • illegal instruction (mcause = 2)
  • load address misaligned (mcause = 4)
# save registers that will be overwritten
csrrw t0, mscratch, t0    # swap t0 and mscratch
sw    t1, 0(t0)           # [mscratch] = t1
sw    t2, 4(t0)           # [mscratch+4] = t2
 
# check cause of exception
csrr  t1, mcause          # t1 = mcause
addi  t2, x0, 2           # t2 = 2 (illegal instruction exception code)
illegalinstr:
    beq   t1, t2, checkother  # branch if not an illegal instruction
    csrr  t2, mepc           # t2 = exception PC
    addi  t2, t2, 4          # increment exception PC
    csrw  mepc, t2           # mepc = t2
    j     done               # restore registers and return
checkother:
    addi  t2, x0, 4          # t2 = 4 (load address misaligned exception code)
    bne   t1, t2, exit       # branch if not a misaligned load
    j     exit               # exit program
 
# restore registers and return from the exception
done:
    lw    t1, 0(t0)          # t1 = [mscratch]
    lw    t2, 4(t0)          # t2 = [mscratch+4]
    csrrw t0, mscratch, t0    # swap t0 and mscratch
    mret                      # return to program
exit:

Checks for two types of exceptions:

  • illegal instruction (mcause = 2)
  • load address misaligned (mcause = 4)