世界を動かす技術を、日本語で。

自作のCPUと自作のCコンパイラでUnix系OS Xv6を動作させました

概要

  • 東京大学の情報科学科で行われた CPU実験プロジェクト の体験談
  • 独自ISA設計、FPGA上へのCPU実装、Cコンパイラ開発、 Xv6 OS移植 の挑戦
  • 学生主体の学習と開発が求められる 高度な課題設定
  • Xv6移植に伴う 技術的課題 とその解決プロセス
  • 実験の進行とチームの協力による 成果と学び

東京大学「CPU実験」体験記:自作CPUとOS移植の挑戦

  • 東京大学情報科学科の 冬季学生実験「CPU実験」 での体験談
  • 学生4~5人のグループで 独自CPUアーキテクチャ設計 ・FPGA実装・OCamlサブセットコンパイラ作成・レイトレーシングプログラム実行
  • 担当分野分担(CPU、FPU、シミュレータ、コンパイラ)による 協働開発
  • 教員からは「このOCaml製レイトレーシングプログラムを自作CPUで動かせ」という シンプルな指示 のみ
  • 学生の 自主学習力・実装力 が強く試される課題設定

OS移植への挑戦とXv6の選択

  • 実験の基本目標(CPU完成・レイトレーシング実行)達成後は 自由課題 に移行
  • 過去にはアウトオブオーダーCPUやマルチコアCPU、ゲーム実装など 多様な発展課題
  • 筆者のグループ6は 「自作CPUでOSを動かす」 を目標に設定
  • 複数グループ合同の Group X (約8名)を結成し、OS移植プロジェクトを開始
  • 移植対象OSは MIT製教育用Unix互換OS「Xv6」 を選択

Xv6移植で直面した技術課題

  • Cコンパイラとツールチェイン :CPU実験ではMLコンパイラが主流でCコンパイラは未整備
  • OSに必要なCPU機能 :特権保護、仮想アドレス、割り込みなどの具体要件の理解不足
  • シミュレータの機能不足 :割り込み・仮想アドレス変換未対応の簡易シミュレータ
  • Xv6の低移植性 :char=1バイト、int=4バイト前提やスタック操作依存などx86依存仕様

Cコンパイラ「Ucc」開発とOSチーム発足

  • 当初はgccやllvm移植を検討も、 独自C89コンパイラ開発 を決断
  • Keiichiのプロトタイプを基に、Yuichi・Wataruらも加わり 「Ucc」 開発チーム結成
  • 筆者はCPU完成後、Shohei・Masayoshiと共に OS移植チーム を始動

CPU実装とHDL開発の実際

  • ハードウェア記述言語(HDL) によるCPU回路設計
  • VivadoやQuartusで 論理合成 を行い、実回路化
  • HDLはプログラミング言語に似るが 信号状態遷移の記述 が本質
  • 論理合成には 長時間(30分以上) かかることも多く、合成待ちの間にSmash Bros. Melee対戦で息抜き

Xv6のMIPS移植とOS要件理解

  • Xv6ソース読解・MIPS移植を通じて 割り込み・MMU実装の仕組み を実装レベルで理解
  • UccもXv6の大半を コンパイル可能な段階 に成長
  • シミュレータ上でXv6の 起動メッセージが表示 されるまで進捗

独自CPU「GAIA」設計とOS移植本格化

  • 割り込み・仮想アドレス変換の仕様策定
  • ハードウェア特権機構(Ring保護) は簡略化し、仮想アドレス変換はx86同様の ページウォーク方式 を採用
  • YuichiがISA設計・CPUコア実装、CPU名は GAIA に決定
  • シミュレータに 割り込み・仮想アドレス変換機能 を追加し、OS実行環境を整備

デバッグ・移植の苦労と進展

  • 独自リンカの作成や割り込みハンドラ実装など 地道な開発作業
  • シミュレータに デバッガ・ダンプ機能 を追加し、デバッグ効率化
  • Uccのchar=32ビット問題でXv6との非互換が発生し、 char=8ビット対応 へ仕様変更
  • ページング初期化・割り込み動作確認など、 Xv6の移植性課題 を克服

