6.828: Operating System Engineering (52)

粗探しというか机上デバグというか。

pgdir_walk

手続き末端で以下なナニ

        *pde = page2pa(page);
        *pde |= PTE_P;
        pte = (pte_t *)PTE_ADDR(*pde);
        *pte |= PTE_P;

最後のソレは意味ない。とりあえず pgdir_walk は page table の先頭の kva を戻す形になってます。

page_insert

昨晩大丈夫か、と言ったのは pgdir_walk から戻るのは 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;

なことをヤッても良いのか、駄目でしょ、って意図でした。実際は pte[PGOFF(va)] に格納しないと駄目なのだと思いますがどうなのか。

修正盛り込み

以下なカンジにして

    pte[PGOFF(va)] = page2pa(pp);
    pte[PGOFF(va)] |= perm | PTE_P;

make qemu してみたら以下で panic している模様。ちょっと進歩したのかどうなのか。

    assert(check_va2pa(boot_pgdir, PGSIZE) == page2pa(pp2));

ええと、page_insert でこんなことしてるな。

    pte_t *tmp = pgdir_walk(pgdir, va, 0);
    if (tmp != NULL) {
        pte_t *addr = (pte_t *)PTE_ADDR(tmp);
        if (addr[PGOFF(va)] != 0x0) {

tmp[PGOFF(va)] で良いはず。でも変わりはなさげ。

むむ

pgdir_walk(pgdir, va, 0)[PGOFF(va)] が valid かどうか、って存在フラグ使えば良いの? でも pgdir_walk が戻すソレがいっちゃん上で書いてる_page table の先頭の kva を戻す_形になってては page_lookup の中でフラグが付いたソレを取得できぬ。
あ、じゃないや。フラグ付きですね。こうなっているので。

        pte = (pte_t *)PTE_ADDR(*pde);
    }

    return (pte_t *)KADDR((physaddr_t)pte) + PTX(va);

と、ゆーことは

  • page_insert では pgdir_walk(pgdir, va, 0) の戻りが NULL でなくて戻りと PTE_P が偽でなかった場合は valid 判定
  • page_lookup では pgdir_walk(pgdir, va, 0) の戻りが NULL でなくて戻りと PTE_P が偽でなかった場合に pte_store に値を設定すれば良い
  • page_remove では削除された場合、*pte から PTE_P フラグを除く

という形で良いのかどうか。

盛り込んでみた

ちょい進んだかも。

    // 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);

上記末端で panic してます。pp_ref は 2 な模様。なんとゆーか行って戻ってなカンジが微妙。ここですが、状況として

  • 0x0 に pp1 で insert
  • 再度 0x0 に pp1 で insert
  • PGSIZE に pp2 で insert
  • free なメモリはないけど PGSIZE に pp2 で insert

の末端部分で失敗してるのですが、page_remove して page_alloc するロジックがダウトらしいです。以下な部分。

        if ((physaddr_t)tmp & PTE_P) {

値見てみりゃ良いのか。って見てみたらフラグ立ってないし。よく考えてみたら立ててない気がしてきました。や、そうじゃないな。
なんかもの凄いナチュラル爆発かもしれない気がしてきましたので一旦手を止めます。

なんとなく

全部 pte[PGOFF(va)] を見なければいけない気がしてきましたの巻〜