読者です 読者をやめる 読者になる 読者になる

MP Configuration table Headerの仕組み

x86

前回はMP Floating Pointer Structureを見て、その中にMP Configuration table Headerへのアドレスが入っていることを書いたので、
今回はMP Configuration table Headerを見ていく。見るといっても内容をすべて見るというよりは、minix2smp実装を理解するために必要な部分だけですが。

minix2smpのソースはここ。
http://gsd.unex.es/projects/minixsmp/


MP Configuration table Headerとは何かというと、「MP Configuration tableのヘッダです」というそのままな説明なんですがw
それだとアレなので、MP Configuration tableは何かっていうと、
これは1種類のテーブルではなく5種類あって、ENTRY TYPEと呼ばれる種別ごとにテーブルの構造が違うけど、
総称してMP Configuration tableと呼んでいるようです。

MPの仕様書で定義されているENTRY TYPEは5種類あり、名称と番号の関係は下のような感じです。

Entry Description         Entry Type Code
Processor                     0
Bus                           1
I/O APIC                      2
I/O Interrupt Assignment      3
Local Interrupt Assignment    4

個別の内容は今度見るとして、今日はMP Configuration table Headerを見ていくお。

前述したようにMP Configuration table HeaderはMP Configuration tableのヘッダなので、
MP Configuration tableの内容を見ていくために必要な情報等も入っています。

minix2smpの実装では、下のような構造体で表現してます。

/* Describes the estruct of MP configuration table header */
struct mp_config_header {
   char  mpch_signature[4];        /* must be "PCMP" */
   u16_t mpch_length;              /* base table size including header */
   u8_t  mpch_version;             /* MP specification version number*/
   u8_t  mpch_checksum;            /* base table + checksum must sum 0 */
   char  mpch_oem_id[8];           /* manufacturer id (space filled) */
   char  mpch_product_id[12];      /* product id (space filled) */
   u32_t mpch_oem_table;           /* optional manufacturer table address */
   u16_t mpch_oem_table_size;      /* manufacturer table size */
   u16_t mpch_entry_count;         /* entry count in MP table */
   u32_t mpch_apic_addr;           /* IO address for local APIC */
   u16_t mpch_extended_length;     /* extended table length */
   u8_t  mpch_extended_checksum;   /* extended table checksum */
   char  mpch_reserved;            /* unused */
};

フィールドは色々あるんですが、mpch_signature、mpch_lengthは読み込んだMP Configuration table Headerの正当性を検証するのに使います。
前回も書いたけど、検証方法はシグネチャ&&チェックサム方式です。
シグネチャはmpch_signatureの値を調べます。コメントにも書いてあるけど、MP Configuration table Headerのシグネチャは「PCMP」なので、mpch_signatureが"PCMP"でない場合は、何かが間違ってます。

そして、チェックサムの計算ですが、MP Floating Pointer Structureの場合はテーブルのサイズ分、1バイトずつ計算してったのですが、
今度はmpch_lengthで指定されたバイト数分、1バイトずつ計算していきます。

コードだとこんな感じになってます。

int test_mptable_checksum(void) {
/* Cheks a MP table header structure for a valid signature and checksum. 
   Return noncero on success */

   unsigned char data, checksum;
   int i;

   /* first match the signature */
   for (i=0; i<4; i++) 
      if (mph.mpch_signature[i] != SIGN_MP_C_HEADER[i] )
         return 0;

最初は、シグネチャのチェック。

   /* then calculate checksum */
   checksum=0;
   for (i=0; i<mph.mpch_length; i++) {
      /* the complete table is in another segment, so we need copy 
         each byte into kernel address space (mph is only the header) */
      phys_copy(fps.fp_mp_table+i, vir2phys(&data), 1);
      checksum +=data;
   }
   return (!checksum);  /* checksum ok if sums 0 */
}

コメントに「セグメントが違うから、正しいアドレスからデータを引っ張るよ」的なことが書かれていますが、
結局は足し算していって結果が0ならチェックサムは問題ないということになります。

次に、mpch_lengthで示されたバイト数分のループで計算していきます。

この後、MP Configuration tableを読みにいくわけなんですが、実装の話はすでに書いたので、そちらを見てみてくださいな。

今度は、各MP Configuration tableの内容を見ていく予定なんですが、
実装上だと、これらの中身を使って何かをしている様子が見えないので、実はそんなに細かいことを調べなくても良い希ガス