OSを自作してみる5 ~IDT/PICの初期化~



前回の記事ではGDTの初期化を行ったが、まだIDTの初期化を行っていなかったのでこの記事で行うことにする。

※過去回の記事とソースコードは下記から入手できる
https://github.com/Shadow5523/osdev/blob/master/README.md
また、ここで使用するコードはGitHubからダウンロードできる。
https://github.com/Shadow5523/osdev/releases/tag/version0.4.0

目次

 
 

概要

まずIDTとは”割り込み記述子管理表”と呼ばれ、割り込みと呼ばれる信号と割り込み時に実行したい処理(ハンドラとかいう)とを結びつけるための48ビットのテーブルの事である。
キーボードなどのボタンを押したりするとまず’PIC’呼ばれるものへ割り込み信号が行き、PICは割り込み信号 + INT命令をCPUへ送る。するとCPUはIDTを参照しPICから送られてきた割り込み信号の値と実行すべき処理の対応付けを確認し対応付けられた処理を実行する。PICは割り込みに優先度をつけ同時に2つの割り込みなどが入った場合にはまず優先度の高い方から割り込み順番にをCPUへ送る役割などもある。

IDTによる割り込み処理を行うにはこのPICの初期化も必要になり今回の記事ではこれも行っていく。

 
 

IDT作製

1.IDTを定義するヘッダファイルを作成。
//idt.h

 

2.IDTテーブルを初期化しlidt命令を呼び出す。lidt命令はアセンブラからしか呼び出せないので別途作成する。
//idt.c

 
 
set_gate_descの引数は以下の通り

  • index : 割り込みのベクタ番号を指定(下記表を参照)
  • offset : 割り込みで呼びたいハンドラ(まぁ関数など)のアドレスを指定
  • selector : ゲートタイプを指定(基本的には32bitコードセグメントである0x08を指定)
  • ar : ゲートタイプを指定(下記表を参照)
  •  
    Exception/IRQベクタ番号

    ベクタ番号 タイプ Exception名/IRQ名
    0 Exceptions(Fault) ゼロ除算エラー
    1 Exceptions(Fault/Trap) デバッグ
    2 Exceptions(Interrupt) ノンマスカブル割り込み
    3 Exceptions(Trap) ブレークポイント
    4 Exceptions(Trap) オーバフロー
    5 Exceptions(Fault) 範囲超過の例外
    6 Exceptions(Fault) 無効なオペコード違反
    7 Exceptions(Fault) デバイスが利用できない
    8 Exceptions(Abort) ダブルフォルトの例外
    9 Exceptions(Fault) コプロセッサ セグメント超過
    10 Exceptions(Fault) 無効なTSS違反
    11 Exceptions(Fault) セグメントが存在しない
    12 Exceptions(Fault) スタックセグメント違反
    13 Exceptions(Fault) 一般保護違反
    14 Exceptions(Fault) ページ違反
    15 予約
    16 Exceptions(Fault) x87 浮動小数点例外
    17 Exceptions(Fault) アライメントチェック違反
    18 Exceptions(Abort) マシンチェック違反
    19 Exceptions(Fault) SIMD 浮動小数点例外
    20 Exceptions(Fault) 仮想化例外
    21 – 29 予約
    30 セキュリティ違反
    31 予約
    32 IRQ0 タイマ割り込み
    33 IRQ1 キーボードコントローラ割り込み
    34 IRQ2 Slave PICからの割り込み
    35 IRQ3 シリアルポートからの割り込み(COM2)
    36 IRQ4 シリアルポートからの割り込み(COM1)
    37 IRQ5 LPTからの割り込み(2)
    38 IRQ6 FDDコントローラからの割り込み
    39 IRQ7 LPTからの割り込み(1)
    40 IRQ8 CMOS リアルタイムクロックからの割り込み
    41 IRQ9 レガシーSCSI/NIC/その他周辺機器の割り込み
    42 IRQ10 SCSI/NIC/その他周辺機器の割り込み
    43 IRQ11 SCSI/NIC/その他周辺機器の割り込み
    44 IRQ12 PS/2マウスからの割り込み
    45 IRQ13 FPU/Coprocessor/Inter-processorなどからの割り込み
    46 IRQ14 プライマリATA HDDからの割り込み
    47 IRQ15 セカンダリATA HDDからの割り込み


     
    ゲートタイプ

    0x8e 32ビット interrupt gate. 通常はこちらを使う。IRQで使用する。
    0x8f 32ビット trap gate. interruput gateとの違いはIFフラグをセットしない事。Exceptionsで使用する。
    0x85 task gate. ダブルフォルトの例外が発生したときのみ使用する。


     
     
     
     
    3.lidt命令を使ってIDTのサイズをIDTRへ格納。この辺はまではGDTの初期化と同じ。
    //idt.s

     
     

    PIC初期化

    4.次にPICの初期化を行っていく。PICはマスタ/スレーブの2台構成(1つはCPU内部にもう一つはマザーボードに)となっておりそれぞれを初期化していく。またPICへ送るポートアドレスやパラメータはぱっと見じゃなんなのかわかりづらいしとても多いのでここで#defineマクロを使用してわかりやすい文字列と対応付けさせる。対応付けのヘッダは以下の通り。
    //pic.h

     

    5.ここでPICの初期化を行う。
    //pic.c

     

    6.カーネルのヘッダファイルにidt.hとpic.hをインクルードさせるコードを追加する。
    //kernel.h

     
     

    kernel側で呼び出し/Makefile編集

    7.カーネル本体へpic、idtを初期化する関数を呼び出すコードを記述する。
    //kernel.c

     
     
    8.Makefileに今回あらたに追加したソースもビルドできるように追加する。
    //Makefile

     
     

    確認

    9.あとはmakeコマンドで無事ビルドが通ればOK。実行しても前回同変化はなしです。。。

    次回割り込み経由でのキー入力を行っていく。

    Leave a Reply

    Your email address will not be published. Required fields are marked *