kexec、kdump[2]

kexecの各セグメント(bzImageとか)の展開先の指定方法について調べている。
(1)kexec-toolsのオプションであるmem-minとmem-maxで指定可能だとか
あと(2)カーネルオプションのcrashkernel=ss@nnでも可能である
(1)(2)の方法で試しにやってみる
前提としてKdumpができるようにカーネルオプションを付けている必要がある
(少なくともカーネルがリロケータブルでないとならない)

(1)

例えばmem-min=0x2000000でやってみる。

$ sudo kexec -l /boot/vmlinuz-2.6.38.7-MK --initrd=/boot/kernel26-MK.img --append=root=/dev/disk/by-uuid/699d4d57-3a37-4419-a31f-df09cbf6afeb ro  --mem-min=0x20000000
Could not find a free area of memory of 5000 bytes...
locate_hole failed

どうやらうまくいかないようだ。
原因を突き止める前に(2)でやってみよう

(2)

まずGRUBのメニューでcrashkernel=126M@512Mとする。これはカーネルの読み込み先を512MBから512+126MBに指定するオプションである。
これを使うと起動時に領域を予約してくれるようだ。dmesgを実行すると以下の行が現れることで確認できる

[    0.000000] Reserving 126MB of memory at 512MB for crashkernel (System RAM: 9024MB)

そしてkexec-toolsに-pオプションをつけて(1)とほぼ同様に実行すると何故かうまくいく。

(1)の原因調査

ソースコードhttp://www.kernel.org/pub/linux/utils/kernel/kexec/)を入手し、デバッグ
(1)がうまくいかない理由をいろいろ探していたら、locate_holeにたどり着いた
locate_holeはどうやらセグメントの展開先に見合う空きメモリを探す関数のようだ
そのなかでエラーの原因となっているセグメントはなんと読み込み先が0xa000以下でないとならないらしく、
memminを512MBとしているので折り合いがつかず、失敗するようだ。
(2)だとなぜうまくいくのかというと、-pオプションだとKEXEC_ON_CRASHというフラグが立ち、
このフラグが立っている場合は問題のセグメントの読み込み先の上限を0xa000から無限大にするようだ。
全部無限にしろよー・・・と思う。事実、ソースコードに変更を加えて、いつでも上限を無限にしてしまえばうまくいくのだ。