6.828: Operating System Engineering (51)
とりあえず remove とか lookup できちんと仕事をさせるべく修正検討。
pgdir_walk
んーと、戻してるのは page table entry の即値だな。check_va2pa だとこれをさらに PTE_ADDR なフィルタにかけたソレを戻してます。
つーかなんとなく間違えてるカンジがするなぁ。
check_va2pa だと
- pgdir[PDX(va)] の中身に PTE_ADDR なフィルタをかける
- 出てきたソレを KADDR なフィルタかけて p に代入
- p[PTX(va)] に PTE_ADDR なフィルタをかける
それが pgdir_walk だと
- pgdir[PDX(va)] の中身に PTE_ADDR なフィルタをかける
- 出てきたソレに PTE_ADDR なフィルタをかける
- さらにそこから出てきたソレに KADDR なフィルタかけて
- PTX(va) を加えたアドレスを戻す
もう自分ごとですが情無いったらありゃしないorz
とゆーことで pgdir_walk を作り直せば check_va2pa みたく使えるようになるはず。
で
pgdir_walk 手続きを、以下なカンジにしたら
pte = (pte_t *)KADDR(PTE_ADDR(*pde)); *pte |= PTE_P; } return (pte_t *)PTE_ADDR(pte[PTX(va)]);
動かなくなりました。ちなみに KADDR なフィルタを外したら正常動作 (?) した模様。なぜにこちらは KADDR なフィルタが不要なのか、とか理解できてないのがモロバレ。
あら? そうじゃない。元に戻したら assert に長くパスするなぁ。とりあえず PTE_ADDR なフィルタはムダなので以下なカンジにしてます。
*pde = page2pa(page); *pde |= PTE_P; pte = (pte_t *)PTE_ADDR(*pde); *pte |= PTE_P; } return (pte_t *)KADDR((physaddr_t)pte) + PTX(va);
とりあえずここはここで課題とゆーことにしといて、問題解決を。
page_lookup のソレ
とりあえず pgdir_walk は page table の先頭の kva を戻す形になってます。
assert(pgdir_walk(boot_pgdir, (void*)PGSIZE, 0) == ptep+PTX(PGSIZE));
ので、page_lookup で引数の pte_store に格納されるべきは以下なのかな。
pte = (pte_t *)PTE_ADDR(pte); *pte_store = (pte_t *)pte[PGOFF(va)];
で、page_insert に話を戻すと、現状以下の末端で panic してます。
// should be no free memory assert(page_alloc(&pp) == -E_NO_MEM); // should be able to map pp2 at PGSIZE because it's already there assert(page_insert(boot_pgdir, pp2, (void*) PGSIZE, 0) == 0); assert(check_va2pa(boot_pgdir, PGSIZE) == page2pa(pp2)); assert(pp2->pp_ref == 1);
page_insert の不具合だな。pp_ref をきちんと制御できていない模様。というか、ごにょごにょしてるんですが、どうもいけません。そもそも va に page ディスクリプタが mapped な状態かどうかをどうやって判断するのか、というと。
- pgdir_walk の戻りを基に page table entry の中身な phys addr げつ
- それを使って page ディスクリプタを取得
- valid かどうかを判断
- じゃなくて取得できるかどうかで判断するのか
valid かどうか、ってあたりを判断するためには page_remove できちんとクリアされてないと駄目なはず、pte が。あ、remove されたら、あるいは初期状態だったら 0x0 ってのが保証されてる必要があるのか。
とりあえず
- page_alloc で提供するページは 0 埋め保証
- page_remove で使用を止めるページは 0 代入
うーん。いいのかなぁ。というか page_remove の中から page_initpp 手続きは呼び出せないみたいなので上記でスルーします。
で
これが担保されていれば page_insert では pgdir_walk(pgdir, va, 0) の戻りを基に PGOFF(va) なソレを取り出して、その値がどうか、ということを見れば良いのかなぁ。
あら、でも page_insert で新規に確保した page table についてこんなことしてますが本当に良いのかなぁ。
pte_t *pte = pgdir_walk(pgdir, va, ~0); if (pte == NULL) return -E_NO_MEM; pp->pp_ref++; *pte = page2pa(pp); *pte = *pte | perm | PTE_P;
試験にパスしてるのが不思議でなりません。というかわしの理解が微妙なのだろうな。