Where traps go, who handles them, and which interrupts fire — the control plane of the trap unit.
3.1.7 mtvec
mtvec (0x305)
Reset and NMI vectors are separate, platform-defined addresses — mtvec governs ordinary traps only.
3.1.8 medeleg / mideleg: pushing traps down
With S-mode present, delegation trap delegation medeleg/mideleg bit i sends trap i occurring in S/U-mode to the S-mode handler (scause/sepc/stval/SPP/SPIE/SIE written; m* untouched). Traps never delegate downward from M-mode occurrences; delegated interrupts are masked at M. medeleg[11] and [16] read-only zero. defined in ch. II·3 — open in glossary lets S/U-mode traps bypass M entirely:
| Rule | |
|---|---|
| What a set bit does | Trap i occurring in S or U-mode → handled by the S-mode handler: scause/sepc/stval/SPP/SPIE/SIE written, SIE cleared — the m* registers stay untouched |
| Never downward | A trap occurring in M-mode ALWAYS stays in M, delegation notwithstanding |
| Interrupt masking | A delegated interrupt is MASKED at M: mideleg[5]=1 means STIs cannot be taken while in M-mode |
| Bit positions | medeleg bit i = mcause exception code i (64-bit; medelegh on RV32); mideleg matches mip layout |
| Hardwiring rules | No medeleg bit may be read-only ONE (delegable must support non-delegation); medeleg[11] (ecall-from-M) and [16] (double trap) are read-only ZERO; discover support by write-ones-readback |
3.1.9 mip / mie: the interrupt front door
Bit i corresponds to cause mcause Interrupt bit + WLRL code. Interrupts: 1/3 SSI/MSI, 5/7 STI/MTI, 9/11 SEI/MEI, 13 LCOFI. Exceptions: 0 IAM, 1 IAF, 2 illegal, 3 breakpoint, 4/6 load/store misaligned, 5/7 load/store access fault, 8/9/11 ecall U/S/M, 12/13/15 page faults, 16 double trap, 18 software check, 19 hardware error. defined in ch. II·3 — open in glossary i; bits 15:0 are standard, ≥16 platform/custom. The take-condition for interrupt i → M-mode mip/mie Interrupt pending/enable, bit i = cause i. Trap to M iff (mode<M, or M with mstatus.MIE) AND mip[i]&mie[i] AND !mideleg[i], evaluated in bounded time. Priority MEI>MSI>MTI>SEI>SSI>STI>LCOFI. MEIP/MTIP/MSIP read-only (controller/mtimecmp/msip-mapped); SEIP read = sw-bit OR controller signal but RMW acts on the sw bit only. defined in ch. II·3 — open in glossary :
(mode < M, or mode = M ∧ mstatus.MIE) and mip[i] ∧ mie[i] and ¬mideleg[i]
— evaluated within bounded time of any mip change and immediately after xRET or writes to mip/mie/mstatus/mideleg. Priority among simultaneous M-destined interrupts: MEI > MSI > MTI > SEI > SSI > STI > LCOFI.
| Bit | mip behavior | |
|---|---|---|
| MEIP/MEIE — machine external | 11 | Read-only; set/cleared by the platform interrupt controller (PLIC/APLIC) |
| MTIP/MTIE — machine timer | 7 | Read-only; pending iff mtime ≥ mtimecmp; cleared by writing mtimecmp |
| MSIP/MSIE — machine software (IPI) | 3 | Read-only; written via the memory-mapped msip register (32-bit, bit 0) |
| SEIP/SEIE — supervisor external | 9 | Software-writable bit B, OR’d with controller signal E: reads return B∨E, RMW sequences act on B only |
| STIP/STIE — supervisor timer | 5 | Writable by M if no stimecmp; read-only reflection of stimecmp when Sstc is active |
| SSIP/SSIE — supervisor software | 1 | Writable; controller-settable too |
| LCOFIP/LCOFIE — counter overflow | 13 | Read-write (Sscofpmf); reflects mhpmevent OF bits |
3.1.10–3.1.14 Counters, gates, scratch, and the return address
- mcycle / minstret (0xB00/0xB02): 64-bit writable masters of the Part I shadows; arbitrary reset value; a CSR write takes effect after the writing instruction completes (the u06 override rule). mcycle may be shared between harts of one core.
- mhpmcounter3–31 + mhpmevent3–31: platform-defined events (0 = none); counter+selector read-only zero is a legal implementation.
- mcounteren (exists iff U-mode): CY/TM/IR/HPMn bits gate the
next-lower mode’s access to the shadow CSRs — clear bit = illegal
instruction from S/U. TM also gates
stimecmp. Pure access control: counters keep counting regardless. - mcountinhibit: CY/IR/HPMn stop the counters themselves
(power/measurement); accessibility unaffected;
mtimeis not inhibitable (it’s shared platform state). - mscratch: the M-handler’s anchor — typically swapped with an
x-register in one
csrrwto obtain a save-area pointer without clobbering user state. - mepc: WARL, bit 0 always zero, bit 1 masked on reads while IALIGN=32 (yet writable underneath — surviving misa.C toggles); must hold every valid virtual address; written by hardware only when a trap is taken.
Hardware Designer Notes
This page plus mstatus is your interrupt unit’s RTL spec: a priority
encoder over (mip ∧ mie) split by mideleg, the mode/MIE geometry, and
the mtvec redirect. The classic bugs live in the corners called out
above — SEIP’s dual nature, delegated-interrupt masking in M, and the
bounded-time re-evaluation after CSR writes (a stale interrupt-pending
latch after csrw mideleg is a real-silicon erratum pattern).
Minimal Linux-boot hart MUST
- Implement the delegated-trap register split exactly: s* written, m* untouched, and the mode check BEFORE mstatus updates
- Mask delegated interrupts out of the M-mode take-condition
- Re-evaluate the interrupt condition after xRET and after writes to mip/mie/mstatus/mideleg — not just on mip edges
- Build the SEIP read=B∨E / RMW-on-B mux
- Mask mepc[1] on reads (including MRET’s) when IALIGN=32
MAY simplify / trap-and-emulate
- Support Direct mtvec mode only (MODE bit read-only 0) — Linux copes
- Hardwire all hpm counters/selectors to zero for v1
- Share one mcycle across a multithreaded core (document it)
Check yourself — vectoring, delegation & interrupts
1.mtvec.MODE=Vectored. Where does a machine timer interrupt (cause 7) land, and where does an illegal-instruction exception land?
2.medeleg delegates illegal-instruction (bit 2) to S-mode. M-mode firmware itself executes an illegal instruction. Who handles it?
3.With mideleg[5]=1 (STI delegated), can a supervisor timer interrupt be taken while the hart executes in M-mode?
4.csrrs t0, mip, t1 executes where the external controller asserts SEIP and the software SEIP bit is 0. What does t0[9] read, and what does the RMW write?
5.Why does mepc's bit 1 read as zero when IALIGN=32, yet remain writable underneath?