2009-03-31

  • ページテーブルエントリをフリーするときにフリーリスト(kmem_free_list)のアドレスが変(0×80000000)
    • kmem_free_listはkmem_tのメンバー。
    • kmem_tはkmem_resource_tのメンバーになる(heap)。
    • kmem_free_listは0番目のメンバーで、kmem_resource_tの中のkmem_tは0番目のメンバーなので、アドレス0×80000000はkmem_resource_tのアドレスになる。
    • つまり、kmem_resource_tの配置がおかしいことになる。
    • kmem_resource_tはget_current_kmem_resource()で取得する。
  • free_utcb_area_memory()がフリーリストを書き換えてしまう。
  • utcbのアドレスに対応するpgentの持つ物理アドレス(utcbの物理アドレス)が0になっている。これが原因でfree_utcb_area_memoryがおかしな挙動をする。原因はUTCBのアロケーションの失敗か?
  • 結局のところ、ページテーブルエントリの有効・無効の判断の仕方に間違いがあったということが分かった。疑わしきは自分の書いたコードである。Rev.92

2009-03-30

  • SpaceControlがちゃんと動かない。

2009-03-27

  • トラップハンドラの見直し終わり。ユーザーコンテキストをTCBに保存するようにした。Rev.83
    • KDBが使えるようになった。
  • Hello, world! Rev.85
  • KTESTを走らせてみる。SPACE_CONTROLでこける。コンティニュエーションのアドレスがおかしい。

2009-03-26

  • トラップハンドラを見直し中。コンテキストの退避と復帰、再突入の考慮など。
  • メモ
    • ユーザーモードからカーネルモードに入る(システムコール、例外、割り込み)
      • ユーザーコンテキストをユーザースタックに退避
      • カーネルスタックに切り替え
      • システムコール、例外、割り込みの処理
      • カーネルの特定の場所でプリエンプション可能になる
      • 例外、割り込みの発生
      • カーネルコンテキストは破棄する
      • カーネルスタックをリセット
      • 例外、割り込みの処理
      • 終了後、コンティニュエーションを実行。TCBからレジスタを復帰。スタックはリセット。
      • 終了後、コンティニュエーションを実行。TCBからレジスタを復帰

2009-03-25

  • ユーザープログラムがこけるのも当たり前、ルートタスク用のcrt0がちゃんと実装されていなかった。
  • おそらくHelloWorldは実行されているが、メッセージが表示されない。シリアルドライバが不完全か?
    • KDBコール(システムコールの一種)がおかしいので、シリアルドライバをデバッグできない。まずはKDBコールを直さなければ。
      • 一般例外ハンドラの配置が違ってたので修正。
      • KDBコールは正しいようだ。
      • 部分的に未実装なので、実装を完璧にする必要がある。
  • read_write_lockのアサーションに引っかかる。一時的なエラーだったみたい。
  • ユーザーレベルのシリアルデバイスドライバがおかしい。

2009-03-24

  • EXPEVTが0の問題は、とりあえず、0を読み込み例外(本来は0×40)と判断することにした。
  • ElfWeaverのスタックポインタの計算が間違っている?
DEFAULT_STACK_SIZE = 0x1000

def get_sp():
    virt_addr = self.stack.virt_addr
    size = self.stack.size
    return virt_addr + size

となっているけど、これではスタックポインタが次のページに行ってしまう。

def get_sp():
    virt_addr = self.stack.virt_addr
    size = self.stack.size - 4
    return virt_addr + size

とすべきだろう。

  • pgent_t::is_readableの判定が間違っていたので修正。
  • 正体不明のページフォルト(0×00117550)が発生する。
    • 正体不明ではなく、期待通りのページフォルト。しかし、カーネルが正しく処理できていない。
    • make_subtreeで64kページを考慮していないのが原因だった。修正。
  • ユーザーコンテキストが元に戻らない。例外発生前のコンテキストが例外処理後に復元されない。
    • tcb_tの中のktcb_tにユーザーコンテキストを保存。回復にはexception_returnを新たに実装。
    • 8ビットイミディエイトの加算演算にはまる。結果が8ビットを越えてもキャリーしない。つまり、
      • 0×88301C60 + 0xA4 = 0×88301C04となる。
      • 上記の式の正しい答えは0×88301D04
    • この様な場合にはイミディエイトではなくレジスタに一旦値をロードして計算する。
  • ユーザープログラムがアサートでこける。OKL4_ENV_HEAER_MAGICが取れていない。

