6.828: Operating System Engineering (3)

とりあえず Ubuntu-box な qemu では動かないのだろう、ということにて tarball を download して

$ ./configure --prefix=/opt --target-list="i386-softmmu x86_64-softmmu"
$ make
$ sudo make install

した後に以下。

$ /opt/bin/qemu -hda ../lab/obj/kern/kernel.img 

一応以下なソレが出力されております。

Booting from Hard Disk...
6828 decimal is XXX octal!
entering test_backtrace 5
entering test_backtrace 4
entering test_backtrace 3
entering test_backtrace 2
entering test_backtrace 1
entering test_backtrace 0
leaving test_backtrace 0
leaving test_backtrace 1
leaving test_backtrace 2
leaving test_backtrace 3
leaving test_backtrace 4
leaving test_backtrace 5
Welcome to the JOS kernel monitor!
Type 'help' for a list of commands.
K>

以下な出力も確認。

K> help
help - display this list of commands
kerninfo - display information about the kernel
K> kerninfo
Special kernel symbols:
  _start f010000c (virt)  0010000c (phys)
  etext  f0101a05 (virt)  00101a05 (phys)
  edata  f0110320 (virt)  00110320 (phys)
  end    f0110980 (virt)  00110980 (phys)
Kernel executable memory footprint: 67KB
K>

ちょっと Web なテキストと違いますね。

掘削しかけてしまった件

なんとなくソース見てやれ、って思って GNUMakefile を開いて中身を確認しかけたのですが、色々ばたばたしていたので掘削には至らず。
とりあえずテキストの続きを確認入れます。メモがあれば以下に追記予定。

GNUMakefile

そういや make qemu で動くんだったか、と言いつつ実行したら駄目。下記を追加してみました。

#
# This makefile system follows the structuring conventions
# recommended by Peter Miller in his excellent paper:
#
#	Recursive Make Considered Harmful
#	http://aegis.sourceforge.net/auug97.pdf
#
QEMU := /opt/bin/qemu
OBJDIR := obj

で、make qemu したら -serial mon:stdio のおかげで qemu なソレだけでなく起動端末でも同様の出力を確認。

The ROM BIOS の項

デバッガで云々な話が出てます。ええと

$ make qemu-gdb

して端末をもういっこ出して lab なディレクトリ (git clone したソレ) に入って

$ gdb
GNU gdb (GDB) 7.2-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
+ target remote localhost:26000
The target architecture is assumed to be i8086
[f000:fff0]    0xffff0: ljmp   $0xf000,$0xe05b
0x0000fff0 in ?? ()
+ symbol-file obj/kern/kernel
(gdb) 

これはまたお手軽ですね。てか、これはどーゆーレベルで止まってるのかが分かってません。ええとコマンドラインで make qemu-gdb したソレが以下。

$ make qemu-gdb
sed "s/localhost:1234/localhost:26000/" < .gdbinit.tmpl > .gdbinit
***
*** Now run 'gdb'.
***
/opt/bin/qemu -hda obj/kern/kernel.img -serial mon:stdio -S -gdb tcp::26000

これ GNUMakefile の以下な部分のソレだな。

qemu-gdb: $(IMAGES) .gdbinit
	@echo "***"
	@echo "*** Now run 'gdb'." 1>&2
	@echo "***"
	$(QEMU) $(QEMUOPTS) -S $(QEMUGDB)

ちなみに .gdbinit 云々は .gdbinit という target があります。

.gdbinit: .gdbinit.tmpl
	sed "s/localhost:1234/localhost:$(GDBPORT)/" < $^ > $@

とりあえず

起動したソレから si してみるか。

The target architecture is assumed to be i8086
[f000:fff0]    0xffff0: ljmp   $0xf000,$0xe05b
0x0000fff0 in ?? ()
+ symbol-file obj/kern/kernel
(gdb)
(gdb) si
[f000:e05b]    0xfe05b: jmp    0xfefdb
0x0000e05b in ?? ()
(gdb) 

ええと 16 * 0xf000 + 0xe05b で 0xfe05b に jmp しとるんかな。また jmp してます。

