訳あってRISC-Vの特権レジスタ群の仕様を読み込んでいるのだが、Privilege Instructionの仕様書をしっかり読むとなかなか面白い。 Chapter-2のControl and Status Registers(CSR)ではCSRレジスタ群についてまずは簡単に分類がされているのだが、いろんなことを考慮した構成になっているのでまとめてみようと思う。
CSRレジスタ群のアドレスマップ
そもそもCSRレジスタ群は12ビットのアドレスマップから構成されており、最大で4096個のCSRレジスタを格納することができる。この12ビットのアドレスは上位から分類がなされており、まとめると大体以下のようになる。
11:10 | 9:8 | 7:6 | 5:0 | |
---|---|---|---|---|
Read-Write Accesibilty | Lowest Privilege | Standard/Non-standard | Others | |
00 | Read & Write | User | Standard | |
01 | Read & Write | Supervisor | Standard | |
10 | Read & Write | Hypervisor | Standard | |
11 | Read Only | Machine | Non-standard |
つまり、上位の11-10ビットは読み書きの特性を表し、9-8ビットはアクセス可能な特権モード、7-6ビットは特殊なモードかどうかを指定するレジスタとなる。このように分類することで、ハードウェアが特権アクセス違反などを簡単に検出することができるようになる。
Shadow Registersについて
RISC-VのCSRを読み解いていると、CSRレジスタマップ上にShadow-Registersという空間が定義されているのがわかる。 Shadow-Registerについて簡単にまとめると
ということになる。このような空間を用意した理由として、たとえばユーザモードではRead-Onlyだが、マシンモードではRead-Write可能なCSRが存在しているとすると、そのレジスタをShadow-Registerに配置しておく。 すると、通常はユーザモードでアクセスすると特権例外でReadすら出来ないのだが、Shadow-Registerに配置しておくとWriteは出来ないがReadは可能になる。 これにより仮想マシンなどユーザモード中で動作するプログラムが特権モードを取得するために例外に飛ぶ機会を減らすことが出来る(という理解で良いのだろうか?)。
たとえば、マシンモードのShadow-Registerには以下のレジスタ群が割り当てられていた。
これはパフォーマンスカウンタは、読み取り専用なのでユーザモードから読めても良い、ということなのだろうか。まあ、書き込みさえ出来なければ、ユーザモードから直接このような性能調査系のシステムレジスタは読めても良い気がする。
StandardレジスタとNon-standardレジスタ群について
StandardレジスタとNon-standardレジスタ群の違いについては、
- Standard : この仕様以降で再定義されることがある
- Non-standard : この仕様以降で再定義されることはない
というものらしい。イメージでは逆のような気がするのだけれども?