xv6を読む:アドレススペースの作成
xv6というOSがある。これは、UNIX V6をベースに(?)MITで開発された教育用のOSである。x86アーキテクチャで動作する。MITなどのアメリカの大学が凄いと思うのは、授業の教材や講義の録画をネットで公開してしまうことである。xv6もテキストとソースコードが公開されている:
http://pdos.csail.mit.edu/6.828/2011/xv6.html
xv6のテキストは、解説とソースコードがLions' Commentaryのように2分冊になっている。それぞれ100ページ以下である。テキストを読み進めてみると、xv6は、x86アーキテクチャとその応用であるOSを勉強するのに格好の教材になりそうだ。
そこで、勉強の成果を忘れないようにメモしておくため、そして、もしかしたら私のメモが役に立つという人もいるかもしれないので、このブログでまとめていくことにする。もちろん、ツッコミは大歓迎である。今回は、アドレススペースの作成である。
OSのブート後、main関数が呼ばれる。最初に、main関数では、アドレススペースの作成が行われる。ここでは、仮想アドレスから物理アドレスへマップするページテーブルを作成する。x86での仮想アドレスは3つの部分を持つ。以下に、mmu.hから引用する:
main
:
+->kvmalloc
| +->setupkvm
| | +->mappages
| | +->walkpgdir
| +->switchkvm
:
setupkvm関数では次の処理を行う:
mappages関数は次の処理を行う:
http://pdos.csail.mit.edu/6.828/2011/xv6.html
xv6のテキストは、解説とソースコードがLions' Commentaryのように2分冊になっている。それぞれ100ページ以下である。テキストを読み進めてみると、xv6は、x86アーキテクチャとその応用であるOSを勉強するのに格好の教材になりそうだ。
そこで、勉強の成果を忘れないようにメモしておくため、そして、もしかしたら私のメモが役に立つという人もいるかもしれないので、このブログでまとめていくことにする。もちろん、ツッコミは大歓迎である。今回は、アドレススペースの作成である。
OSのブート後、main関数が呼ばれる。最初に、main関数では、アドレススペースの作成が行われる。ここでは、仮想アドレスから物理アドレスへマップするページテーブルを作成する。x86での仮想アドレスは3つの部分を持つ。以下に、mmu.hから引用する:
+--------10------+-------10-------+---------12----------+
| Page Directory | Page Table | Offset within Page |
| Index | Index | |
+----------------+----------------+---------------------+
\--- PDX(va) --/ \--- PTX(va) --/
仮想アドレスは、それぞれ10ビットのページディレクトリインデックスとページテーブルインデックス、そして12ビットのページ内オフセットからなる。それぞれの意味を以下に示す:
アドレススペースの作成は、main関数からのkvmalloc関数の呼び出しで行う。setupkvm関数でページディレクトリを作成し、それをswitchkvm関数でCR3レジスタに設定する。関数の呼び出し関係を以下に示す:
main
:
+->kvmalloc
| +->setupkvm
| | +->mappages
| | +->walkpgdir
| +->switchkvm
:
setupkvm関数では次の処理を行う:
- ページディレクトリ用に1ページ(4KB)を割り当てる
- 次の各カーネル領域について、mappages関数を呼び出すことで、ページテーブルを作成し、ページディレクトリエントリに書きこむ:
- 作成したページテーブルを、1のページディレクトリに書き込み、返す
ここで、各カーネル領域は任意の大きさでよい。mappages関数に領域のサイズを渡すことで、必要な分だけページテーブルが割り当てられる。
- walkpgdir関数を呼び出し、引数で渡された仮想アドレスに対応する、ページテーブルエントリを取得する
- エントリにマップする物理アドレス、アクセス権、存在ビットを書きこむ
- 領域全体をマップし終わるまで1から繰り返す
walkpgdir関数は次の処理を行う:
- ページディレクトリから、ページディレクトリインデックスに該当するエントリを引く
- 1で引いたエントリの存在フラグが立っていれば、ページテーブルを取得する(エントリに記述されているアドレスに存在するはず)
- 2でない場合、関数の引数でallocフラグに真が渡された場合(この場合はそうである)、新たに1ページ取得し、これをページテーブルとする。このページテーブルの物理アドレス、存在ビット、書き込み可ビット、ユーザ空間ビットを、1で取得したエントリに書きこむ
- 2または3で取得したページテーブルから、ページテーブルインデックスに該当するエントリのアドレスを返す
以上で、アドレススペースを作成した。ただし、ここで作成したのはページテーブルまでで、物理ページの割り当ては行っていない。次回は、テキストに従って、物理メモリの割り当てに進みたい。