FPGA開発日記

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

ブートセクションをずらしてISSでブートできるようにする(ディスクのロード)

※ この記事はまだ勉強中のため、いろいろ間違いがあるかもしれません。

xv6のbootmain.cをコンパイルしてブートローダを作ってみたが、何とMIPSコンパイラではオブジェクトのサイズが1セクタ(512バイト)に入り切らなかった! そこで、今回はアーキテクチャも違う、ということで、割り切って、1セクタにブートローダを入れる制約を無くし、自由にロードできるようにする。

ISSにおいて、imgファイルをロードするのは、以下のような機能を追加した。IDEのセクションにアクセスすると、自動的にディスクを読み込んで、次の位置までポインタを進める。

github.com

Word_t ModuleIde::ReadImgFile (void)
{
    Word_t word = 0;
    for (int i = 0; i < 4; i++) {
        Byte_t byte_data;
        if ((byte_data = fgetc (m_img_fp)) == EOF) {
            return 0;
        }
        word = ((word >> 8) & 0x00FFFFFFULL) | (byte_data << 24);
    }
    m_env->DebugPrint ("<ReadImgFile(Index=%d)=>%08x>\n", m_read_count, word);
    if ((++m_read_count) == 512 / 4) {
        CloseImgFile ();
        m_read_count = 0;
    }

    return word;
}

さて、これをロードするために、readsect()内に入っているstosb()を変更する。

github.com

static inline void
stosb(void *addr, int data, int cnt)
{
  int i;
  for (i = 0; i < cnt; i++) {
    *(((volatile char *) addr) + i) = (char) data;
  }
}

また、実行している最中に気が付いたのだが、img_env.cpp内でread()関数に1024バイト分のイメージをロードしている。

