vm.c void inituvm(pde_t *pgdir, char *init, uint sz)
トップページ
jupiteroak.hatenablog.com
vm.c
https://github.com/mit-pdos/xv6-public/blob/master/vm.c#L182
void inituvm(pde_t *pgdir, char *init, uint sz) { char *mem; if(sz >= PGSIZE) panic("inituvm: more than a page"); mem = kalloc(); memset(mem, 0, PGSIZE); mappages(pgdir, 0, PGSIZE, V2P(mem), PTE_W|PTE_U); memmove(mem, init, sz); }
引数pgdirが指定するページディレクトリに仮想アドレス0x0000 0000~0x0000 0FFFと割り当てたページフレーム(4KBのメモリ領域)のマッピングを設定し、そのページフレームに先頭アドレス init・サイズがszのメモリ領域に格納されている内容をロードします。
引数 pde_t *pgdir
設定対象となるページディレクトリの先頭アドレスです。
引数 char *init
ページフレームにロードさせたい内容を含んだメモリ領域の先頭アドレスです。
引数 uint sz
ページフレームにロードさせたい内容を含んだメモリ領域のサイズ(バイト単位)です。
処理の内容
- サイズszが4KB以上の場合はメッセージを出力する
- ページフレームとして使用する4KBのメモリ領域を割り当てる
- ページフレームを0で初期化する
- ページフレームのマッピングを行う
- ページフレームに先頭アドレス init・サイズがszのメモリ領域に格納されている内容をロードする
サイズszが4KB以上の場合はメッセージを出力する
if(sz >= PGSIZE) panic("inituvm: more than a page");
サイズszが4KB(#define PGSIZE 4096)以上になる場合は、panic関数を呼び出して、メッセージを出力します。
ページフレームとして使用する4KBのメモリ領域を割り当てる
mem = kalloc();
kalloc関数を呼び出して、ページフレームとして使用する4KBのメモリ領域を割り当てます。
ページフレームを0で初期化する
memset(mem, 0, PGSIZE);
memset関数を呼び出して、ページフレームとして使用する4KB(#define PGSIZE 4096)のメモリ領域を0で初期化します。
ページフレームのマッピングを行う
mappages(pgdir, 0, PGSIZE, V2P(mem), PTE_W|PTE_U);
mappages関数を呼び出して、pgdirで指定されたページディレクトリに、仮想アドレス0~0+PGSIZE-1と物理アドレスV2P(mem)~ V2P(mem)+PGSIZE-1 のマッピングを設定します(0x0000 0000~0x0000 0FFFと物理アドレスV2P(mem)~V2P(mem)+0x0FFFのマッピングを設定します)。
ページフレームとして使用する4KBのメモリ領域の先頭アドレスmemは仮想アドレスなので、V2Pマクロを使って物理アドレスにV2P(mem)に変換しています。
マッピングで使用するPTEのbit1(ページテーブルエントリのR/Wフラグ)を1、PTEのbit2(ページテーブルエントリのU/Sフラグ)を1にするために、mappages関数の第3引数にPTE_W(#define PTE_W 0x002)とPTE_U(#define PTE_U 0x004)の論理和を指定しています。
PTEのbit1(ページテーブルエントリのR/Wフラグ)が1の時は、ページフレームが読み書き可能であることを示しています。
PTEのbit2(ページテーブルエントリのU/Sフラグ)が1の時は、ユーザープロセスがページフレームにアクセスできることを示しています。