まとめ・学び

  • 自作CPU・独自OS移植 を通じて、CPU・OS・コンパイラ・ハードウェア・デバッグ技術を実践的に習得
  • 自主性・チームワーク・問題解決力 の重要性を実感
  • 東京大学「CPU実験」は 極めて教育効果の高い実践型課題 であり、ソフトウェアエンジニアとしての礎となる体験

Hackerたちの意見

(2020)

以前のリンク: https://news.ycombinator.com/item?id=24680109

大学時代にやった3人での3週間のグループプロジェクトを思い出すなぁ。選べるトピックがいくつかあって、その中には非常にシンプルなオペレーティングシステムをゼロから作るっていうのもあったんだ。教授に、MINIX3をRaspberry Piにポートすることはできないかって聞いたら、(BeagleBoardにARMポートがあったから)OKしてくれたんだよね。最初は割と簡単なプロジェクトのはずだったのに、予想外の技術的な問題がたくさん出てきて、すごく大変だった。一番厄介だったのは、Raspberry Pi 3がスーパーバイザーモードじゃなくてハイパーバイザーモードで起動しちゃったこと。QEMUのRaspberry Piエミュレーションの精度も当時はひどくて、OS開発にはほぼ役に立たなかったんだ。これを解決するのに、低レベルのハードウェアデバッグに1週間もかかったのを覚えてる。最終的には、Raspberry Pi 2と3で動作するUART、GPIO、フレームバッファドライバを持つ動作するポートを完成させたよ。実際のハードウェアでポートを使ってプレゼンを行ったんだけど、ramdiskからビットマップを表示して、スライドを前後に移動させるためにGPIOピンを監視するシェルスクリプトを使ったんだ(必要に応じてナイフでピンをショートさせてた)。オリジナリティだけで言えば、グループの中で一番クールなプレゼンだったと思うし、そのSDカードの画像はまだどこかに残ってるはず。

いいね。

教授に、MINIX3をRaspberry Piに移植できないか聞いたら、失敗すると思ってたみたい。 QEMUのRaspberry Piエミュレーションの精度はひどかったからね。趣味でOS開発してた時は、まずQEMUで動かして、それから実際のハードウェアでも動くことを祈ってたけど、まあまあうまくいったよ。実際のハードウェアでRaspberry Piのデバッグはどうやってやったの?

必要に応じてピンをショートさせるためにナイフを使った。 ATXマザーボードの電源オンピンをショートさせて、スイッチなしで起動させるのを思い出したよ。もちろん、君のセットアップの方がずっとクールだったけど。いい仕事だね。

すごいね!低レベルの作業は、特にデバッガーみたいな基本的なツールがないと、めっちゃ面倒で時間がかかるからね。

バグのあるkprintfをデバッグするためにオシロスコープを使ったことがないなら、まだ本当の意味で生きてないよ。

25~30年前にSFUでこんなことやったなぁ。ただ、OSやコンパイラを動かすところまではいかなかったし、グループプロジェクトじゃなかったけど。こういう実験をやってみたいけど、ガイダンスや使いやすいツールが欲しい人には、Turing Completeを超おすすめするよ。ゲートからフルコンピュータまで進化できるから。コンポーネントはコミュニティと共有できて、RiscVコアみたいなものも見つかるよ。とにかく、すごく楽しい。おすすめだよ。Steamで買えるよ: https://store.steampowered.com/app/1444480/Turing_Complete/

それ、nand2tetrisのゲーム版みたいだね。前にやって楽しかったよ(別の提案として)。

Magic-1とBMOWも似たようなことをやってたよ。詳しくはここを見てね: https://www.homebrewcpu.com/ 自分のCPUを作ったサイトのリスト: https://www.homebrewcpuring.org/

CPUとコンパイラ、OSを一緒に作ると、下にプラットフォームがないんだよね。自分がプラットフォームになる。遭遇するバグは全部、自分のシステムの法則なんだ。ほとんどの人は、他の誰かが書いたレイヤーをデバッグするけど、ここではルールすら自作だもんね。OPは自分のルールをデバッグしたんだ。

これから半導体ラボに走って、CPUを作ってもらわないといけないね。FPGAを設定するんじゃなくて。