30日OS自作本6日目
6日目は割り込みハンドラの実装&呼び出しを行った。
GDTの仕組み
GDTRという48ビットのレジスタにGDTを配置した番地(開始地点)とリミット(開始地点からどこまでGDTか)を書き込む
- GDTRの最初の2バイトはリミットを表す
- 残りの4バイトでGDTが置いてある番地を表す
0xFFFF00002700
で0x270000~0x27ffff
までGDTとして扱うという意味なる。- GDT自体のサイズは8バイトであるからこの場合GDTは8192個設定可能となる。
構造体の解説
struct SEGMENT_DESCRIPTOR { short limit_low, base_low; char base_mid, access_right; char limit_high, base_high; };
上記の構造体の説明。文章だけだとこんがらがったので画像に起こして理解した。画像とコードの対応がちょっとおかしいが、C言語は4bit長の変数がないらしく、limit_highの上位4bitにセグメント属性を書き込むようになっている。最終的にGDTに書き込む長さとしてはlimit_highは実質4bit,access_rightは実質12bitとなっている。
構造体上での表現 63 55 47 39 31 23 15 7 0 +--------+--------+--------+--------+--------+--------+--------+--------+ |base_hi |limit_hi| ar |base_mid| base_low | limit_low | +--------+--------+--------+--------+--------+--------+--------+--------+ CPUの仕様上のデスクリプタ ※limit_highの上位4bitはアクセス属性の続きになります。だから実際はCPUは上の構造体を以下の形式で扱います。 63 55 47 39 31 23 15 7 0 +--------+----+----+--------+--------+--------+--------+--------+--------+ |base_hi |ar |l_hi| ar |base_mid| base_low | limit_low | +--------+----+----+--------+--------+--------+--------+--------+--------+ ※入りきらない変数名は省略しています
アクセス権の設定値
arの中身です。
設定値 | hex | 意味 |
---|---|---|
00000000 | 0x00 | GDTが未使用であることを示す |
10010010 | 0x92 | システム専用readのみ。実行不可 |
10011010 | 0x9a | システム専用read可能&実行可能 |
11110010 | 0xf2 | アプリケーション用readのみ。実行不可 |
11111010 | 0xfa | アプリケーション用read可能&実行可能 |
セキュリティ
CPUにはアプリケーションモードとシステムモードがある。
- アプリケーションモードの時にLGDTの実行を制限(監視)する
- アプリケーションモードの時にシステム専用のセグメントの読み書きを制限(監視)する
実行中のプログラムが0x9a,0xfaどちらのセグメントに配置されているかでモードの判別を行う。 アプリケーションモード時にLGDTの実行を制限しているのはGDTの再設定ができてしまうから。*1
割り込み
割り込みにはGDTとIDTの初期化に加えて、PICの初期化が必要
PICとは?
programmable intrrupt controllerの略
CPUは単独では一つしか割り込みを扱えない。 複数(8個)の割り込みを一つの割り込み信号にまとめる装置がPIC
割り込み信号をIRQといい0~8の数字が振られPICの各ピンに対応している
本中のPICは2連結(マスター:スレーブ)になっているらしく、15個のIRQが扱える*2
- マウス:IRQ12
- キーボード:IRQ1
はここに記載があるものと一緒。何かの標準規格?
http://d.hatena.ne.jp/wocota/20090302/1235985661
ハードウェア的にはIntel8259と呼ばれるものと同一?
PICの接続をマスターの2番ピンにさしてるのはIBMのおじさんが決めた、的な下りがあるけど、 IBMのおじさんが決めた規格があってInterl人もそれに添って決めているということなのかな。
PICのレジスタ
全て8bit
- IMR:innterrupt mask register
- 1が立っている位置に対応しているIRQの割り込みを無視する。
- ICW:1~4の合計4バイトがあるが何に使っているかよくわからない。プログラムの設定値以外は設定できないらしい。
- ICW3:スレーブが刺さってるマスタのピンを登録。つまり
0b00000100
で固定。- 下位ビットからpin 0,pin 1,pin 2,...という対応だと思う。
- 他の値は設定できない。
- ICW2:IRQ0~15をINTのどれで受け取るかを指定。以下に設定例を示す
- ICW3:スレーブが刺さってるマスタのピンを登録。つまり
io_out8(PIC0_ICW2, 0x20 ); /* IRQ0-7は、INT20-27で受ける */ io_out8(PIC1_ICW2, 0x28 ); /* IRQ8-15は、INT28-2fで受ける */
割り込みの設定
キーボード(IRQ1)の例
- IDTに0x21bの割り込みの祭に呼び出す関数
_asm_inthandler21
(アセンブリ)を設定 _asm_inthandler21
からC言語の関数inthandler21
を呼び出す- キーボードが押された際に画面に出力