6.828: Operating System Engineering (62)
以下のどこかでオチている模様。
// Turn on paging. cr0 = rcr0(); cr0 |= CR0_PE|CR0_PG|CR0_AM|CR0_WP|CR0_NE|CR0_TS|CR0_EM|CR0_MP; cr0 &= ~(CR0_TS|CR0_EM); lcr0(cr0);
いつまでも printf デバッグとゆーのもアレだし、レジスタダンプによれば
EIP=f01028a7 EFL=00000086 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
とのことなのでデバッガで場所は分かるはず。というかどう考えても lcr0 な命令で、なのだろうとは思いますが。
デバッガで確認
ちなみにダンプによれば cr0 レジスタの値は 80050033 でこれは
CR0_PE|CR0_MP|CR0_ET|CR0_NE|CR0_WP|CR0_AM|CR0_PG
になります。ちなみに
cr0 = rcr0(); || した時点での cr0 の状態は 0x11 になってて >|| cr0 |= CR0_PE|CR0_PG|CR0_AM|CR0_WP|CR0_NE|CR0_TS|CR0_EM|CR0_MP; cr0 &= ~(CR0_TS|CR0_EM);
で、0x80050033 になるのか。
あら?
オチる直前に p/x $cr0 したら以下なナニ。あと info registers の出力に control register が出てこない。
(gdb) p/x $cr0 $8 = Value can't be converted to integer. (gdb) info registers eax 0x0 0 ecx 0x3d5 981 edx 0x3d5 981 ebx 0x80050033 -2147155917 esp 0xf0113f80 0xf0113f80 ebp 0xf0113fd8 0xf0113fd8 esi 0x9f 159 edi 0xf0146bf4 -267097100 eip 0xf01028b4 0xf01028b4 <i386_vm_init+5791> eflags 0x86 [ PF SF ] cs 0x8 8 ss 0x10 16 ds 0x10 16 es 0x10 16 fs 0x10 16 gs 0x10 16 (gdb)
と思ったら随分前に
(gdb) p $cr0 $6 = void (gdb)
な問題は検出してたりするけどスルーされている模様。
gdb で
見てるのですが、cr0 への格納はできてるのかどうか。
gdb) n => 0xf0102899 <i386_vm_init+5764>: mov %cr0,%ebx 174 __asm __volatile("movl %%cr0,%0" : "=r" (val)); (gdb) n => 0xf010289c <i386_vm_init+5767>: or $0x8005002f,%ebx 260 cr0 |= CR0_PE|CR0_PG|CR0_AM|CR0_WP|CR0_NE|CR0_TS|CR0_EM|CR0_MP; (gdb) n => 0xf01028a2 <i386_vm_init+5773>: movl $0xf01047a3,(%esp) 262 cprintf("(i386_vm_init) (3.5)\n"); (gdb) n => 0xf01028ae <i386_vm_init+5785>: and $0xfffffff3,%ebx 167 __asm __volatile("movl %0,%%cr0" : : "r" (val)); (gdb) n => 0xf01028b4 <i386_vm_init+5791>: movl $0xf01047b9,(%esp) 267 cprintf("(i386_vm_init) (4)\n"); (gdb)
なんつーか出力されてる命令が、cr0 に出力してる箇所あたりから整合してないんだよな。これ系の不具合ってどう対処すべきなんだろ。本当に始末に困る。
しかし上記のソレは printf デバッグの痕跡ががっつり確認できて情無いッスね。
ちなみに上記の状態から n したらレジスタダンプが出て止まらなくなります。QEMU も暴走してるカンジに見えますね。ダンプが以下。
EAX=00000000 EBX=80050033 ECX=000003d5 EDX=000003d5 ESI=0000009f EDI=f0146bf4 EBP=f0113fd8 ESP=f0113f80 EIP=f01028b4 EFL=00000086 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0 ES =0010 10000000 ffffffff 10cf9300 DPL=0 DS [-WA] CS =0008 10000000 ffffffff 10cf9a00 DPL=0 CS32 [-R-] SS =0010 10000000 ffffffff 10cf9300 DPL=0 DS [-WA] DS =0010 10000000 ffffffff 10cf9300 DPL=0 DS [-WA] FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA] GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA] LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy GDT= 00114000 00000017 IDT= 00000000 000003ff CR0=80050033 CR2=00113f80 CR3=00115000 CR4=00000000 DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 DR6=ffff0ff0 DR7=00000400 Triple fault. Halting for inspection via QEMU monitor.
ん、Triple fault って何でしょ。wikipedia に以下な記述が。
In QEMU, a triple fault produces a dump of the virtual machine in the console, with the instruction pointer set to the instruction that triggered the first exception.
eip は 0xf01028b4 とありますな。
なんとなく
ページングを有効にしたらオチる、ってことはその準備に何らかの手抜かりがあるのだろうな、ということで別途夜に確認してみます。