[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: reboot without WinCE



カーネルが収まる程の領域を連続でとれる可能性は期待できないと思います。
(カーネルに RAM disk image が入っていると 8MB とかになるし)

 > こばやしです
 > 
 >  >uvm_pglistallocを使って、新しいカーネルを格納するのに十分な(2,3MBぐらい?)
 >  >連続な物理メモリを確保しようとしたのですが、500KB近くなるとuvm_pglistalloc
 >  >が返ってこなくなります。ENOMEMで返ってくるならまだわかるのですが...
 > 
 > 引数におかしな数値がはいっていたのが原因でした。直したところ、確保できる限界
 > が増え、足りないときもすぐENOMEMで返ってくるようになりました。ただ、それでも
 > 連続な領域として確保できるのは2MB弱が限界みたいです。(32MBのマシンでboot直後)
 > このままではkernelは収まりませんね。う〜む、どうしたものか。

連続でなくてもとにかく必要なだけの物理メモリ(page out されない)を
確保し、カーネルの他に、「Xn から Yn 番地へ 1 page コピー」という
ようなことを書き連ねたマップを用意します。
ブートの直前、既にカーネルが停止した状態で、小さなプログラムが
このマップを元にどんどんコピーしてカーネルを連続領域に転送して
からカーネルの先頭に実行を移します。

pbsdboot では、具体的な手順は以下のようになっています。

 1. カーネルファイルの ELF ヘッダを検査して読み込み後の領域を調べる
    (例えば 0x80001000 から 1000 ページとか)
 2. 1. で求めた領域を記述するのに必要なマップやその他必要なページ数の計算
    (1000 ページならば、マップに 4 ページと bootinfo などに 1 ページと
      コピープログラムに 1 ページの合計 1006 ページとか)
 3. 必要なページの確保(system call を使う)
    (1006 ページを確保する。連続でなくて良い)
 4. 確保した各ページ全ての物理をアドレスを調べる(system call を使う)
 5. カーネルをロードする。同時にマップも作成
 6. コピープログラムを 1 ページに書き込む。bootinfo なども書き込む。
 7. 割り込みを禁止して、コピープログラムを実行する
    (ここで現在のカーネルは停止する)
 8. マップをたどりながら 1 ページずつコピーする
 9. マップの最後まで来たら cache を flush してカーネルの先頭に実行を移す

詳しくは src/sys/arch/hpcmips/stand/pbsdboot/vmem.c を見てみて下さい。
コピープログラムは同じディレクトリの vr41xx.c にあります。
小さなアセンブラのプログラムです。単独で cache を flush するために
CPU に依存したプログラムになっています。このため、TX39xx 用の
tx39xx.c もあります。hpcboot もほぼ同様の処理を行なっています。
(pbsdboot と hpcboot ではマップの構造がすこし違います。pbsdboot は
ツリー状になっているのに対し、hpcboot はリンクになっています。)

NetBSD 上で実装する場合は、2. と 4. を /dev/mem の ioctl とし、
6-9 も 1 つの ioctl にすると良いのではないかと思います。

Takemura