第5回 マルチプロセッサ

たまには予告どおりのテーマでやりまする。


時代はマルチコア!周波数を増大させて速度を以下略!


まず、マルチプロセッサといっても、いろいろあって、

  • ソケットが別 (Xeonとか)
  • パッケージが別 (Core2Quadとか)
  • コアが別 (Core2Duoとか)
  • スレッドが別 (Atomとか)

がありますが、忘れるなよ…ソフトウェアから見るとAPIC IDの見えかたが違うだけで以下の説明ではこれらの区別ないということを…


まず、用語として、「BSP」「AP」という用語があるなー

  • BSP : Bootstrap Processor - 最初に起動してるプロセッサ。OSの起動とかを頑張っている
  • AP : Application Processor - BSP以外のプロセッサ。BSPがOSの起動とかを頑張っているあいだぐうたらと眠っている


マルチプロセッサを使うといっても、やることはAPを起こすというだけです。起きなさい、私のかわいいAP。今日は7月4日よ。(だから何?)


起こす手順は…つっても、これ(PDF)の7.5.4.1にまんま書いてあるのだった。

簡単に書くと、

  • INIT IPI を投げる (するとAP初期化するBIOSプログラムが実行される)
  • そしたらそのままだまって10msec待つんだ
  • Startup IPI を投げる
  • APが起動!!!やったね

である。簡単ですね。


いや、簡単ではないです。IPIについて説明していない。
IPI(Inter-Processor Interrupt : プロセッサ間割り込み)とは…えーと…プロセッサ間の割り込み…としかいいようがない。

ようは、あるプロセッサが、他のプロセッサに割り込みをかけられる、と、いうものです。


あるプロセッサが、APICにある「ICRレジスタ(0xfee00300)」というレジスタに値を書くと、その時にIPIが発射されます。相手は死ぬ。いや、死にません。

で、このときに、いくつか特殊な割り込みをかけられるのですが、今回使うのは、その特殊な割り込みのうちのふたつ、「INIT IPI」と「Startup IPI」というわけですね。

詳しい解説はこれ(PDF)の「8.6.1. 割り込みコマンドレジスタ(ICR)」を読みましょう。


まず、「INIT IPI」を撃つと…えーと…何が起こるんでしょうか、よくわかりません。とりあえず撃っておきましょう。

続いて、「Startup IPI」を撃つと、APのプログラムカウンタをどこかに飛ばすことができます。どこに飛ばすかは、IPIを撃つときのICRレジスタの値の下位8bitで指定できます。(ここで指定した値) * 4096 がAPのプログラムカウンタに設定されます。


おめでとうござる!これでAPが起動しました。APは最初は16bitモードで動いてます。適切にgdtやらセグメントやらを設定してあげましょう!
これであなたもマルチコアです!マルチコアは流行りですからね!周波数を増大させて速度を以下略!

サンプルプログラム
起動して"boot_ap"と打つとAP起動できまっす。やってることは、

  • main.c:boot_ap() 上に書いてあるIPIを撃つ
  • apboot16.s: 先頭から256Kの位置に置かれる16bitプログラム。APの開始

なのであった。


おっと、そういえばどうやって10msec待つかを書いてなかった。上のサンプルではHPETを使って待ってます。HPETの解説は次回、I/O APICの使いかたとあわせて解説される予定でしょう。予定でしょう!

とりあえずここでは、ICH7を使ってれば、0xfed00000を読むとタイマの周期(14.318MHz)がとれて、0xfed00010の最下位ビットを立てればタイマ開始、0xfed000f0を読むとカウンタの値が読める、とだけ覚えておいてくれ!