pipe 追加した直後くらいに make DEBUG=1 qemu で ls | wc すると変な仮想アドレスにアクセスしてしまうバグがあった。
$ ls | wc
...
panicked at 'PhysAddr(0xffc00000) is too high', src/pmap.rs:167:9
panicked 後に gdb から SIGINT 送って backtrace を確認した。
(gdb) c
Continuing.
^C
Program received signal SIGINT, Interrupt.
The target architecture is assumed to be i386
=> 0xf01001cf <rust_begin_unwind+303>: jmp 0xf01001cf <rust_begin_unwind+303>
0xf01001cf in rust_begin_unwind (info=0xeffff258) at src/lib.rs:70
70 loop {}
(gdb) backtrace
#0 0xf01001cf in rust_begin_unwind (info=0xeffff258) at src/lib.rs:70
#1 0xf0155b3d in core::panicking::panic_fmt ()
#2 0xf01494e7 in xv6_rust::pmap::PhysAddr::to_va (self=0xeffff324) at src/pmap.rs:167
#3 0xf014cf10 in xv6_rust::pmap::PageAllocator::alloc (self=0xf01af724 <xv6_rust::pmap::PAGE_ALLOCATOR+4>,
flag=xv6_rust::pmap::AllocFlag::AllocZero) at src/pmap.rs:1006
#4 0xf0149cfe in xv6_rust::pmap::PageDirectory::walk (self=0xeec06000, va=..., should_create=true,
allocator=0xf01af724 <xv6_rust::pmap::PAGE_ALLOCATOR+4>) at src/pmap.rs:330
#5 0xf014a4ae in xv6_rust::pmap::PageDirectory::insert (self=0xeec06000, pa=..., va=..., perm=6,
allocator=0xf01af724 <xv6_rust::pmap::PAGE_ALLOCATOR+4>) at src/pmap.rs:430
#6 0xf014a733 in xv6_rust::pmap::PageDirectory::region_alloc (self=0xeec06000, va=..., len=4096) at src/pmap.rs:453
#7 0xf0129997 in xv6_rust::env::exec (path=0xeffff864 "wc\000", argv=...,
env=0xf015de4c <xv6_rust::env::ENV_TABLE+900>) at src/env.rs:693
#8 0xf0137d21 in xv6_rust::sysfile::exec (orig_path=0x802025 <error: Cannot access memory at address 0x802025>,
orig_argv=...) at src/sysfile.rs:385
#9 0xf0147d54 in xv6_rust::syscall::syscall (syscall_no=7, a1=8396837, a2=8396837, a3=0, a4=0, a5=0)
at src/syscall.rs:146
#10 0xf011b7a0 in xv6_rust::trap::trap_dispatch (tf=0xf015de4c <xv6_rust::env::ENV_TABLE+900>) at src/trap.rs:373
#11 0xf011bca1 in trap (orig_tf=0xefffffbc) at src/trap.rs:442
#12 0xf014efe9 in _alltraps () at src/alltraps.S:22
#13 0xefffffbc in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
pipe 追加した直後くらいに
make DEBUG=1 qemu
でls | wc
すると変な仮想アドレスにアクセスしてしまうバグがあった。panicked 後に gdb から SIGINT 送って backtrace を確認した。
PageAllocator の alloc で失敗しているっぽい。 alloc 時の挙動を見るためにログを追加してみた。
最後から 2 つ目で設定している page_free_list (次に alloc したときに手に入れる PageInfo, つまり物理ページ) がおかしい。 0xf01a8000 というのは end symbol (kernel の末尾として kernel.ld で設定している) 0xf01a9000 よりも前なのでそのアドレスを alloc してはいけない。 ただ調べるとどうやら悪いのは alloc というより end symbol の位置っぽい。というのは objdump によれば kernel が end よりも後にもロードされることになっているので。
LOAD 4 つ目から 0xf015d000 + 0x00092001 = 0xf01ef001 であり、上の end より明らかに大きい。
kernel.ld
を JOS のそれと比べるといくつか省略していた section があったのでそれを追加したところ修正された。恐らくエラーの原因は kernel の bss 領域を PageInfo の一部として不正に使ってしまったせいだった。(0xf01ee23e を PGSIZE で切り上げれば 0xf01ef000 なので ok)
なお追加した section のうち実際に存在していたのは
.bss.*
のみだった。これがどのオブジェクトファイル由来か調べるまではやっていないが、とりあえずこれらも原則加えると思ってしまっていいのかなと。