MMUを使ってメモリ保護をする意味

今さらなんですけど、ARM Cortex-Rのことを取り上げたとき、

Cortex-AではMMU(Memory Management Unit)を搭載している。

仮想アドレスを物理アドレスに変換する機能を持っており、高級なOSを使うなら必須だが、

複雑な仕組みであるために処理時間の大きな変動を招きかねないと。

なのでこの部分はよりシンプルな仕組みにしている。

(Cortex-Rシリーズはめんどくさい)

と書いたのだが、当時その真意はわかっていなかった。


MMUを使って仮想アドレスと物理アドレスを変換するメリットとして、

メモリのフラグメンテーションの対策になるという話は理解していた。

何も考えずにメモリの一定領域を占有して解放するというのを繰り返すと、

有効利用できない空き領域が発生してしまうことが考えられる。

このような現象をフラグメンテーションという。日本語で言えば断片化か。

対策はいろいろあるのだが、物理的には飛び飛びの領域を繋ぎあわせれば有効活用できる。

仮想アドレスで見れば一続きの領域が確保できているように見えるが、

物理的には飛び飛びの領域を繋ぎあわせたものになっていることがあると。


しかし、それにしてもリアルタイム性を阻害するほどMMUは悪いのか?

と気になっていたが、他にも重要な要素があった。

MMUのアドレス変換に使うページテーブルはメモリ上に格納するんですね。

いちいちメモリにアクセスしていたら変換に時間がかかって仕方ないので、

ページテーブル用のキャッシュを用意しているが、外れると大きなタイムロスが発生してしまうという。


そしてページテーブルをメモリ上に格納する理由でもあるけど、

プロセスごとにページテーブルを切り替えると、プロセス間のメモリ保護が実現できると。

ページテーブルの先頭アドレスをレジスタに格納すれば切り替えられる。

MMUはメモリ変換とともにメモリ保護の役割もある。

プロセスA用のページテーブルでは、プロセスAで使う領域だけアクセスを許可、

プロセスB用のページテーブルでは、プロセスBで使う領域だけアクセスを許可、

としておいて、プロセスを切り替えるごとにページテーブルを切り替えれば、

プロセス間のメモリ保護が実現できるというわけ。


そんなのも知らんかったのかと言われそうな話だが――

仮想アドレスから物理アドレスへの変換テーブルを容易に切り替えられることが、

結果としてメモリ保護というところにつながっていたんですね。


なんでこんな話を書いたかというと、新しいシステムではコアごとにメモリのアクセス範囲を制限しないといけないねという話があった。

ARMだとMPU(Memory Protection Unit)という仕組みで対応できる程度の話である。

MPUはレジスタベースで作られているから、それによるタイムロスはない。

ただ、レジスタベースだから機動的に切り替えるのは難しいと思われる。

特権モードと非特権モードでアクセス範囲を制限する程度に留まるのでは?


シンプルな仕組みで対応できればそれでよいとも言えるし、

複雑な仕組みにはそれだけのメリットがあるってことだな。

以前も書いたのだが、Cortex-RにはMMUを搭載したものも存在する。

Cortex-R82ではMMUを搭載してコアごとに有効/無効を選べる。

一部のコアではMMUを使わずリアルタイム処理、一部のコアではMMUを使ってLinuxを動かす、なんてことができますよと言っている。

MMUは必須ではないが、必要なら使うこともできると。

なんだそれはって思うけど、好きな方を選べるということ自体は悪くない。