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 = (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の探索に失敗した場合は、次の処理へ進みます。

BIOS ROMのアドレス範囲を探索する

return mpsearch1(0xF0000, 0x10000);

システムベースメモリの終端から1KBの範囲にMP floating pointer structureが見つからなかった場合、mpsearch1関数を呼び出して、BIOS ROMの物理アドレス0x000F 0000 〜 0x000F FFFFの範囲でMP floating pointer structureを探索します。