読者です 読者をやめる 読者になる 読者になる

FPGA開発日記

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

xv6を移植するときに書き換えるルーチンについて調査(7)

xv6

http://img.deusm.com/eetimes/2014/08/1323406/microprocessor-x-366.jpg

msyksphinz.hatenablog.com

xv6のRISC-Vへのインポートの続き。

そういえばISSRISC-V用ビルドには、IDEモジュールとUARTモジュールを追加していなかった。 x86では、IDEやUARTはinbやoutb命令で操作できるが(つまりポートマップドI/O)、MIPSRISC-Vではそうはいかない。メモリマップに、これらのモジュールを定義しておかなければならない。

メモリマップドI/O - Wikipedia

ポートマップドI/Oでは、入出力用の特別なCPU命令を使用する。例えば、インテルx86には入出力専用の IN 命令と OUT 命令があり、入出力機器の1つのバイトの読み書きを行う。

RISC-Vの実装で、外部アクセス系を具体的にどこにマップすればよいのか資料を見つけることはできなかったが、とりあえず適当にマップを作成する。このマップは後で変更するつもりだけれども。

start end
IDEモジュール 0xffff_0000 0xffff_7fff
UARTモジュール 0xffff_8000 0xffff_ffff

github.com

基本的にメモリマップI/Oなので、ロードストア処理の部分に分岐を突っ込んでやっておけば外部I/Oモジュールにアクセスできるようになる。

この実装はずいぶんと付け焼刃な感じがして、拡張性に乏しいが、後でちゃんとテーブルとか作って書き直そう。

MemResult RiscvEnv::LoadFromBus (Addr_t addr, Size_t size, DWord_t *data)
{
  Byte_t byte[8];
  MemResult result;
  if (addr >= ide_start && addr <= ide_end) {
    Addr_t ide_addr = addr - ide_start;
    Word_t w_data;
    result = m_ide->LoadData (ide_addr, size, &w_data);
    *data = static_cast<Word_t>(w_data);
  } else if (addr >= uart_start && addr <= uart_end) {
    Addr_t uart_addr = addr - uart_start;
    Word_t w_data;
    result = m_uart->LoadData (uart_addr, size, &w_data);
    *data = static_cast<Word_t>(w_data);
  } else {
    result = LoadFromBus (addr, size, byte);
    memcpy (data, byte, 8);
  }
  return result;
}

IDEモジュールについて

今回実装しているIDEモジュールは、MIPS用シミュレータを作ったときに実装したものだけれど、基本的にそれを流用すればよいと思っている。

msyksphinz.hatenablog.com

ATA/ATAPI/I/O Port, Register - OS Project Wiki

UARTモジュールについて

こっちは、Intel 8250というモジュールを利用している。これも、MIPS用シミュレータを作ったときに実装したものだ。

8250 UART - Wikipedia

実装した結果、まずはRISC-VのIPLが動作してOSをローディングするようになった。つまりIPL(Initial Program Loader)が動作し始めた。

       103:M:MBar:[000002a0] ffff06b7 : lui        r13,0xffff0          r13<=ffff0000
       104:M:MBar:[000002a4] 04000713 : addi       r14,r00,0x040        r00=>00000000 r14<=00000040
<IDE: CommandPort:RegularStatus(0x000001f7) Load>
       105:M:MBar:[000002a8] 1f76c783 : lbu        r15,r13,0x1f7        r13=>ffff0000 r15<=00000040
       106:M:MBar:[000002ac] 0c07f793 : andi       r15,r15,0x0c0        r15=>00000040 r15<=00000040
       107:M:MBar:[000002b0] fee79ce3 : bne        r15,r14,0x7f         r15=>00000040 r14=>00000040
       108:M:MBar:[000002b4] 00c12403 : lw         r08,r02,0x00c        r02=>bfffff98 (bfffffa4)=>000000ff r08<=ffffffff
       109:M:MBar:[000002b8] 01010113 : addi       r02,r02,0x010        r02=>bfffff98 r02<=bfffffa8
       110:M:MBar:[000002bc] 00008067 : jalr       r00,r01,0x067        r01=>00000328 pc<=00000328
       111:M:MBar:[00000328] 20048693 : addi       r13,r09,0x200        r09=>00010000 r13<=00010200
       112:M:MBar:[0000032c] ffff0737 : lui        r14,0xffff0          r14<=ffff0000
<IDE: DataPort(0x000001f0) Load>
<ReadImgFile(Index=0)=>000000b3>
       113:M:MBar:[00000330] 1f072783 : lw         r15,r14,0x1f0        r14=>ffff0000 r15<=00000000
       114:M:MBar:[00000334] 00f4a023 : sw         r09,r15,0x00|r00     r09=>00010000 r15=>00000000 (00010000)<=00000000
       115:M:MBar:[00000338] 00448493 : addi       r09,r09,0x004        r09=>00010000 r09<=00010004
       116:M:MBar:[0000033c] fe969ae3 : bne        r13,r09,0x7f         r13=>00010200 r09=>00010004 pc<=00000330
<IDE: DataPort(0x000001f0) Load>
<ReadImgFile(Index=1)=>00000133>
       117:M:MBar:[00000330] 1f072783 : lw         r15,r14,0x1f0        r14=>ffff0000 r15<=00000000
       118:M:MBar:[00000334] 00f4a023 : sw         r09,r15,0x00|r00     r09=>00010004 r15=>00000000 (00010004)<=00000000
       119:M:MBar:[00000338] 00448493 : addi       r09,r09,0x004        r09=>00010004 r09<=00010008
       120:M:MBar:[0000033c] fe969ae3 : bne        r13,r09,0x7f         r13=>00010200 r09=>00010008 pc<=00000330
<IDE: DataPort(0x000001f0) Load>
<ReadImgFile(Index=2)=>000001b3>
       121:M:MBar:[00000330] 1f072783 : lw         r15,r14,0x1f0        r14=>ffff0000 r15<=00000000
       122:M:MBar:[00000334] 00f4a023 : sw         r09,r15,0x00|r00     r09=>00010008 r15=>00000000 (00010008)<=00000000
       123:M:MBar:[00000338] 00448493 : addi       r09,r09,0x004        r09=>00010008 r09<=0001000c
       124:M:MBar:[0000033c] fe969ae3 : bne        r13,r09,0x7f         r13=>00010200 r09=>0001000c pc<=00000330
<IDE: DataPort(0x000001f0) Load>
<ReadImgFile(Index=3)=>00000233>
       125:M:MBar:[00000330] 1f072783 : lw         r15,r14,0x1f0        r14=>ffff0000 r15<=00000000
       126:M:MBar:[00000334] 00f4a023 : sw         r09,r15,0x00|r00     r09=>0001000c r15=>00000000 (0001000c)<=00000000
       127:M:MBar:[00000338] 00448493 : addi       r09,r09,0x004        r09=>0001000c r09<=00010010

Initial Program Loader とは

IPLとは、CPUがブートしたときに最初に動作するプログラムで、ROMなどの不揮発性の媒体に格納されている。

CPUが起動すると、まずこのIPLを実行する。IPLはディスクの特定の場所からOSのイメージをロードし、メインメモリに転送する。 OS起動用のプログラムがメインメモリに格納されると、OSプログラムのブートアドレスにジャンプし、OSの起動が開始するという訳だ。

とりあえず、ここまではうまくいったようだ。RISC-V版で、xv6が起動するまで、頑張ろう。