5.1. main関数
ここからは各関数でAPICの設定やAPの起動等を行い、最終的にスケジューラを起動する。
main.c
extern char end[]; // first address after kernel loaded from ELF file
/* 略 */
int
main(void)
{
kinit1(end, P2V(4*1024*1024)); // phys page allocator
kvmalloc(); // kernel page table
mpinit(); // detect other processors
lapicinit(); // interrupt controller
seginit(); // segment descriptors
picinit(); // disable pic
ioapicinit(); // another interrupt controller
consoleinit(); // console hardware
uartinit(); // serial port
pinit(); // process table
tvinit(); // trap vectors
binit(); // buffer cache
fileinit(); // file table
ideinit(); // disk
startothers(); // start other processors
kinit2(P2V(4*1024*1024), P2V(PHYSTOP)); // must come after startothers()
userinit(); // first user process
mpmain(); // finish this processor's setup
}
先に各関数の概要をまとめておく。
関数名 | 概要 |
---|---|
kinit1 | 大域変数kmemのfreelistに、kernelの終わりから物理アドレス4MBまでを追加する。 |
kvmalloc | カーネル用のページディレクトリとPDE、PTEを作成して切り替える。 |
mpinit | 大域変数lapicにLAPICへのアクセスアドレスを設定、各cpu構造体にLAPIC IDを設定、大域変数ioapicidにIOAPIC IDを設定する。 |
lapicinit | LAPICを有効にし、スプリアス割り込みを無効化。APICタイマが10000000からバスクロックが進むごとにカウントダウンされ、0になるとIRQ32で割り込みをかけ、再度カウントダウンを始めるよう設定。LINT0とLINT1ピン、パフォーマンスモニタリングカウンタを無効化。割り込みエラーの際にIRQ51で割り込みかけるように設定。ESR、EOIレジスタをリセット。ICRでAPにINIT IPIを送信し、Arb IDをLAPIC IDと同じ値に設定。TPRをリセット。 |
seginit | GDTを作成し、ロードする。 |
picinit | MPに対応していない古いPICでの割り込みを無効化する。 |
ioapicinit | 大域変数ioapicにIOAPICへのアクセスアドレスを設定し、IOリダイレクションテーブルの設定を行う。IRQ0~23番がBSPにIRQ32~55番でリダイレクトされるよう設定を行い、それら全てを無効化する。 |
consoleinit | devsw配列の1番にコンソール読み書き用の関数を設定し、IOAPICのキーボードコントローラからの割込みのリダイレクトを有効化する(IRQ1からIRQ33へのリダイレクト)。 |
uartinit | UARTのFIFOを無効化し、ボーレートを9600、ワードサイズを8bitに初期化。シリアルポートが使用できるか否かを確認し、使用できる場合は「xv6...」という文字列を送信する。 |
pinit | ロセステーブルのロックを初期化する。 |
tvinit | 大域変数idtに256個のゲートディスクリプタを作成する。 |
binit | 大域変数bcache(バッファキャッシュ)を初期化する。 |
fileinit | 大域変数ftable(ファイルテーブル)のロックを初期化する。 |
ideinit | ディスク1の存在確認をする。ide.cの静的変数havedisk1に値を設定(0ならディスク1は無し、1なら有り)。 |
startothers | 各APを起動し、GDT、ページング、IDT等の設定を行い、スケジューラを実行する。mpmain関数もここで見る。 |
kinit2 | 大域変数kmemのfreelistに物理アドレス4MB(0x400000)から終わり(0xe000000)までを加え、use_lockフィールドの値を1にする。 |
userinit | initcode.Sのプロセスを作成し、プロセステーブルに追加する。 |
mpmain | APのときと同様にBSPでも「cpu0: starting 0」をコンソールに出力し、IDTを読み込み、スケジューラを実行する。 |