2009-03-23

  • TCBは空っぽではなかった。しかし、PCが指すアドレス(0×100000)には何も配置されていない。
      HelloWorldが期待通りにマッピングされていないのが原因のようだ。map_regionを見直す。
  • TLBミスハンドラがオフセット0×400にない!
  • クラッシュの原因はTLBミスハンドラにあるようだ。
    • TLBミスハンドラの冒頭でユーザーコンテキストをユーザースタックに退避する。しかしながら、ユーザースタックはTLBにエントリがない。これが原因でダブルフォルトが発生し、カーネルがリセットされる。
    • generic_space_t::activate内でユーザースタックをTLBエントリに追加した。
  • TLBミスハンドラで例外コードがとれない。EXPEVTを読み込むと値が0。

2009-03-19

  • ページマッピングがうまくいかない。カーネルモードでP0領域にアクセスしようとしてこける。UTLBはちゃんとセットしているんだが。。。
    • 読み込みは成功しているようだが、書き込みはダメだ。
    • ライトバックのページを複数箇所にマッピングする時はキャッシュをフラッシュする必要がある。
    • 下記のページテーブルの構成に付随した問題だった。ページサイズを直接指定することで取り合えず解決。
  • ページテーブルの構成はTODO
    • add_mappingで指定したページサイズとlookup_mappingで取れるページサイズが違う。ページテーブルの構成がコアの実装と合っていないようだ。
    • 直した。
  • initial_to_userでTCBが空っぽ。なのでリセットされてしまう。TCBをどこかでセットアップしているはずなんだが…

2009-03-18

  • ページマッピングでパニック。ページサイズが0になっている。アドレスが0×117400となっており、1kアラインである。これはおかしい。設定ファイル(machines.py)で1kページを許可しないようにしたら直った。本質的な解決ではないかもしれない。
  • パニックするようなエラーはでなくなった。ちゃんと動いている?HelloWorldが使うシリアルポートドライバがまだ出来ていないので確認できない。
  • シリアルポートデバイスドライバを実装。でもメッセージは出ない。どこかでハングしているようだ。
    • それもそのはず。switch_toが未実装でコンテキストスイッチが起きていなかった。
  • switch_to実装も新たなバグ。UTCBの実装を見直さなければならない。

2009-03-17

  • キャッシュのコードを修正。オペランドキャッシュのフラッシュのためにVIRT_RAM_BASE(0×88210000)を使っていたのだが、実はこの アドレスにはグローバル変数が格納されおり、このグローバル変数の変更がライトバックされていない状態でキャッシュをフラッシュしようとすると、今のアル ゴリズムではグローバル変数が破壊されてしまう。VIRT_RAM_BASEを止めて、KERNEL_AREA_START(0×80000000)に変 更。
    • 0×88000000とすべきか?
  • トレースを表示するように変更。コマンドラインで指定する方法を探すのに手間取った。カーネルソースでは、VERBOSE_INITというディレクティブ でトレースの表示をコントロールしている。これを単にコマンドラインでVERBOSE_INIT=trueとすれば、トレースの表示が有効になる。他の ディレクティブも同様と思われる。
  • small_alloc_t::allocateのメモリテストでエラー。check_poisoned_areaで引っかかる。メモリが汚染されているらしい。
    • 他の誰かが使っている
    • オーバーフロー
    • キャッシュ操作の間違い
