設計
GCCの呼び出し規約を参考にしてシステムコールの呼び出し規約を定義する。
GCC(ルネサス?)の呼び出し規約
R0:返却値
R1からR3:空
R4からR7:引数
R8からR13:呼び出し先が退避する
R14:フレームポインタ、呼び出し先が退避する
R15:スタックポインタ
PR:サブルーチンの戻りアドレス
参考1:gcc/config/sh/sh.h
参考2:http://www.ertl.jp/~takayuki/readings/info/no04.html
呼び出し規約
第一引数:R4
第二引数:R5
第三引数:R6
第四引数:R7
第五引数:R1
第六引数:R2
第七引数:R3
第八引数:R9
システムコール番号:R8
返却値:R0
ユーザプログラムはR8にシステムコール番号を格納し、TRAPA命令を発行する。システムコールの引数は指定のレジスタを介して渡される。システムコールは8個までの引数を取ることが出来る。
TRAPAはイミディエイトオペランドを持つので、このオペランドを使ってシステムコール番号を指定することも可能だ。
TRAPA
PC+2、SR、R15の値をSPC、SSR、SGRに退避し、イミディエートデータをTRAレジスタに格納する。処理モードを特権モードに切り替え、BANK1レジスタを選択し、例外コード0×160をEXPEVTレジスタに書き込む。処理は例外ハンドラに分岐する。
システムコールの流れ
ユーザー側の処理(呼び出し前)
・前提:以下の処理は関数の先頭で行う。(R4からR7以外は自由に使える状態であること)
・スタックから第五引数から第八引数をR0からR3に格納する。
・R8にシステムコール番号を格納する
・TRAPAを発行する。
・R10からR14は使わない
カーネル側の処理
・TCBにシステムレジスタを退避する
・カーネルスタックに切り替える
・バンク1からバンク0に切り替える(ユーザーのレジスタに切り替える)
・R0からR3をスタックに格納する
・コンティニュエーションをPRに格納
・システムコールを呼び出す
コンティニュエーション
・TCBからシステムレジスタを復帰する
・ユーザースタックに切り替える
・RTEを発行する
ユーザー側の処理(呼び出し後)
・呼び出し元に戻る。
コンティニュエーションの利用
カーネルスタックの管理を簡単にするためにL4はコンティニュエーションを多用している。
IPCの最適化
マイクロカーネルのシステムで最も大きなボトルネックとなるのがIPCである。たとえば、モノリシックカーネルではサブシステム間のコンテキストスイッチが起きない。それに対し、マイクロカーネルではサブシステムがユーザレベルのプロセスとして動くのでサブシステム間でコンテキストスイッチが起こる。サブシステムを細かく分割すれば安全性は高まるが、より多くのIPCが発生し、結果としてシステムの性能は低下する。
IPCはシステムコールであるが、トラップハンドラ内でIPC専用のパスを用意することで最適化する。