引き続き、RISC-Vにxv6を移植するための情報を調査していこう。
initcode.Sは一番最初のプロセスとして実行される。 引数を設定し、システムコールを呼び出す。
RISC-Vにて、システムコールを発生させるには以下の命令を使う。
ecallは、システムコールを発生させ、マシンモードに遷移する。どの例外ベクタに飛ぶかについては、どのモードからecall命令を実行したかに依存している。 まず、mtvecレジスタにベクトルベースレジスタを設定し、それから、以下の表に基づいてベクタアドレスにジャンプする。
まずはRISC-Vの例外ベクタを作成しないといけないのだが、この部分はとりあえず例外ベクタのテンプレートだけ用意しておこう。 ちなみに、ecallを実行すると、mcauseレジスタには以下のようなルールで値が書き込まれる(つまり8)、これで、どこから、何の例外が発生したかを確認するわけだ。
さらに、リンカスクリプトを修正する。現在はi386用になっているが、これをRISC-V用に変更した。
OUTPUT_FORMAT("elf32-littleriscv") OUTPUT_ARCH(riscv)
コンパイルをしていると、_binary_entryother_startや、binary_entryother_sizeがないと怒られる。これは、entryother.Sから来ているものらしいのだが、xv6のマニュアルを読んでも、それらしき説明がない。 いろいろコードを見ていると、スタートアップ時の初期設定をメインのCPUが実行し、それ以外のCPUは待機状態に入る。このためのルーチンらしい。 とりあえずシングルコアで動かす予定なので、この部分は今の時点では実相を省略する。
さらに、usys.Sでは、システムコールを発生させるためのルーチンを定義している。これも、RISC-Vのものに書き換えよう。
#include "syscall.h" #include "traps.h" #define SYSCALL(name) \ .globl name; \ name: \ li x16, SYS_ ## name; \ ecall; \ eret