void *
small_alloc_t::allocate(bool zeroed)
{
    ...
    if (!first_free) {
        /* ここでは4Kのブロックを確保 */
        first_free = allocate_block(mem_group);
        if (!first_free) {
            return NULL;
        }
        /* 確保したブロックを汚染しておく */
        poison_area(get_object(first_free, 0), objs_per_block * obj_size, KMEM_POISON_FREE);
    }

    /* ファーストフィットでフリーブロックを確保 */
    int position = bitmap_findfirstset(first_free->get_bitmap(), objs_per_block);
    void* object = get_object(first_free, position);
    bitmap_clear(first_free->get_bitmap(), position);

    /* 現在のブロックがすべて使われているならば、first_freeをアップデート */
    while (bitmap_findfirstset(first_free->get_bitmap(), objs_per_block) == -1) {
        first_free = first_free->next;
        if (!first_free) {
            break;
        }
    }
    num++;

    check_poisoned_area(object, obj_size, KMEM_POISON_FREE, object);
    ...
}
void
poison_area(void* addr, word_t size, unsigned char poison_value)
{
    memset(addr, poison_value, size);
}
void
check_poisoned_area(void* addr, word_t size, unsigned char poison_value, void* obj_addr)
{
    unsigned char* p = (unsigned char*)addr;
    while (size--) {
        if (*p != poison_value) {
            enter_kdebug("poison");
        }
        ++p;
    }
}
  • 原因はmsbを実装していないことにあった。
  • l1_entry_tとl2_entry_tのサイズがおかしくなっていたせいで、メモリアロケーションがおかしなことになっていた。
    • l1_entry_tとl2_entry_tは4バイトでなければならないのだが、ビット指定を間違えていて33ビットのデータ構造になってしまっていた。

2009-03-16:カーネルが動き始める

  • MMUCRなどを更新した際に、任意のアドレスでICBIを発行するのだが、その任意のアドレスを0×1000とするとクラッシュする。
    • 0×80000000として回避した。
  • 最初のカーネルメッセージが表示された!
  OKL4 - (provider: Open Kernel Labs) built on Mar 16 2009 14:50:15 using gcc version 3.4.5.
  • run_init_scriptでこける
    • phys_to_virtのバグ。Machine.pyを修正。
    • Elf Weaverが物理アドレスでinit scriptを書き込んでいる一方で、カーネルは仮想アドレスでそのスクリプトをロードする。

2009-03-13

  • いよいよ実機で走らせつつ、デバッグを開始する。
    • まずはデバッガ用のウィンドウズのインストールから。

2009-03-12:ビルドが通るようになる

  • ldスクリプトのしょうもないバグを修正。ビルドが大分進む用になった。
  • crt0_rootserver.sppを実装したら、ビルドが通った

2009-03-11

  • とりあえずカーネル内の空の関数は実装した。
  • ライブラリの実装に取りかかる。
    • KDBインターフェースのテンプレートを作成
    • 実装完了か?
  • シリアルデバイスドライバがないのでビルドが停止する。

2009-03-10

  • トラップハンドラ実装の続き。
  • 例外ハンドラの実装。
  • KDBインターフェースを実装しなければならない。lib/l4/include/syscall_asm.hにKDB用のシステムコール番号だけは予約した。

2009-03-09

  • トラップハンドラを大幅に変更。例外コードをオフセットにして各ベクタに飛ぶようにした。
  • コンティニュエーションの仕組みと役割を理解した。

2009-03-06

  • レジスタのネーミングを仕様書どおりにする。いままでは可読性を高めようと独自に名前を変更していたが、かえって仕様書との読み替えが面倒になるのではないかと考えた。その代わり、コメントで可読性を補うことにする。

2009-03-05

  • 割り込みがいやらしい。L4ではSHでいうところの外部割り込みしか想定していないようだ。内部割り込みもユーザ側に投げる必要があると思うので、その場 合、内部・外部割り込みを一つの空間で管理しなければならないが、各割り込みは必ずしも連番になっていない。一方でL4内部では配列で割り込みの管理をし ている。割り込みの番号空間を連番空間にマッピングする関数が必要なのだが。。。
  • 結局、虫食いになってもいいから、大きめの配列を用意することにした。将来的に今穴の開いている割り込み番号に何かが加わるかもしれないし。

Post a Comment

*
*