割り込みがうまくいかない。

キーボード割り込みのみを有効にした状態で、キーを押すと以下の画像のように

一瞬画面がおかしくなり、正常な関数が呼ばれない。

本来、呼ばれるはずの関数ではCLI命令(CPUレベルで割り込みを禁止する命令)が呼ばれるため、それ以降、割り込み自体が起こらなくなるはずなのに相変わらずキーを押すたびに画面がおかしくなるのでおそらく呼ばれるはずの関数は呼ばれていないと考えた。

f:id:m011501945:20190611024201g:plain

割り込み発生時

割り込みは、GDTとIDTの設定が間違っていなければ少なくとも割り込みベクタ番号に対応した関数は呼ばれるはずである。

そこでデバッグをした軌跡を以下に続ける。

まずqemuでGDTRレジスタとIDTRレジスタにどんなアドレスが入っているか調べた。

f:id:m011501945:20190611024959p:plain

GDTとIDTが設定されている。

GDTは0x1041a0、IDTは0x104200というアドレスが設定されていることが分かる。

まずはGDTから見てみる。

f:id:m011501945:20190611025140p:plain

GDTのアドレスからバイナリダンプ

1041a0からの8バイトはnullディスクリプタ、続いての8バイトがカーネルのコードディスクリプタ、その次の8バイトがカーネルのデータディスクリプタである。

カーネルのコードディスクリプタはベースアドレス0で大きさが0xffffである。

つまりメモリ全体をコードディスクリプタとしている。データセグメントも同様。

おかしいところは無いように思う。

4つ目は気にしないで頂きたい(デバック中の名残)

 

次はIDTを見てみる。

f:id:m011501945:20190611025735p:plain

IDTのバイナリダンプ

0x104200からIDTは始まっているが、そこは割り込みベクタ番号0から31までの設定なので気にしなくて良い。

割り込みベクタの32番の設定が104300から8バイト、33番の設定が104308から8バイトでされている。

32番はタイマ割り込み、33番がキーボード割り込みである。

今は、キーボード割り込みしか受け付けないようにしているため32番は気にしなくて良い。

セグメントセレクタは0x08、つまりカーネルのコードディスクリプタを指している。

33番の設定をみると割り込みハンドラは0x100938をコールするようになっている。

f:id:m011501945:20190611030501p:plain

0x100938の関数

上の画像はカーネルマップで見た0x100938に配置されている関数である。名前がタイマ割り込みとなっているが、実際はCLIする関数である。

本当に困った。

私の目からはちゃんと設定されているようにしか見えない・・・。

他にどのような原因があるでしょうか?

もしかしたらここが変な可能性あるとか思いついた方いましたらご教授お願いします・・・。

f:id:m011501945:20190611031449p:plain

そのほかの情報

上の画像ではちょっとGDTとIDTが変わってしまっているが多分問題ないです。

コンパイルしたらちょっと変わっただけです。

またコンパイルは-O2というオプションで最適化してコンパイルしている。

 

 

以下は使っているリンカスクリプト

SECTIONS
{
. = 0x100000;
.text :
{
_text_start = .;
*(.text)
_text_end = .;
}

.rodata :
{
_rodata_start = .;
*(.rodata)
_rodata_end = .;
}

.data :
{
_data_start = .;
*(.data)
_data_end = .;
}

.bss :
{
_bss_start = .;
*(COMMON)
*(.bss)
_bss_end = .;
}
_end = .;
}