mp.c static struct mp* mpsearch(void)
トップページ
jupiteroak.hatenablog.com
mp.c
https://github.com/mit-pdos/xv6-public/blob/master/mp.c#L48
static struct mp* mpsearch(void) { uchar *bda; uint p; struct mp *mp; bda = (uchar *) P2V(0x400); if((p = ((bda[0x0F]<<8)| bda[0x0E]) << 4)){ if((mp = mpsearch1(p, 1024))) return mp; } else { p = ((bda[0x14]<<8)|bda[0x13])*1024; if((mp = mpsearch1(p-1024, 1024))) return mp; } return mpsearch1(0xF0000, 0x10000); }
mpsearch関数は、①EBDA(Extended BIOS Data Area)の先頭から1KBの範囲、②システムベースメモリ(物理アドレス0x0000 0000 〜 0x000A 0000 あるいは 物理アドレス0x0000 0000 〜 0x0008 0000 )の終端から1KBの範囲、③BIOS ROMの物理アドレス0x000F 0000 〜 0x000F FFFFの範囲、の順でMP floating pointer structureを探索し取得します。
戻り値 struct mp* mp
MP floating pointer structureの探索に成功した場合は、MP floating pointer structureの先頭アドレスが戻り値となります。
MP floating pointer structureの探索に失敗した場合は、0が戻り値となります。
処理の内容
- BDA(BIOS Data Area)の先頭アドレスを仮想アドレスに変換する
- BDA(Extended BIOS Data Area)の先頭から1KBの範囲を探索する
- システムベースメモリの終端から1KBの範囲を探索する
- BIOS ROMのアドレス範囲を探索する
BDA(BIOS Data Area)の先頭アドレスを仮想アドレスに変換する
bda = (uchar *) P2V(0x400);
BDA(BIOS Data Area)の先頭アドレス0x400は物理アドレスです。この物理アドレスに対応している仮想アドレスを得るために、P2Vマクロを使って物理アドレス0x400を仮想アドレスbda(P2V(0x400))に変換します。この処理では、ページディレクトリ・ページテーブルの設定とページング回路の有効化が既に完了していることを前提としています。
BDA(Extended BIOS Data Area)の先頭から1KBの範囲を探索する
if((p = ((bda[0x0F]<<8)| bda[0x0E]) << 4)){ if((mp = mpsearch1(p, 1024))) return mp; }
EBDAの先頭から1KBの範囲でMP Floating Pointer Structureを探索します。
BDA(BIOS Data Area)のbda[0x0E]とbda[0x0F]のメモリ領域(2バイト)には、EBDA(Extended BIOS Data Area)のベースアドレスを4bit右シフト演算した値が格納されています。EBDA(Extended BIOS Data Area)のベースアドレスを4bit右シフト演算した値のうち、上位1バイトがbda[0x0F]に、下位1バイトがbda[0x0E]に格納されているので、EBDA(Extended BIOS Data Area)のベースアドレスを4bit右シフト演算した値は(bda[0x0F]<<8) | bda[0x0E])と表記できます。よって、EBDAのベースアドレスは(bda[0x0F]<<8)| bda[0x0E]) << 4 となります。
(p = ((bda[0x0F]<<8)| bda[0x0E]) << 4)が真となる場合→EBDAのベースアドレスが定義されていた場合は、mpsearch1関数を呼び出して、EBDAの先頭pから1KB(1024)の範囲でMP Floating Pointer Structureを探索します。
(mp = mpsearch1(p, 1024))が真となる場合→mpsearch1関数の戻り値が0ではない場合→MP Floating Pointer Structureの探索に成功した場合は、取得したMP Floating Pointer Structureの先頭アドレスmpを戻り値としてリターンします。
(mp = mpsearch1(p, 1024))が偽となる場合→mpsearch1関数の戻り値が0の場合→MP Floating Pointer Structureの探索に失敗した場合は、次の処理へ進みます。
システムベースメモリの終端から1KBの範囲を探索する
} else { p = ((bda[0x14]<<8)|bda[0x13])*1024; if((mp = mpsearch1(p-1024, 1024))) return mp; }
EBDAのベースアドレスが定義されていなかった場合は、システムベースメモリ(物理メモリ0x0000 0000 〜 0x000A 0000 あるいは 物理メモリ0x0000 0000 〜 0x0008 0000)の終端から1KBの範囲でMP Floating Pointer Structureを探索します。
BDA(BIOS Data Area)のbda[0x13]とbda[0x14]のメモリ領域(2バイト)には、システムベースメモリの終端アドレスを1KB単位で表現した値が格納されています。システムベースメモリの終端アドレスを1KB単位で表現した値のうち、上位1バイトがbda[0x14]に、下位1バイトがbda[0x13]に格納されているので、
システムベースメモリの終端アドレスを1KB単位で表現した値は(bda[0x14]<<8) | bda[0x13]) と表記できます。よって、システムベースメモリの終端アドレスは(bda[0x14]<<8) | bda[0x13])*1024 となります。
mpsearch1関数を呼び出して、システムベースメモリの終端から1KBの範囲でMP Floating Pointer Structureを探索します。
(mp = mpsearch1(p-1024, 1024))が真となる場合→mpsearch1関数の戻り値が0ではない場合→MP Floating Pointer Structureの探索に成功した場合は、MP Floating Pointer Structureの先頭アドレスmpを戻り値としてリターンします。
(mp = mpsearch1(p-1024, 1024))が偽となる場合→mpsearch1関数の戻り値が0の場合→MP Floating Pointer Structureの探索に失敗した場合は、次の処理へ進みます。