FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://sites.google.com/site/fpgadevelopindex/

xv6の起動プロセスを追い掛けるためのシミュレータの準備

msyksphinz.hatenablog.com

前の記事ではあまりにも中身が無かったが、今回も作業ログで中身が無い。

xv6のコンパイル結果のバイナリ

調べてみると、xv6でコンパイルしたコードの中で、オブジェクトとして残っているもので一番多きなものはkernelだった。 kernelをobjdumpしているものとして、kernel.asmが残っている。つまり、これをロードしてシミュレータで流してみると、一応ブートプロセスが辿れるかもしれない。

kernel:     file format elf32-littlemips


Disassembly of section .text:

80100000 <_start>:
.align 2

# By convention, the _start symbol specifies the ELF entry point.
.globl _start
_start:
  mfc0   $t0, $COP0_STATUS
80100000:       00 60 08 40 01 00 09 24 25 40 29 01 26 40 09 01     .`.@...$%@).&@..
  # Disable interrput
  li     $t1, STATUS_IE
  or     $t0, $t1, $t1
  xor    $t0, $t0, $t1
  # Setup IM registers preparing for enabling interrput
  ori    $t0, $t0, STATUS_IM
80100010:       00 ff 08 35 00 10 09 3c 25 40 09 01 00 60 88 40     ...5...<%@...`.@
  lui    $t1, STATUS_CU0 >> 16
  or     $t0, $t0, $t1
  mtc0   $t0, $COP0_STATUS

  # Set up the stack pointer.
  la  $sp, stack + KSTACKSIZE
80100020:       51 80 1d 3c e0 d6 bd 27 10 80 08 3c 84 50 08 25     Q..<...'...<.P.%

  # Jump to main()
  la     $t0, main
  jr     $t0
80100030:       08 00 00 01 00 00 00 00 00 00 00 00                 ............

8010003c <binit>:
  struct buf head;
} bcache;

void
binit(void)
{
8010003c:       27bdffe0        addiu   sp,sp,-32
80100040:       afbf001c        sw      ra,28(sp)
80100044:       afbe0018        sw      s8,24(sp)
80100048:       03a0f021        move    s8,sp
  struct buf *b;

  initlock(&bcache.lock, "bcache");
8010004c:       3c028051        lui     v0,0x8051
80100050:       2444d6e0        addiu   a0,v0,-10528
80100054:       3c028011        lui     v0,0x8011
80100058:       2445b500        addiu   a1,v0,-19200
...

あ、mfc0とmtc0をシミュレータに実装してないや。とりあえず空っぽでいいから実装してみる。 こういう時に、命令の追加を自動化しておくと楽だ。

github.com

コンパイルされたバイナリを実行してみる。

さて、実行してみると、何が起きるだろう。PCはとりあえず0x8010_0000を設定して実行してみた。

swimmer_mips --binfile ./kernel --max 10000 --init_pc 80100000 --out debug.log --debug --debug_func --debug_gvar

おお、何となく実行されている。 命令の詳細は表示せずに、通過する関数だけ表示していってみよう。

swimmer_mips --binfile ./kernel --max 10000 --init_pc 80100000 --out debug.log --debug_func > swimmer.log

<Finish loading global variable table>
<Func: main>
<Func: kinit1>
<Func: initlock>
<Func: freerange>
<Func: kvmalloc>
<Func: setupkvm>
<Func: kalloc>
<Func: switchkvm>
<Func: mpinit>
<Func: cprintf>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: printint>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: consputc>
<Func: uartputc>
<Func: picinit>
<Func: outb>
<Info: NewMemory Region is defined.
<Func: outb>
<Func: outb>
<Func: outb>
<Func: outb>
<Func: outb>
<Func: outb>
<Func: outb>
<Func: outb>
...

うーん、これ本当に合ってるのかな。ソースコード見ながら追い掛けるしかないか。これも勉強だ。 xv6の資料を見ながら、これが本当に正しい動作なのかを確かめる。そして、Swimmerのログ表記が分かりにくかったので、後で直す。