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ヘッダーの先頭アドレスを取得する
- MP configuration tableヘッダーの先頭アドレスを仮想アドレスに変換する
- MP configuration tableのシグネチャを確認する
- MP configuration tableのバージョンを確認する
- MP configuration tableのチェックサムを確認する
- 参照渡しされたmp構造へのポインタにMP floating pointer structureの先頭アドレスを格納する
- MP configuration tableヘッダーの先頭アドレスを戻り値としてリターンする
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ヘッダーの先頭アドレスを戻り値としてリターンします。