結構昔にRISC-VのPMP機構(Physical Memory Protection)について調査したのだった。
改めて復習しているが、PMPのNAPOTについてあまり明確に理解していなかった。 PMPのアドレス範囲選択については、3つのモードがある:
pmpcfg[*].A == 0
: 無効pmpcfg[*].A == 1
: TOR(Top of Range)pmpcfg[*].A == 2
: NA4(Naturally aligned four-byte region)pmpcfg[*].A == 3
: NAPOT(Naturally aligned power-of-two region, >=8)
TORについては、2つのpmp領域を利用してマッチングアドレスの上下を設定する。
NA4とNAPOTは似ていて、NAPOTはアドレスの範囲の指定領域が2の累乗バイトに限定されるアドレス範囲の指定方法である。
アドレス範囲はpmpaddr[*]
を使って指定するのだが、ここで注意するのはpmpaddr[*]
のアドレスは4バイトアラインであり、下位の2ビットは右に2ビットシフトされて節約されている。
ここで、NAPOTのアドレス指定方式について見ていく。仕様書の中では という変数が使われているが、これはおそらくハードウェアで指定されたアドレス領域の粒度(Granularity)の意味だと思う。ここでは、例えば8バイト粒度だと として取り扱うことにする(/4としているのはNAPOTが4バイト粒度以下をサポートしていないから)。
まず、pmpcfg
を書き込んでNAPOTモードにすると、当該pmpaddr
レジスタの ビットの位置までがすべて1に設定される(のときはどこも1に設定されない)。これはNAPOTモードを解除すると解放される。
これはどういう意味なんだろうととちょっと考えていたのだが、普通に考えるとマッチングのアドレス領域を簡単に指定しようとしているのだと気が付く。
例えば、上記の図で16-byteの粒度の場合、NAPOTのアドレスマッチング範囲はyyyy...yy00
から yyyy...yy01
までとなる(実際には下位にビットが省略されているので、 yyyy...yy0000
から yyyy...yy0111
までとなる。
TORと同じ機構でアドレスの比較ができるため、このような仕組みになっているのか、と思っている。
ただ、上記の例だと0x0~0x7までしかチェックできないため1ビット分足りないな?どういう仕組みになっているんだろう。