FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

xv6の割り込みに必要な機能を実装する

xv6のデバッグを進めるためにGDBの整備は進んだのだが、ディスクアクセスなどの機能がまだサポートできていない。 また、重要な問題として、割り込みの機能を実装ができていないのだ。ディスクアクセスについて、ディスクからの読み込みが完了すると割り込みが発生する仕組みになっているのだが、その機能は実装できていない。

xv6の教科書にも、ディスクの読み込みの完了を通知するために割り込みが必要になる。

https://pdos.csail.mit.edu/6.828/2012/xv6/book-rev7.pdf

Eventually, the disk will finish its operation and trigger an interrupt. trap will call ideintr to handle it (3374).

この機能を実装するためには、どのようにしたら良いのだろう?

MIPS側の割り込みベクタの仕組み

MIPS側は、割り込みが入ると、以下のようなテーブルに従ってPCが変化する。

f:id:msyksphinz:20160207212940p:plain

f:id:msyksphinz:20160207213114p:plain

今回はここまでは実装しないが、とりあえず割り込み要求が入るとPCが割り込み要求に飛ぶようにしない。

github.com

まずは、IDEモジュールにイベントハンドラを追加し、特定の条件が一致すると、割り込み要求を発生させる。

void ModuleIde::EventHandler ()
{
    int32_t curr_timer = GetTimer ();
    if (curr_timer != 0) {
        m_env->InfoPrint ("EventTrigger ModuleIDE %d\n", curr_timer);
        SetTimer (curr_timer - 1);
        if (curr_timer == 1) {
            m_env->RequestInterrupt ();
        }
    }
}

Env側で割り込み要求のメンバ変数が上がっていると、それに応じてフェッチするPCを変える。とりあえずこれだけの実装だ。

ExecStatus MipsEnv::StepExec (bool is_resume_break)
{
...
    if (IsInterruptRequested ()) {
        ClearInterruptRequest ();
        InfoPrint ("<Interrupt is cleared>\n");
        SetPC (0x1fc00200);   // Interrupt Vector
    }
...
}

これで、とりあえずIDEから割り込みが入るようになった。ただし、IDE側でちゃんとしたプロトコルで動かしていないので、xv6が暴走するようになってしまった。 ここは修正する。