{
    const int read_size = 1024;

    uint8_t buf[read_size];

    Addr_t start_addr = 0xbfc00000;

    // open binary
    int fs_img = open (filename.c_str(), O_RDONLY, S_IREAD);
    if (fs_img < 0) {
        perror (filename.c_str());
        exit (EXIT_FAILURE);
    }

    // Seek Kernel Load position
    if (lseek (fs_img, start_addr, 0) == -1) {
        perror ("lseek");
    }

    // Read head 1024byte of image file
    if (read (fs_img, buf, 1024) != 1024){
        perror ("read");
        exit (EXIT_FAILURE);
    }

このとき、ブートローダはディスクイメージの最後の方にいて、実は1024バイト分イメージが存在していない。 これにより、

if (read (fs_img, buf, 1024) != 1024){

が成立せずに落ちてしまうことが分かった。 これを防ぐために、xv6.imgを拡張して、最初からbfc0_0000から2セクタ分余分にディスク領域を確保しておく。

xv6.img: bootblock kernel fs.img Makefile
        dd if=/dev/zero of=xv6.img count=6283266
        dd if=bootblock of=xv6.img seek=6283264 conv=notrunc
        dd if=kernel of=xv6.img seek=1 conv=notrunc
        hexdump xv6.img > xv6.img.dmp

イメージとしては3GBにもなってしまうが、まあ、実験用だし、いっか。

-rw-rw-r-- 1 vagrant vagrant 3.0G Sep 16 15:37 xv6.img

これで、ブートローダがディスクからイメージをロードして、main()まで行く道筋が出来上がった! 実行してみよう。

swimmer_mips --imgfile xv6.img --out debug.log --debug_func --debug_gvar --max 10000000 --img_dump --binfile bootblock.o --only_info_load --debug
bfc00000 : 00 60 08 40 01 00 09 24 25 40 29 01 26 40 09 01
bfc00010 : 00 ff 08 35 00 10 09 3c 25 40 09 01 00 60 88 40
bfc00020 : c0 bf 1d 3c 00 00 bd 27 c0 bf 18 3c 4c 01 18 27
bfc00030 : 09 f8 00 03 00 00 00 00 20 00 00 42 00 b4 05 3c
bfc00040 : c0 ff 04 24 40 00 03 24 f7 01 a2 90 ff 00 42 30
bfc00050 : 24 10 44 00 fc ff 43 14 00 00 00 00 08 00 e0 03
bfc00060 : 00 00 00 00 e0 ff bd 27 1c 00 bf af 18 00 b1 af
bfc00070 : 14 00 b0 af 21 88 80 00 0f 00 f0 0f 21 80 a0 00
bfc00080 : 00 b4 02 3c 01 00 03 24 f2 01 43 a0 02 1a 10 00
bfc00090 : f3 01 50 a0 f4 01 43 a0 e0 ff 05 24 02 1c 10 00
bfc000a0 : 02 86 10 00 f5 01 43 a0 25 80 05 02 20 00 03 24
bfc000b0 : f6 01 50 a0 0f 00 f0 0f f7 01 43 a0 21 20 20 02
bfc000c0 : 00 02 22 26 00 b4 05 3c f0 01 a3 8c 04 00 84 24
bfc000d0 : fd ff 82 14 fc ff 83 ac 1c 00 bf 8f 18 00 b1 8f
bfc000e0 : 14 00 b0 8f 08 00 e0 03 20 00 bd 27 e0 ff bd 27
bfc000f0 : 14 00 b1 af ff 01 d1 30 42 32 06 00 18 00 b2 af
bfc00100 : 10 00 b0 af 1c 00 bf af 21 90 85 00 23 88 91 00
bfc00110 : 01 00 d0 24 2b 10 32 02 06 00 40 10 21 20 20 02
bfc00120 : 19 00 f0 0f 21 28 00 02 00 02 31 26 45 00 f0 0b
bfc00130 : 01 00 10 26 1c 00 bf 8f 18 00 b2 8f 14 00 b1 8f
bfc00140 : 10 00 b0 8f 08 00 e0 03 20 00 bd 27 e0 ff bd 27
bfc00150 : 10 80 04 3c 00 10 05 24 21 30 00 00 1c 00 bf af
bfc00160 : 18 00 b2 af 14 00 b1 af 3b 00 f0 0f 10 00 b0 af
bfc00170 : 10 80 02 3c 00 00 44 8c 4c 46 03 3c 7f 45 63 24
bfc00180 : 25 00 83 14 1c 00 bf 8f 1c 00 50 8c 2c 00 51 94
bfc00190 : 21 80 50 00 40 89 11 00 21 88 11 02 2b 10 11 02
bfc001a0 : 16 00 40 10 10 80 02 3c 0c 00 12 8e 10 00 05 8e
bfc001b0 : 04 00 06 8e 3b 00 f0 0f 21 20 40 02 14 00 03 8e
bfc001c0 : 10 00 02 8e 2b 20 43 00 f4 ff 80 50 20 00 10 26
bfc001d0 : 23 18 62 00 21 28 00 00 21 10 52 00 2a 20 a3 00
bfc001e0 : 04 00 80 10 21 20 45 00 00 00 80 a0 77 00 f0 0b
bfc001f0 : 01 00 a5 24 67 00 f0 0b 20 00 10 26 1c 00 bf 8f
bfc00200 : 18 00 b2 8f 14 00 b1 8f 10 00 b0 8f 18 00 59 8c
bfc00210 : 08 00 20 03 20 00 bd 27 18 00 b2 8f 14 00 b1 8f
bfc00220 : 10 00 b0 8f 08 00 e0 03 20 00 bd 27 00 00 00 00
bfc00230 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc00240 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc00250 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc00260 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc00270 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc00280 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc00290 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc002a0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc002b0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc002c0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc002d0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc002e0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc002f0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc00300 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc00310 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc00320 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc00330 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc00340 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc00350 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc00360 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc00370 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc00380 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc00390 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc003a0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc003b0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc003c0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc003d0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc003e0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bfc003f0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

$ less debug.log
...
   4962745 : [bfc001fc] 8fbf001c : lw      r31,0x001c(r29)         r29=>bfbfffe0 (bfbffffc)=>bfc00038 r31<=bfc00038
   4962746 : [bfc00200] 8fb20018 : lw      r18,0x0018(r29)         r29=>bfbfffe0 (bfbffff8)=>00000000 r18<=00000000
   4962747 : [bfc00204] 8fb10014 : lw      r17,0x0014(r29)         r29=>bfbfffe0 (bfbffff4)=>00000000 r17<=00000000
   4962748 : [bfc00208] 8fb00010 : lw      r16,0x0010(r29)         r29=>bfbfffe0 (bfbffff0)=>00000000 r16<=00000000
   4962749 : [bfc0020c] 8c590018 : lw      r25,0x0018(r02)         r02=>80100000 (80100018)=>80100000 r25<=80100000
   4962750 : [bfc00210] 03200008 : jr      r25                     r25=>80100000 pc<=bfc00214 pc<=80100000
   4962751 : [bfc00214] 27bd0020 : addiu   r29,r29,0x0020          r29=>bfbfffe0 r29<=bfc00000
<Error: instruction is not decoded. [80100000]=464c457f

途中で命令デコードエラーが発生して落ちた。これを次回は解析しよう。