vm.c void freevm(pde_t *pgdir)
トップページ
jupiteroak.hatenablog.com
vm.c
https://github.com/mit-pdos/xv6-public/blob/master/vm.c#L283
void freevm(pde_t *pgdir) { uint i; if(pgdir == 0) panic("freevm: no pgdir"); deallocuvm(pgdir, KERNBASE, 0); for(i = 0; i < NPDENTRIES; i++){ if(pgdir[i] & PTE_P){ char * v = P2V(PTE_ADDR(pgdir[i])); kfree(v); } } kfree((char*)pgdir); }
ユーザー空間に関わる、ページディレクトリのメモリ領域、全てのページテーブルのメモリ領域、全てのページフレーム(4KBのメモリ領域)を解放します。
引数 pde_t *pgdir
ページディレクトリを指定する先頭アドレスです。
処理の内容
- ページディレクトリがない場合はメッセージを出力する
- ユーザー空間にマッピングされている全てのページフレームを解放する
- 全てのページテーブルに割り当てられているメモリ領域を解放する
- ページディレクトリに割り当てられているメモリ領域を解放する
ページディレクトリがない場合はメッセージを出力する
if(pgdir == 0) panic("freevm: no pgdir");
引数pgdirがページディレクトリを指定していない場合は、panic関数を呼び出してメッセージを出力します。
ユーザー空間にマッピングされている全てのページフレームを解放する
deallocuvm(pgdir, KERNBASE, 0);
deallocuvm関数を呼び出して、ユーザー空間にマッピングされている全てのページフレーム(仮想アドレス0から仮想アドレスKERNBASE(#define KERNBASE 0x8000 0000)未満の範囲にマッピングされている全ての4KBのメモリ領域)を解放します。
全てのページテーブルに割り当てられているメモリ領域を解放する
for(i = 0; i < NPDENTRIES; i++){ if(pgdir[i] & PTE_P){ char * v = P2V(PTE_ADDR(pgdir[i])); kfree(v); } }
for文を使って、全て(#define NPDENTRIES 1024)のページディレクトリエントリpgdir[i]にアクセスします。
if文の条件では、pgdir[i]の値(32bit)をPTE_P(#define PTE_P 0x001)でマスク処理することにより、pgdir[i]のbit0(ページディレクトリエントリのPフラグ)を取り出しています。pgdir[i] & PTE_Pが真となる場合→pgdir[i]のbit0(ページディレクトリエントリのPフラグ)が1となる場合→pgdir[i](ページディレクトリエントリ)が参照しているページテーブルが存在する場合は、ページディレクトリエントリpgdir[i]が参照しているページテーブルに割り当てられているメモリ領域を解放します。
PTE_ADDRマクロを使うことで、ページディレクトリエントリpgdir[i]からページテーブルの先頭アドレスを取得しています。
取得したページテーブルの先頭アドレスは物理アドレスなので、P2Vマクロを使って物理アドレスPTE_ADDR(pgdir[i])を仮想アドレスvに変換しています。