Linuxのカーネルの初期化ルーチン

Linuxは、ブートイメージの初期化ルーチンから制御を受け取った直後に、アーキテクチャ特有の初期化処理やディバイス情報の取得、またC言語で記述されたLinuxカーネルの動作を可能とするためのメカニズムの構築を行う。
これらは、処理こそカーネル側についているが、目的から、カーネルの起動処理へ含め難い。

そこで、この処理はカーネルの起動とは独立させ、別途解説することとした。

処理の流れ

カーネルが制御を受け取る際、入口としては2箇所ある。
これらのインタフェースは、arch/x86/boot/compressed/以下に配置されたヘッダファイル(head_32.S/head_64.S)に記述されている。(※2.6.31の時点では)

これらには、startup_32、startup_64の2つのインタフェースが存在し、32ビット版か64ビット版かで呼び出し先を変える。

これらstartupと呼ばれるインタフェースは、メモリ上のアドレス0x100000へ配置される。これはブートイメージの初期化ルーチンと同じ位置であるが、カーネルイメージの解凍&展開処理を行った際に再配置が行われたため、呼び出しは正常に行われる。

カーネルは初期化を行っていないため、カーネルのサービスを提供できない。
つまり、プログラム内でアドレスの解決を行う際に、ページングが機能していないため、ベースアドレスが算出できない。

初期化ルーチンの初期においては、アドレス0x100000にstartupを固定で配置することにより、これを解決している。__PAGE_OFFSETで定義された値を利用することで、泥臭い方法を用いて対処している。

しかしながら、これを永久に続けていては問題も多い。そのため、すぐさまアドレス0x100000はページングされているように設定し、その後の処理が0x100000上に配置されたページ上で動作しているかのように振舞わせる。
勿論、ページング自体はしばらくあとの処理で初期化が行われるが、暫定としてこのように処理する。

次に、再びブートイメージの初期化ルーチンにもあった同様の問題に対処する。
C言語による記述を可能とするための、メモリ初期化だ。

関数の実装を可能とするためスタック領域の作成し、また静的変数・大域領域の実装を可能とするためのBSS領域の設定を行う。

次に、割り込みディスクリプタの再定義を行う。
x86のリアルモードの割り込みは、H8マイコンのように常時同一のハードウェアスタックとジャンプ先(割り込みベクタ)へ制御を投げる。したがって、これらのハードウェア上で動作するオペレーティングシステムが初めに行う処理は、割り込み禁止処理とハードウェアスタックの初期化であるのが定石である。

しかし、プロテクションモードで動作するx86の場合、割り込み発生時に制御が投げられる先は、IDT(Interrupt Descriptor Table)上で定義されたアドレスとなるため、柔軟な設定が行える。したがって、割り込み禁止を行う代わりに、head_xx.S上で定義されたignore_int(何もしない処理)へ制御を投げるようIDTを設定し、割り込み発生時に何の処理も行わないというアプローチをとっている。

次に、0x90000上に格納された、ブートイメージでの初期化ルーチン等が取得した情報をカーネル側に吸い上げる処理を行う。また同時に、CPU情報の取得やセグメントの再定義を行う。

その後、カーネルの起動処理へ制御を渡す。


構築・インストール

(後日掲載)


設定・調整

(後日掲載)

  • 最終更新:2009-12-20 00:57:22

このWIKIを編集するにはパスワード入力が必要です

認証パスワード