概要
- RISC-V向けに最小限のタイムシェアリングOSカーネルのPoCをZigで実装した事例紹介
- 低レベルなシステムソフトウェアやドライバ、システムコールの基礎理解を目的とした内容
- Unikernel構成・OpenSBIを利用したSBI層・スレッド仮想化の実装手法を解説
- スタックとレジスタの保護、割り込みによるスレッド切り替えなどの実装詳細
- 学生やシステムソフトウェア学習者に有用な、現代的RISC-Vアーキテクチャへの実践的アプローチ
RISC-V向け最小タイムシェアリングOSカーネルPoCの実装
- GitHubリポジトリ で最終コードを公開、記事中でもコードを参照
- ターゲット読者 はシステムソフトウェアやコンピュータアーキテクチャを学ぶ学生やエンジニア
- モダンなRISC-Vアーキテクチャ とZig言語による実装実験
- Zigはセットアップが容易で再現性が高い利点
- 従来のC言語 ではなく Zig を採用し、クロスコンパイルや環境構築の手間を削減
推奨事前知識・参考文献
- レジスタ・メモリアドレス・割り込み などの基本アーキテクチャ知識
- 推奨参考文献
- Bare metal programming on RISC-V
- RISC-V boot process with SBI
- RISC-V interrupts with a timer example
- (オプション) Making a micro Linux distro
Unikernelアプローチ
- Unikernel とは、アプリケーションコードとOSカーネルを一体化した単一バイナリ構成
- ユーザコードを実行時に個別ロード不要
- リンカやローダの複雑さを回避
SBI層と権限モード
- RISC-Vの権限モード
- M-mode: フルアクセスのベアメタル
- S-mode: OSカーネルが動作
- U-mode: アプリケーションコードが動作
- OpenSBI を利用し、コンソール出力やタイマ制御を実現
- SBI層を使うことで移植性向上
カーネルの目標
- スレッドの静的定義 (実行前に固定、動的生成なし)
- スレッドは無限ループ関数 として実装
- ユーザモードスレッド がSモードカーネルにシステムコール可能
- タイムスライス方式 でスレッド切り替え
- シングルコア マシンを対象
スレッドと仮想化の基礎
- スレッド とは、単一コアで複数ワークロードを同時に動かすための抽象
- 協調型スケジューリング (YIELDを明示的に呼ぶ)と タイムシェアリング (割り込みで自動切り替え)の違い
- 仮想化 :各スレッドが独自のコアを持つような錯覚を実現
- 各スレッドは独自の アーキテクチャレジスタ (x0-x31, CSR等)と スタック を持つ
スタック・メモリ仮想化
- スレッドごとに独立したスタック を割り当て
- メモリは基本的に共有だが、スレッド/プロセス/コンテナ/VMのように仮想化レベルを選択可能
- Linuxカーネルも“コンテナ”という明示的構造は持たず、chrootやcgroups等の仕組みを組み合わせて実現
スレッド仮想化の実装方針
- レジスタの保護 :他スレッドからの不正アクセス防止
- 独立スタック :関数呼び出し時の局所変数・戻りアドレス保持
- プログラミングモデル はほぼ変更不要
割り込みコンテキストとタイムシェアリング
- 割り込みハンドラ によりスレッド切り替えを実現
- 割り込みハンドラのプロローグ/エピローグで レジスタ保存/復元 を実装
- 例:RISC-V Sモードタイマ割り込みルーチン
- 割り込みは“システム効果で呼ばれる関数”として捉え、 利用レジスタをスタックに退避 し、終了時に復元
この後の実装詳細(アセンブリスタートアップ、I/Oドライバ、S-modeハンドラ、ユーザ空間スレッドなど)は、GitHubリポジトリのコード参照を推奨。 本記事では RISC-Vの低レベルOSカーネル構築の基礎概念と設計方針 を重点的に解説。