ARMの仮想化支援機能を使ってみたかったので, 現在しゅううさん(@syuu1228)と一緒に教育用自作VMMを作成中です. もちろん,BareMetalで.
対象ボードは,とりあえずCortex-A7を積んだRaspberry Pi 2を予定中. (ARM64なボードが届いたらそちらに移るかも?)
まだ色々調べている段階なので,道中わかったことをメモしていきます.
ARMの仮想化支援
ARMの仮想化支援機構は,Cortex-A15(+ Cortex-A7)から導入された. ここで行われた主なアーキテクチャ拡張は以下の3つ:
- ハイパバイザモードの追加
- 2重メモリアドレス変換機能
- 物理アドレス空間の40bitへの拡張
各機能の詳細はまだ調べきれていない. 以下の資料を参照.
http://www.hotchips.org/wp-content/uploads/hc_archives/hc22/HC22.23.220-1-Brash-ARMv7A.pdf
VMMの概要
ホストOSとゲストOSの動作イメージが,うまくつかめていない.
以下の資料を見る限りだと,VMMはHYPモードで動くが,ホストOSとゲストOSはどちらもSystemモードとユーザーモードで動くらしい.
http://www.linux-kvm.org/wiki/images/d/d4/2012-forum-arm-christoffer-dall.pdf
つまり,
モード | OS |
---|---|
User | ゲストOS |
System | ホストOS |
HYP | ハイパバイザ |
ではなく
モード | OS |
---|---|
User | ホスト & ゲストOS |
System | ホスト & ゲストOS |
HYP | ハイパバイザ |
というイメージで動くっぽい.
ゲストOSからハイパバイザへの復帰,HWアクセスのトラップ方法についてはまだわかってない(後者はSystem MMUというのを使うっぽい?).
System MMUの資料(要ログイン)
MMUの有効化方法
VMMを作るにはMMUの理解が必須だと思うけれど,私はMMUについて全く知らない.
これではまずいので,MMUについて理解を深めるため,まずはRaspberry Pi 2のMMUを有効化する方法について調べ始めた.
資料
資料は以下の3つ:
一番最後の資料はRenesasの資料.
日本語なのでわかりやすいけど,説明が一部間違っているようなので注意.
VMSAとPMSA
アーキテクチャマニュアルを読むと,メモリシステムアーキテクチャの項目が,VMSAとPMSAの2つある.両者の違いは以下.
アーキテクチャ | 説明 |
---|---|
VMSA | MMUベースの仮想メモリシステムアーキテクチャ.Cortex-A対象 |
PMSA | MPUベースの保護メモリシステムアーキテクチャ.Cortex-R対象 |
つまり今回はCortex-A7が対象なので,VMSAについて調べれば良い.
Renesasの資料は,どうも一部の記述がVMSAとPMSAを間違えているようなので,適宜読み替えて読む(もしかするとRenesasのCortex-A9では正しいのかもしれない)
MMUアドレス変換の仕組み
まだ説明できるほど理解してない.
とりあえず,アドレスの変換のレイアウトを物理アドレスと同じにすれば,物理アドレスの時と同じように扱えるっぽい.
MMUの初期化
起動直後はMMUが無効になっているので,有効にしないといけない.
各種L2キャッシュはMMUが動いていないと使えないので,MMU動かすついでにL2キャッシュも有効にしてあげるといいらしい.
有効化までの手順は先ほど上げたRenesasの資料にわかりやすく書かれており,以下のようにすれば良い.
- TLBの初期化
- 命令キャッシュの初期化(Invalidate)
- データキャッシュの初期化
- 予測分岐の初期化
- MMU, 命令キャッシュ,データキャッシュ, 分岐予測の有効化
※ MMUの初期化手順のみなら,アーキテクチャマニュアルの「Enabling MMUs」にも書かれている.
コプロセッサ設定のやり方
MMUやキャッシュの設定はメモリの特定アドレスにアクセスして行うのではなく,コプロセッサに対し専用命令を使って行う.
専用命令は以下の2つ. 前者が書き込み命令で,後者が読み込み命令
命令 | 構文 |
---|---|
mcr | mcr pn, Op1, Rt, CRn, CRm, Op2 |
mrc | mrr pn, Op1, Rt, CRn, CRm, Op2 |
構文の各項目の意味は以下.
項目 | 説明 |
---|---|
pn | 命令が実行されるコプロセッサ名 |
Op1,2 | コプロセッサ固有のオペコード |
Rt | コプロセッサとデータをやりとりするARMレジスタ |
CRn, CRm | コプロセッサレジスタ |
Rtを除く項目は,アーキテクチャマニュアルに命令と項目の対応表があるので,参考に設定する.
TLBの初期化
TLBの初期化(Invalidate)は,TLBIALLレジスタを叩いて行う. Rtの値は不問.
mcr p15, 0, r0, c8, c7, 0
命令キャッシュの初期化
キャッシュにはゴミが残ってる可能性があり,これを掃除しないと実メモリにゴミが書かれてしまうかもしれないので,こちらも初期化を行う.
命令キャッシュの初期化はICIALLUレジスタに0を書き込んで行う.
mov r0, #0 mcr p15, 0, r0, c7, c7, 0
データキャッシュの初期化
データキャッシュの初期化はDCISWレジスタに0を書き込んで行う.
mcr p15, 0, r0, c7, c6, 0
分岐予測キャッシュの初期化
分岐予測の初期化はDCISWレジスタに0を書き込んで行う.
mcr p15, 0, r0, c7, c5, 6
MMU, 命令キャッシュ, データキャッシュ, 分岐予測 の有効化
MMUとキャッシュの有効化は,システム制御レジスタ SCTLR で行う. このレジスタのキャッシュとMMUに関するビットを立てると,各機能が有効になる.
ビット | 機能 |
---|---|
12 | 命令キャッシュ |
11 | 分岐予測 |
1 | データキャッシュ |
0 | MMU |
movw r0, #0x1803 mcr p15, 0, r0, c1, c0, 0
MMUの初期設定
今後の課題.
参考になりそうなサイトとか
Enabling HYP mode on the Raspberry Pi 2 | flexVDI
http://www.linux-kvm.org/wiki/images/d/d4/2012-forum-arm-christoffer-dall.pdf