mp.c static struct mpconf* mpconfig(struct mp **pmp)

トップページ
jupiteroak.hatenablog.com


mp.c
https://github.com/mit-pdos/xv6-public/blob/master/mp.c#L72

static struct mpconf* mpconfig(struct mp **pmp)
{
  struct mpconf *conf;
  struct mp *mp;

  if((mp = mpsearch()) == 0 || mp->physaddr == 0)
    return 0;
  conf = (struct mpconf*) P2V((uint) mp->physaddr);
  if(memcmp(conf, "PCMP", 4) != 0)
    return 0;
  if(conf->version != 1 && conf->version != 4)
    return 0;
  if(sum((uchar*)conf, conf->length) != 0)
    return 0;
  *pmp = mp;
  return conf;
}

mpconfig関数は、MP floating pointer structureとMP configuration tableのヘッダーを取得します。

引数 struct mp **pmp
mp構造体(MP floating pointer structureを表現したデータ構造)へのポインタを指定するアドレスです。
mpconfig関数の処理が正常に終了した場合は、アドレスが指定するポインタにMP floating pointer structureの先頭アドレスが格納されます。

戻り値 struct mpconf *conf または 0
MP configuration tableのヘッダーを取得できた場合は、MP configuration tableのヘッダーの先頭アドレスが戻り値となります。
MP configuration tableのヘッダーを取得できなかった場合は、0が戻り値となります。

処理の内容

MP floating pointer structureからMP configuration tableヘッダーの先頭アドレスを取得する

if((mp = mpsearch()) == 0 || mp->physaddr == 0)
    return 0;

mpsearch関数を呼び出して、MP floating pointer structureの先頭アドレスを取得し、MP floating pointer structureからMP configuration tableヘッダーの先頭アドレスmp->physaddrを取得します。
(mp = mpsearch()) == 0が真となる場合→mpsearch関数の戻り値が0の場合→MP floating pointer structureの取得に失敗した場合、または、mp->physaddr == 0が真となる場合→mp->physaddrが0の場合→MP configuration tableが定義されていない場合は、0を戻り値として処理を終了します。

MP configuration tableヘッダーの先頭アドレスを仮想アドレスに変換する

conf = (struct mpconf*) P2V((uint) mp->physaddr);

MP configuration tableヘッダーの先頭アドレスmp->physaddrは物理アドレスになっています。この物理アドレスに対応している仮想アドレスを得るために、P2Vマクロを使って物理アドレスmp->physaddrを仮想アドレスconf(P2V((uint) mp->physaddr))に変換します。この処理では、ページディレクトリ・ページテーブルの設定とページング回路の有効化が既に完了していることを前提としています。

MP configuration tableのシグネチャを確認する

 if(memcmp(conf, "PCMP", 4) != 0)
    return 0;

memcmp関数を呼び出して、MP configuration tableヘッダーの先頭4バイトのメモリ領域に"PCMP"(MP configuration tableであることを示すシグネチャ)が格納されているかを調べます。
memcmp(conf, "PCMP", 4) != 0 が真となる場合→memcmp関数の戻り値が0ではない場合→"PCMP"が格納されていなかった場合は、0を戻り値として処理を終了します。

MP configuration tableのバージョンを確認する

 if(conf->version != 1 && conf->version != 4)
    return 0;

conf->version(MP configuration tableヘッダーのSPEC_REVフィールド)には、MP specificationのバージョンを示す値が格納されています。
conf->versionの値が1の時はMP specificationのバージョンが1.1、conf->versionの値が4の時はMP specificationのバージョンが1.4となります。
MP specificationのバージョンが1.1と1.4以外の場合は、0を戻り値として処理を終了します。

MP configuration tableのチェックサムを確認する

  if(sum((uchar*)conf, conf->length) != 0)
    return 0;

MP configuration tableのチェックサムを確認を確認します。
sum関数は、先頭アドレスがconf・サイズがonf->lengthのメモリ領域において、各メモリ(1バイト)に格納されている値の和を求めます。
アドレスconfがMP configuration tableヘッダーの先頭アドレスである場合、sum関数の戻り値は0となります。
チェックサムの値はMP configuration tableヘッダーの各フィールドとBase Configuration Tableの各フィールドの合計値が0になるように設定されています(conf->lengthは、Configuration TableヘッダーのBASE TABLE LENGTHフィールドの値で、base section(MP configuration tableヘッダー、Base Configuration Table)のサイズをバイト単位で示しています)。
sum((uchar*)conf, conf->length) != 0が真となる場合→sum関数の戻り値が0ではない場合→アドレスconfがMP configuration tableヘッダーの先頭アドレスとみなされなかった場合は、0を戻り値として処理を終了します。

参照渡しされたmp構造へのポインタにMP floating pointer structureの先頭アドレスを格納する

*pmp = mp;

mp構造へのポインタ*pmpに、MP floating pointer structureの先頭アドレスmpを格納します。

MP configuration tableヘッダーの先頭アドレスを戻り値としてリターンする

return conf;

MP configuration tableヘッダーの先頭アドレスを戻り値としてリターンします。