自作CPU & 自作OSをやっていく (2) - 64ビットRISC-Vの "Hello World" をRustで作った

2020年1月から、趣味エンジニアリング活動として自作CPUと自作OSをやっていく。

今回は、64ビットRISC-V (RV64I) の “Hello World” をRustで作ったので、そのリポジトリの紹介。

自作CPU & 自作OS タグで、この前後の進捗とか目指しているもの(初回記事)とかを追えるようにしている。

冒頭にも貼ったが、

のリポジトリに公開している。READMEに全部書いてあるが、特徴を抜粋すると

  • Dockerfile を書いているので、面倒なコンパイラツールチェインなどのインストールを自前でしないで良い。
  • 64ビットなRISC-Vターゲットへコンパイルされる(世のサンプルは32ビット版が多いのでちょっと参考になるかも)。
  • RustのStableビルドを使う。Nightlyビルドは使わない。
  • xargo を使わず cargo を使う。
  • Visual Studio Codeを使う人なら、Remote Development Containerで走るように設定ファイルを同梱している。

あたり。

参考にさせていただいた RustでRISC-V OS自作!はじめの一歩 とファイル構成は同じなので、比較しながら読めば十分に挙動は追えるはず(解説をサボった)。こちらの記事との差分は、

  • 64ビット版であること。
  • QEMUで -machine sifive_u ではなく -machine virt を使った。それに伴いUARTのアドレスが 0x10013000 から 0x10000000 に変わった。
  • リンカスクリプトで無駄を省いたりコメント追加したりした。あと MEMORY コマンドを使った(と言っても定義して実際に使ったのはRAMだけだが…)。
  • boot.s で、スタック領域を確保するときに la アセンブリ疑似命令を使うようにした。

あたり。

苦労したこと・学んだこと

  • RustのStableビルドで勝負するなら、インラインアセンブリが使えないので、生アセンブリファイルを書く必要がある。
  • 生アセンブリファイルを書いた瞬間に、RISC-V用のコンパイラツールチェイン が必要になる。アセンブリファイルのアセンブルのため、その結果のオブジェクトファイルを rustc でコンパイルした別のオブジェクトファイルとリンクするため。
    • rustc がバックエンドに使ってるLLVMでRISC-V用のオブジェクトファイル生成もリンクもできているわけなので、本来的には不要なはず。 build.rs をもっと上手に書けば不要にできるのか…?🤷
  • QEMUのバージョンの違いで “Hello World” が出力されたりされなかったり…
  • スタック領域確保、64ビットにした途端に動かなくなった…
  • リンカスクリプト何もわからん状態だったが、 リンカスクリプトの書き方 読んでだいぶ分かるようになった気がするありがたい。
  • SiFiveはRISC-Vクロスコンパイル用のビルド済みgccもqemuを提供してくれていてとてもありがたいけど、Ubuntu 14.04前提なのが厳しかった。特に riscv64-unknown-elf-gdbqemu-system-riscv64 起動に必要な動的ライブラリの適切なバージョンを引っ張ってくるので地獄を見た(最初は rust dockerイメージで頑張ってたけど匙投げて ubuntu:14.04 使うようにしてから苦行程度に落ち着いた)。
author Sho Nakatani a.k.a. laysakura

トヨタ自動車株式会社所属。プリンシパル・リサーチャーとして、セキュリティ・プライバシー・データ基盤に関する業務に従事。
OSCP/BSCP/CISSP/情報処理安全確保支援士(合格) 等の資格保有。CTF出場やセキュリティ関連の講演活動も行っている。
詳細プロフィール