(gdb) si
[f000:efdb]    0xfefdb: mov    %cr0,%eax
0x0000efdb in ?? ()
(gdb) 

う。レジスタの確認の方法を忘れとる。ascii の GDB 本を引っ張り出してみたら $eax で良いのか。

(gdb) p %eax
A syntax error in expression, near `%eax'.
(gdb) p/x $eax
$1 = 0x0
(gdb) p/x $cr0
$2 = Value can't be converted to integer.
(gdb) p $cr0
$3 = void
(gdb) 

とほほ void って何だよ。スルーして次を見る。

(gdb) si
[f000:efde]    0xfefde: and    $0x9fffffff,%eax
0x0000efde in ?? ()
(gdb) 

レジスタの中身を見てみます。

(gdb) p $eax
$4 = 1610612752
(gdb) x/i $eax
   0x60000010:  add    %al,(%bx,%si)
(gdb) 

うう。というかこのあたり BIOS なソレなのか。命令のアドレスを見つつとりあえず si しまくってみます。

(gdb) si
[f000:efe4]    0xfefe4: mov    %eax,%cr0
0x0000efe4 in ?? ()
(gdb) si
[f000:efe7]    0xfefe7: cli    
0x0000efe7 in ?? ()
(gdb) si
[f000:efe8]    0xfefe8: cld    
0x0000efe8 in ?? ()
(gdb) si
[f000:efe9]    0xfefe9: mov    $0x8f,%eax
0x0000efe9 in ?? ()
(gdb) si
[f000:efef]    0xfefef: out    %al,$0x70
0x0000efef in ?? ()
(gdb) si
[f000:eff1]    0xfeff1: in     $0x71,%al
0x0000eff1 in ?? ()
(gdb) si
[f000:eff3]    0xfeff3: cmp    $0x0,%al
0x0000eff3 in ?? ()
(gdb) si
[f000:eff5]    0xfeff5: jne    0xff00a
0x0000eff5 in ?? ()
(gdb) si
[f000:eff7]    0xfeff7: xor    %ax,%ax
0x0000eff7 in ?? ()
(gdb) si
[f000:eff9]    0xfeff9: mov    %ax,%ss
0x0000eff9 in ?? ()
(gdb) si
[f000:effb]    0xfeffb: mov    $0x7000,%esp
0x0000effb in ?? ()
(gdb) si
[f000:f001]    0xff001: pushl  $0xf194b
0x0000f001 in ?? ()
(gdb) si
[f000:f007]    0xff007: jmp    0xffeae
0x0000f007 in ?? ()
(gdb) si
[f000:feae]    0xffeae: mov    %eax,%ecx
0x0000feae in ?? ()
(gdb) si
[f000:feb1]    0xffeb1: cli    
0x0000feb1 in ?? ()
(gdb) si
[f000:feb2]    0xffeb2: cld    
0x0000feb2 in ?? ()
(gdb) si
[f000:feb3]    0xffeb3: mov    $0x8f,%eax
0x0000feb3 in ?? ()
(gdb) si
[f000:feb9]    0xffeb9: out    %al,$0x70
0x0000feb9 in ?? ()
(gdb) si
[f000:febb]    0xffebb: in     $0x71,%al
0x0000febb in ?? ()
(gdb) si
[f000:febd]    0xffebd: in     $0x92,%al
0x0000febd in ?? ()
(gdb) si
[f000:febf]    0xffebf: or     $0x2,%al
0x0000febf in ?? ()
(gdb) si
[f000:fec1]    0xffec1: out    %al,$0x92
0x0000fec1 in ?? ()
(gdb) si
[f000:fec3]    0xffec3: lidtw  %cs:0x7a18
0x0000fec3 in ?? ()
(gdb) si
[f000:fec9]    0xffec9: lgdtw  %cs:0x7a58
0x0000fec9 in ?? ()
(gdb) si
[f000:fecf]    0xffecf: mov    %cr0,%eax
0x0000fecf in ?? ()
(gdb) si
[f000:fed2]    0xffed2: or     $0x1,%eax
0x0000fed2 in ?? ()
(gdb) si
[f000:fed6]    0xffed6: mov    %eax,%cr0
0x0000fed6 in ?? ()
(gdb) si
[f000:fed9]    0xffed9: ljmpl  $0x8,$0xffee1
0x0000fed9 in ?? ()
(gdb) si
The target architecture is assumed to be i386
=> 0xffee1:     mov    $0x10,%eax
0x000ffee1 in ?? ()
(gdb)

なんかちょっと違うステイトになった気がします。もう少し続行。

(gdb) si
=> 0xffee6:     mov    %eax,%ds
0x000ffee6 in ?? ()
(gdb) si
=> 0xffee8:     mov    %eax,%es
0x000ffee8 in ?? ()
(gdb) si
=> 0xffeea:     mov    %eax,%ss
0x000ffeea in ?? ()
(gdb)

なんかセグメントレジスタに値が代入してるように見えるが。

(gdb) si
=> 0xffeec:     mov    %eax,%fs
0x000ffeec in ?? ()
(gdb) si
=> 0xffeee:     mov    %eax,%gs
0x000ffeee in ?? ()
(gdb) si
=> 0xffef0:     mov    %ecx,%eax
0x000ffef0 in ?? ()
(gdb) si
=> 0xffef2:     ret    
0x000ffef2 in ?? ()
(gdb) 

む、ret したぞ。

(gdb) si
=> 0xf194b:     push   %ebp
0x000f194b in ?? ()
(gdb) si
=> 0xf194c:     push   %edi
0x000f194c in ?? ()
(gdb) si
=> 0xf194d:     push   %esi
0x000f194d in ?? ()
(gdb) si
=> 0xf194e:     push   %ebx
0x000f194e in ?? ()
(gdb) si
=> 0xf194f:     sub    $0xdc,%esp
0x000f194f in ?? ()
(gdb) si
=> 0xf1955:     xor    %edx,%edx
0x000f1955 in ?? ()
(gdb) si
=> 0xf1957:     mov    %dl,%al
0x000f1957 in ?? ()
(gdb) si
=> 0xf1959:     out    %al,$0xd
0x000f1959 in ?? ()
(gdb) si
=> 0xf195b:     out    %al,$0xda
0x000f195b in ?? ()
(gdb) si
=> 0xf195d:     mov    $0xc0,%al
0x000f195d in ?? ()
(gdb) si
=> 0xf195f:     out    %al,$0xd6
0x000f195f in ?? ()
(gdb)

まだ BIOS っぽい。違うのかなぁ。

(gdb) si
=> 0xf1961:     mov    %dl,%al
0x000f1961 in ?? ()
(gdb) si
=> 0xf1963:     out    %al,$0xd4
0x000f1963 in ?? ()
(gdb) si
=> 0xf1965:     push   $0xf5420
0x000f1965 in ?? ()
(gdb) si
=> 0xf196a:     push   $0xf4f90
0x000f196a in ?? ()
(gdb) si
=> 0xf196f:     call   0xed965
0x000f196f in ?? ()
(gdb) si
=> 0xed965:     lea    0x8(%esp),%ecx
0x000ed965 in ?? ()
(gdb)

なんだか関数呼び出してたり。

(gdb) si
=> 0xed969:     mov    0x4(%esp),%edx
0x000ed969 in ?? ()
(gdb) si
=> 0xed96d:     mov    $0xf7288,%eax
0x000ed96d in ?? ()
(gdb) si
=> 0xed972:     call   0xed1e0
0x000ed972 in ?? ()
(gdb) si
=> 0xed1e0:     push   %ebp
0x000ed1e0 in ?? ()
(gdb) si
=> 0xed1e1:     push   %edi
0x000ed1e1 in ?? ()
(gdb) si
=> 0xed1e2:     push   %esi
0x000ed1e2 in ?? ()
(gdb) si
=> 0xed1e3:     push   %ebx
0x000ed1e3 in ?? ()
(gdb) 

このあたりは BIOS ROM に書いてある処理だからね、って理解で良いのかどうか。明日時間があればもうすこし地味にこのあたりを確認してみたいと思います。