さいきん QEMU RISC-V virt マシンで何ができるか色々探していたところ、なんと VGA が使えることがわかったので記事を書きます。
最新の RISC-V で古き良き VGA が動いてるのが面白いだけです。実用性はあまりありません。笑
解説
qemu で virtio-vga を使うと PCI デバイスが生えてきますが、実は本来の virtio の機能のほかに PCI VGA の機能もあります。
そもそも RISC-V で PCI デバイスにアクセスする方法ですが、 DeviceTree から /soc/pci
を探し、 pci-host-ecam-generic
というプロトコルを使ってコンフィグレーションレジスタにアクセスできます。*1
本来はここで PCI デバイスの列挙が必要ですが、 QEMU は固定値っぽいので省略してアドレス 0x3000_8000 から始まる PCI コンフィグレーションレジスタで virtio-vga にアクセスできます。
QEMU RISC-V のファームウェアでは全く設定されていないようなので BAR とコマンドレジスタを自力で設定する必要があります。 サンプルでは適当なアドレスで決め打ちします。
https://github.com/neri/riscv-vga-sample/blob/main/src/main.rs#L22
BAR の設定が終わったらいよいよ VGA の設定をします。 通常の VGA は I/O アドレス 0x3C0〜に主要な機能がありますが、 virtio-vga では BAR2 の MMIO + 0x400 〜の MMIO レジスタとして実装されています。 これをうまく設定すると VGA として動きます。
ここではみんな大好き 320x200 8bit カラーのモード13hと同じ設定をします。
https://github.com/neri/riscv-vga-sample/blob/main/src/vga.rs
設定が終わったら embedded-graphics の DrawTarget として動作するラッパークラスを作ります。
https://github.com/neri/riscv-vga-sample/blob/main/src/main.rs#L99
これで簡単に画面が表示できました。
しかし、よく考えてください。 解像度 320x200 8bit カラーしか使えない VGA より、普通の virtio-vga として使った方がもっと広くて綺麗な画面が使えます。 それとも 640x480 の 4bit プレーンがお好みですか?そんなわけありませんよね。
いかがでしたか?
調べてみたけどあまり役に立ちませんでした。 多分これが一番無駄だと思います。