RISC-Vの権限階層は4階層構造を取っている。強い方から順に、
- Machine Mode
- Hypervisor Mode
- Supervisor Mode
- User mode
ちなみに、Hypervisorモードはまだちゃんとした規定が無い。命令については、Under constructionという感じだ。とりあえずパタンとしては、User→Supervisor→Machineモードと遷移していっても問題無い気がする。 もちろん、上位の階層のシステムレジスタに書き込むことはできない。例外処理などのために、RISC-Vのシステムレジスタは各階層別にシステムレジスタを保持している。
- mstatus, mepc, mcause, etc... ; マシンレベルでのCPUの状態を示す
- hstatus, hepc, hcause, etc... ; ハイパーバイザレベルでのCPUの状態を示す
- sstatus, sepc, scause, etc... ; スーパバイザレベルでのCPUの状態を示す
などが存在する。
ひとまず、あるCPUの実行モード中に例外が発生(ミスアラインアクセスなど)すると、Trapベクタに従って例外に飛ぶ。このとき、権限が一つ上げられる。
例外ベクタ中で要因(xstatusレジスタに格納される)を解析し、要因ごとに処理を実施するのだと思う。 また、権限を一つ上げたり、元に戻ったりするためには、以下の命令が用意されている。
- ECALL; 一つ上の権限に上がる。Trapを発生し、必要な情報をシステムレジスタに記録して、権限を上げる。
- EBREAK; ブレークポイント例外を発生させる。
- ERET; 前の権限に戻る。必要な情報をシステムレジスタから書き戻す。
これらの基本的な権限と、例外処理系の機構が備わっていれば、とりあえずテストパタンを複雑なやつも、通るようになると思う。
滅茶苦茶な実装だが、とりあえず自作シミュレータにトラップ系の機構と階層機構を定義して実行してみた(まだ権限毎のライトプロテクトとか全然である)。
[M] 99 : [000002f0] 02049063 : bne r09,r00,0x01 r09=>00000000 r00=>00000000 [M] 100 : [000002f4] 00400313 : addi r06,r00,0x004 r00=>00000000 r06<=00000004 [M] 101 : [000002f8] 342022f3 : csrrs r05,0x342,r00 r00=>00000000 mcause=>00000004 r05<=00000004 [M] 102 : [000002fc] fc6298e3 : bne r05,r06,0x7e r05=>00000004 r06=>00000004 [M] 103 : [00000300] 341022f3 : csrrs r05,0x341,r00 r00=>00000000 mepc=>00000280 r05<=00000280 [M] 104 : [00000304] 00828293 : addi r05,r05,0x008 r05=>00000280 r05<=00000288 [M] 105 : [00000308] 34129073 : csrrw r00,0x341,r05 mepc=>00000280 r05=>00000288 mepc<=00000288 r00<=00000280 [S] 106 : [0000030c] 10000073 : eret mepc=>00000288 pc<=00000288 [S] 107 : [00000288] 00600e13 : addi r28,r00,0x006 r00=>00000000 r28<=00000006 <Error: Address Misalign: Byte Addr = 000002f3> [M] 108 : [0000028c] 00342003 : lw r00,r08,0x003 r08=>000002f0 mepc<=0000028c mcause<=00000004 stvec=>00000140 pc<=00000140 (000002f3)=>ffffffff r00<=ffffffff [M] 109 : [00000140] 34202f73 : csrrs r30,0x342,r00 r00=>00000000 mcause=>00000004 r30<=00000004 [M] 110 : [00000144] fa0f5ee3 : bge r30,r00,0x7d r30=>00000004 r00=>00000000 pc<=00000100 [M] 111 : [00000100] 00000f17 : auipc r30,0x00000 r30<=00000100 [M] 112 : [00000104] 22cf0f13 : addi r30,r30,0x22c r30=>00000100 r30<=0000032c [M] 113 : [00000108] 34102ff3 : csrrs r31,0x341,r00 r00=>00000000 mepc=>0000028c r31<=0000028c [M] 114 : [0000010c] 07ff0c63 : beq r30,r31,0x03 r30=>0000032c r31=>0000028c [M] 115 : [00000110] 00000f17 : auipc r30,0x00000 r30<=00000110 [M] 116 : [00000114] ef0f0f13 : addi r30,r30,0xef0 r30=>00000110 r30<=00000000 [M] 117 : [00000118] 020f1863 : bne r30,r00,0x01 r30=>00000000 r00=>00000000 [M] 118 : [0000011c] 00000f17 : auipc r30,0x00000 r30<=0000011c [M] 119 : [00000120] 1d4f0f13 : addi r30,r30,0x1d4 r30=>0000011c r30<=000002f0 [M] 120 : [00000124] 1c0f1663 : bne r30,r00,0x0e r30=>000002f0 r00=>00000000 pc<=000002f0 [M] 121 : [000002f0] 02049063 : bne r09,r00,0x01 r09=>00000000 r00=>00000000 [M] 122 : [000002f4] 00400313 : addi r06,r00,0x004 r00=>00000000 r06<=00000004 [M] 123 : [000002f8] 342022f3 : csrrs r05,0x342,r00 r00=>00000000 mcause=>00000004 r05<=00000004 [M] 124 : [000002fc] fc6298e3 : bne r05,r06,0x7e r05=>00000004 r06=>00000004 [M] 125 : [00000300] 341022f3 : csrrs r05,0x341,r00 r00=>00000000 mepc=>0000028c r05<=0000028c [M] 126 : [00000304] 00828293 : addi r05,r05,0x008 r05=>0000028c r05<=00000294 [M] 127 : [00000308] 34129073 : csrrw r00,0x341,r05 mepc=>0000028c r05=>00000294 mepc<=00000294 r00<=0000028c
かろうじてミスアラインのテストパタンは通るようになったかなー。上記のログを見ると、Supervisorのモードでミスアライン例外が発生して、マシンモードに遷移している。 このとき、スーパバイザからの遷移は、Trapベクタによって0x140に飛ぶと規定されているので、そのようになっている。 xcauseレジスタに格納されている(この場合はmcause)のは、例外の要因だ。
この規定によると、ミスアラインアクセスの場合はException Codeとして4を挿入することになっているので、mcauseに4を入れたという訳だ。ここらへんの機構としては、一応理解はしたつもりだけど、まだ通らないパタンがあるなー。