次世代のオペレーティングシステムアーキテクチャ「SASOS(単一アドレス空間OS)」をRustでゼロから構築するプロジェクト、PangeaOS。
従来のOS(LinuxやWindows)が抱える、MMU(メモリ管理ユニット)による重いコンテキストスイッチのオーバーヘッドを完全に排除し、すべてのタスクをRing 0の特権レベルで動作させるという野心的なアプローチを取っています。我々はすでに、UEFIブートローダの境界を越え、ベアメタル環境における物理メモリの完全な支配、動的メモリ(ヒープ)の復活、そして独自のGUIフレームバッファ描画基盤を確立しました。
しかし、SASOSが直面する最大の壁は「セキュリティ」にあります。すべてのコードがRing 0で動く環境下において、出所不明のサードパーティ製アプリケーションをいかにして安全に実行するのか。Rustコンパイラの型システムだけに依存するのではなく、より絶対的な防壁が必要です。
その究極の解が、WebAssembly(Wasm)を用いたSoftware Fault Isolation(SFI)のカーネルへの統合です。
OS内にWebAssemblyのコンパイラをゼロから実装するという作業は、「OS開発そのものと同じか、それ以上の規模を持つ別の巨大プロジェクトを同時に走らせる」ことを意味します。コード行数にして、最低でも数万行〜10万行クラスの極めて複雑なコンパイラ・エンジニアリングが必要です。
今回は、PangeaOSが挑むこの「巨大な作業」の正体を4つの技術的障壁として具体的に分解し、SASOS完成に至るまでの現実的な開発ロードマップを公開します。
1. 仮想マシン命令からx86_64機械語への変換(バックエンド生成)
Wasmのスタックマシンアーキテクチャから、実機のx86_64レジスタマシンへ変換する完全なAOTコンパイラエンジンを自作するフェーズです。
具体的に実装すべきタスク(数十のモジュール開発):
Wasmバイナリパーサーの実装: .wasm ファイルの仕様(マジックナンバー、セクション構造、型シグネチャ、インポート/エクスポート定義)をバイト単位でデコードする処理。
中間表現(IR)の構築: Wasmの命令を、最適化しやすいSSA(静的単一代入)形式の内部グラフに変換するモジュール。
レジスタ割り当てアルゴリズム(Register Allocator): 無限にあるWasmのローカル変数を、限られた16個のx86_64汎用レジスタ(RAX, RBXなど)にどう割り当てるか、あるいはスタックに退避(Spill)させるかを計算するグラフ彩色アルゴリズムの実装。
命令ロワリング(Instruction Lowering): Wasmの i32.add などの抽象命令を、x86_64の add eax, ebx にマッピングする変換テーブルの作成。
x86_64アセンブラ(Emitter)の自作: アセンブリ言語を最終的な16進数の機械語(マシンコード)に変換するエンコーダ。ModR/Mバイト、SIBバイト、REXプレフィックスのビット演算をすべて手書きで実装。
関数プロローグ/エピローグの生成: System V AMD64 ABIに従い、関数呼び出し時にスタックポインタ(RSP)やベースポインタ(RBP)を退避・復元する機械語の自動挿入。
リロケーション(Relocation)処理: 事前には分からない関数やグローバル変数のメモリアドレスを、バイナリ生成後に機械語の中に書き戻す(リンクする)処理。
2. ソフトウェア境界チェックの強制(Sandboxing)
ユーザーが書いたWasmコードが、PangeaOSのカーネル領域(ページテーブルやIDT)を破壊しないための「絶対的な檻」を機械語レベルで構築するフェーズです。
具体的に実装すべきタスク(極度の最適化とセキュリティ機構):
線形メモリ(Linear Memory)の確保: Wasmモジュールごとに、専用の仮想アドレス空間(例: 4GBの連続領域)をページテーブル上で割り当てるメモリアロケータの実装。
インライン境界チェック(Inline Bounds Checking): AOTコンパイル時、すべての load / store 命令の直前に、対象アドレスが線形メモリの上限を超えていないかを判定する cmp と jl(ジャンプ)命令を自動挿入する機構。
ハードウェア支援ページフォールトの統合: インラインチェックによる速度低下を防ぐため、線形メモリの末尾にアクセス不可能な「ガードページ(Guard Pages)」を配置し、不正アクセスをIDT(割り込みハンドラ)の PageFault でキャッチしてWasmトラップに変換する高度なMMU連携。
制御フロー完全性(CFI: Control Flow Integrity)の強制: call_indirect(関数ポインタ呼び出し)が実行される際、ジャンプ先のアドレスが正しい型の関数であるかを、実行時に機械語レベルで検証する安全機構の埋め込み。
実行スタックの分離: Wasmのコールスタック(関数呼び出しの履歴)と、x86_64のネイティブスタック(ハードウェアが使うスタック)を物理的に分離し、スタックオーバーフローによるカーネルパニックを防ぐ機構。
3. no_std 環境の罠(OSエコシステムからの孤立)
既存のWasmランタイム(Wasmtimeなど)が依存している「当たり前の機能」を、ベアメタル環境で自前で提供するフェーズです。
具体的に実装すべきタスク(標準ライブラリの再発明):
カスタム mmap 代替アーキテクチャ: 既存エンジンのメモリ確保(OSへの mmap システムコール)を剥がし、PangeaOSの FrameAllocator と PageTable を直接操作して仮想メモリを割り当てるバックエンドに差し替え。
例外処理(シグナル)のカーネルレベル実装: ゼロ除算や不正メモリアクセスが発生した際、Linuxの SIGSEGV や SIGFPE の代わりに、PangeaOSの割り込みハンドラ(IDT)から直接Wasmの実行コンテキストを安全に終了させる状態回復処理(Unwinding)の実装。
浮動小数点演算(FPU/SSE/AVX)のコンテキスト管理: Wasm内で小数を計算させる場合、Ring 0内でハードウェアのFPU状態をタスクごとに安全に退避・復元する機構(fxsave / fxrstor)の実装。
4. ABIとホスト関数のバインディング(越境通信)
隔離されたWasmの世界から、PangeaOSのネイティブ機能(画面描画など)を安全に呼び出すための「検問所」を構築するフェーズです。
具体的に実装すべきタスク(セキュアなシステムコールの設計):
WASI (WebAssembly System Interface) のサブセット実装: WasmがOSの機能を呼ぶための標準インターフェース(画面出力、時刻取得など)のPangeaOS版実装。
ポインタの安全な翻訳機構: Wasmから渡される「メモリオフセット(例: 0x100)」を、カーネルの実際の仮想アドレス(例: 0x4444_4444_0100)に加算して変換するブリッジ機能。
越境メモリアクセスの完全なサニタイズ: Wasmが「長さ 0xFFFF_FFFF の文字列を描画して」と要求してきた場合、カーネル領域へのバッファオーバーリードを防ぐための厳格な引数検証(サニタイズ)ロジック。
ケイパビリティの動的検証: ホスト関数(カーネルAPI)が呼び出された際、そのWasmモジュールが「画面描画の許可トークン(Capability)」を持っているかを検証するアクセスコントロールマネージャ。
現実的な段階的アプローチの詳細
これらを一度に作ろうとすると、OSが完成する前に確実に息絶えます。以下が、Ring 0でWasmを動かすための現実的なロードマップです。
フェーズ 1(現在の目標): 静的リンクによる純粋なSASOS
Wasmはまだ使いません。OSの全機能とアプリケーションを、Rustのコンパイラで一つの巨大なバイナリとしてコンパイルします。画面描画、キーボード入力、タスク管理といった「OSとしての基本機能」と「ケイパビリティを用いた型安全なAPI」の基礎をここで完成させます。
フェーズ 2: Wasmインタープリタの移植(AOTの回避)
AOTコンパイラを作るのは後回しにします。wasmi のような no_std で動く軽量な「インタープリタ(実行時に1命令ずつ解釈するエンジン)」をカーネルに組み込みます。実行速度は劇的に遅いですが、SFI(ソフトウェア境界)の概念と、ホスト関数(ABI)の連携テストを安全に行うことができます。
フェーズ 3: JIT / AOTコンパイラの自作
フェーズ2でインターフェースが固まった後、満を持して「1.」の機械語生成バックエンドの開発に取り掛かり、実行速度をネイティブレベルまで引き上げます。
PangeaOSの現在のフェーズでは、強固な基礎を作ることが最優先です。Wasmの巨大な壁に挑む前に、まずは「ケイパビリティ(権限の型安全化)」を用いた美しいアーキテクチャで、入出力を制御する強固なRing 0環境の構築を進めていきます。
