- 默认情况下,所有的trap都是在machine mode中处理的;
- 虽然machine-mode可以通过调用MRET指令,来重新将traps给到其他的mode来执行,但是性能上并不好;
- 因此增加如下两个寄存器:mideleg/medeleg,分别将对应bit的excp/int指定给更低权限等级的mode执行;
- medeleg/mideleg都是可读可写的;
实现了S-Mode的系统,medeleg/mideleg是必须实现的,如果设置了对应的bit, 可以将s-mode/u-mode下的trap, 委托给s-mode处理,而不是m-mode;
没有实现S-mode的系统,可以不实现这两个寄存器;?
如果一个trap委托给了s-mode,需要做如下处理:
- scause记录trap cause;
- sepc记录发生异常的指令的pc;
- stval用来写入异常相关的数据;
- mstatus.SPP, 记录trap发生时候所处于的mode;
- mstatus.SPIE记录发生trap时,mstatus.SIE;
- mstatus.SIE被清除;
- 此时mcause/mepc/mtval/mstatus.MPP,mstatus.MPIE都不写入任何数据;
mideleg/medeleg,可以再进行细分,用每个bit表示需要将哪种类型的trap进行委托;
- 实现时,medeleg不应该有任何一个bit是read-only one的,因为任何一个异常,都应该可以指定是委托还是不委托;
- 实现时,mideleg中,与machine-level相关的bit,不应该是固定read-only one的;其他lower-level的是可以的;
M-mode产生的traps, 不能delegate到S-mode; 但是,S-mode的traps, 可以delegate到S-mode, 也就是说,可以平级的delegate;
- 如果某一个中断,被delegate了,那么在被delegate的那个privilege level, 该中断就被mask了;
- 例如,如果STI被delegate到S-mode, 那么,如果当前的mode是M-mode, 此时发生了STI,则不会被处理,会被mask掉;
- 对于更低等级的level, medeleg应该是read-only zero的;
- 中断委托,不能把M-mode的中断委托给S-mode;
- mideleg/medeleg,只能在M-mode下访问和修改;