2012年10月7日作成
ESXiでfsカーネルのブート
6/12頃、ESXi 5.0にfs64カーネルを置いて動かしたところ、 起動時に、たぶんカーネルの実行がはじまったあたりで、 割り込みかなにかを受けてパニックしました。 回避はしたけど解決できていないので、いちおうまとめ。
具体的なメッセージはこんなの。
cpu0: 2590MHz P6
apm ax=f000 cx=f000 dx=40 di=ffff ebx=5470 esi=-1
bios (usb) loading disabled
no ethernet interfaces recognised
bus dev type vid did intlognised
bus dev type vid did intl memory
found 9fsfs64
.388008.........................+1208352.................+189444-705804
entry: 0x80100020
FLAGS=10086 TRAP=e ECODE=0 PC=80128b8c
AX f000ff53 BX 801913b4 CX 801959a4 DX 801913b4
SI 8012b96b DI 001ac964 BP 00000049
CS 0010 DS 0008 ES 0000 FS 0008 GS 0008
CR0 80010011 CR2 f000ff53 CR3 00183000
panic: exception/interrupt 14
FLAGS=10086 TRAP=e ECODE=0 PC=8001e777
AX 8001e769 BX 00000c80 CX 808185fc DX 00000006
SI 00000000 DI 8004f3e8 BP 0000000a
CS 0010 DS 0008 ES 0000 FS 0008 GS 0008
CR0 80010011 CR2 80818614 CR3 00183000
panic: exception/interrupt 14
....
interrupt 14とは
調べると、page faultでした。結構いやな感じ。
上記のログ"entry: 0x80100020"に続くのは、 おそらく"Plan 9 63-bit fileserver"で、 この文字列はmain()の中、一部の初期化が終わったところにあります。 で、exception/interrupt 14というメッセージは、 ローダの割り込みハンドラに書かれています。
最新のローダで動かす
最新(6/14頃)のCD imageからインストールしてみると普通に動きました。 そのまま、カーネルだけfs64に差し替えてみたらエラー。 なのでローダのメッセージが出ているけれど、原因はカーネルっぽい。
ESXiとの相性問題なのか調べる
少なくとも物理マシンで動いていた、2010年頃(もっと前かも)に作成した fs64のブートフロッピーからブートしたら動きました。 そのままカーネルだけを新しくコンパイルしたものに差し替えたら起動しません。
ビルド環境を変えてみる
fsカーネルは/386/lib/libc.a等をリンクしているようなので 適当に、/n/dump/2011/0701/386を/386にバインドして コンパイルしたものの、やっぱり変わらずエラー。
コンパイラとリンカを2011/07/01のものに変えたらなんだか動いた。
% 9fs dump
% bind /n/dump/2011/0701/386/8c /bin/8c
% bind /n/dump/2011/0701/386/8l /bin/8l
コンパイラのバグが修正されて、修正の結果、 それまでバグがあったおかげでたまたまうまく動いていた部分が 今回から落ちるようになったのなら、放置すると後で困りそうだなあ。
おまけ
いちおう読んだfsカーネルのブート周りのフロー。
port/main.c:main
port/sub.c:formatinit() # printの書式などを初期化
port/main.c:machinit() # mってなんだ?
pc/pc.c:vecinit()
# たぶん、9loadに読み込まれたplan9.iniをパースする
# confname[n], confval[n]に入る
# =が複数ある場合は、最初の=までがconfname
port/main.c:confinit()
# conf構造体を初期化
pc/pc.c:meminit()
pc/pc.c:mconfinit()
# mmap, mapaddrを初期化しているっぽい
pc/mmu.c:mmuinit()
# gdt, kptを初期化?
# このあたりになるとよくわからない
pc/mmu.c:taskswitch()
# tssを初期化
trapinit()
# 割り込み設定
# intr0, 1みたいな関数は、pc/l.sにあるアセンブリコード
# そこから潜って、pc/trap.c:trapに落ち着く
SEGCG: call gate
SEGIG: interrupt gate
SEGTG: task gate
# 0..255までにtask gateとして、intrbadを設定
sethvec() for 17..23, 40..255
# 0から16までは特別なintr0, intr1みたいなトラップ
# うち、14(page fault), 16(math coprocessor)はinterrupt gate
sethvec() for 0..16
# デバイス割り込みはinterrupt gate; これも特別なトラップ
sethvec() for 24..39
なんかいろいろ
fpinit()
fs64/9fsfs64.c:localconfinit()
# confをいろいろ設定
# 時間とか
pc/pc.c:lockinit()
# 何もしない
port/devcons.c:printinit()
# printq, readqを初期化
pc/pc.c:consinit()
# consgetc, consputc, consputs, intrputsの設定
# コンフィグがconsole=cgaでなければbaudとかも設定
pc/kbd.c:kbdinit()
port/proc.c:procinit()
# procallocを初期化
wakeup()
pc/8253.c:clockinit()
# 他もだが、特にここは本気でわからない
setvec()
cpuid()
cycles()
aamloop()
print("Plan 9 64 bit file server...")
printsizes()
alarminit()
# このあたりでserveq, raheadqを初期化
mbinit()
sntpinit()
fs64/9fsfs64.c:otherinit()
# 終わりに、files, wpaths, uid, gidspaceを初期化
authinit()
iobufinit()
arginit()
userinit()
wakeup()
launchinit()
schedinit()