Raspberry Pi 4をQEMUで動かしてみた on Ubuntu Server 20.04

# はじめに
QEMU 9.0.0から[Raspberry Pi 4がサポートされた](https://www.qemu.org/2024/04/23/qemu-9-0-0/)ので試してみました。

# 構成図
```
+-----------------------------+
| +-------------------------+ |
| | +---------------------+ | |
| | | +-----------------+ | | |
| | | | Raspberry Pi OS | | | |
| | | +-----------------+ | | |
| | | Rapsberry Pi 4      | | |
| | +---------------------+ | |
| | QEMU                    | |
| +-------------------------+ |
| Ubuntu Server               |
+-----------------------------+
```

# 各ソフトウェアのバージョン
## Ubuntu Server
```
$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.6 LTS"
```

## QEMU
- 以下からソースコードをダウンロードし、ビルドしました。
  - https://download.qemu.org/qemu-9.0.0.tar.xz
- 筆者の環境では、複数のバージョンのqemu-system-aarch64をインストールしているため、コマンド名の末尾にバージョンをつけています。
  ```
  $ qemu-system-aarch64-9.0.0 --version 
  QEMU emulator version 9.0.0
  Copyright (c) 2003-2024 Fabrice Bellard and the QEMU Project developers
  ```
  ```
  $ qemu-system-aarch64-9.0.0 -M help |grep raspi
  raspi0               Raspberry Pi Zero (revision 1.2)
  raspi1ap             Raspberry Pi A+ (revision 1.1)
  raspi2b              Raspberry Pi 2B (revision 1.1)
  raspi3ap             Raspberry Pi 3A+ (revision 1.0)
  raspi3b              Raspberry Pi 3B (revision 1.2)
  raspi4b              Raspberry Pi 4B (revision 1.5)
  ```

## Rapsberry Pi OS
- 2020-08-20-raspios-buster-arm64
  - https://downloads.raspberrypi.org/raspios_arm64/images/raspios_arm64-2020-08-24/
  - 2024-03-15-raspios-bookworm-arm64.imgでも後述の手順を試してみたのですが、起動処理が進まない事象が発生しています。
    ```
    $ ./run.sh 
    qemu-system-aarch64-9.0.0: warning: bcm2711 dtc: brcm,bcm2711-pcie has been disabled!
    qemu-system-aarch64-9.0.0: warning: bcm2711 dtc: brcm,bcm2711-rng200 has been disabled!
    qemu-system-aarch64-9.0.0: warning: bcm2711 dtc: brcm,bcm2711-thermal has been disabled!
    qemu-system-aarch64-9.0.0: warning: bcm2711 dtc: brcm,bcm2711-genet-v5 has been disabled!
    （以降、何も出力されない）
    ```

# 手順
1. Raspberry Pi用のファイルを保存するディレクトリ (e.g., /home/user/raspi4) を作成します。
   ```sh
   mkdir -p /home/user/raspi4
   ```
1. Raspberry Pi OSのイメージをダウンロードします。
   ```sh
   cd /home/user/raspi4
   ```
   ```sh
   wget https://downloads.raspberrypi.org/raspios_arm64/images/raspios_arm64-2020-08-24/2020-08-20-raspios-buster-arm64.zip
   ```
1. ダウンロードしたファイルを解凍します。
   ```sh
   unzip 2020-08-20-raspios-buster-arm64.zip
   ```
1. イメージファイル2020-08-20-raspios-buster-arm64.imgをループバックマウントします。
   ```sh
   sudo losetup --show -fP 2020-08-20-raspios-buster-arm64.img
   ```
   - ループバックマウントが成功すると、以下のようにデバイス名が表示されます。デバイス名は環境によって異なります。
     ```
     /dev/loop6
     ```
1. 上記デバイス上のパーティション/dev/loop6p1を任意のディレクトリ (e.g., /mnt/tmp) にマウントします。
   ```sh
   sudo mkdir /mnt/tmp
   ```
   ```sh
   sudo mount /dev/loop6p1 /mnt/tmp/
   ```
1. 以下の2つのファイルを/hoem/user/raspi4にコピーします。
   ```sh
   cp /mnt/tmp/bcm2711-rpi-4-b.dtb /home/user/raspi4
   ```
   ```sh
   cp /mnt/tmp/kernel8.img /home/user/raspi4
   ```
1. 該当のデバイスをアンマウントします。
   ```sh
   sudo umount /mnt/tmp
   ```
   ```sh
   sudo losetup -d /dev/loop6
   ```
1. 仮想マシンを起動するためのシェルスクリプトrun.shを作成します。
   ```sh
   cd /home/user/raspi4
   ```
   ```sh
   touch run.sh
   ```
   ```sh
   chmod +x run.sh
   ```
   ```sh
   vim run.sh
   ```
   ```
   qemu-system-aarch64-9.0.0 \
   -m 2048 \
   -M raspi4b \
   -kernel kernel8.img \
   -dtb bcm2711-rpi-4-b.dtb \
   -drive format=raw,file=2020-08-20-raspios-buster-arm64.img \
   -append "root=/dev/mmcblk1p2 rw rootwait rootfstype=ext4 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 earlyprintk" \
   -no-reboot \
   -device usb-kbd \
   -device usb-mouse \
   -nographic
   ```
   - [Raspberry Pi 3の時](https://qiita.com/fukunagt/items/879758258ae1da188721#%E6%89%8B%E9%A0%86)と異なり、デバイス名が`root=/dev/mmcblk1p2`となっています。
1. run.shを実行してください。
   ```sh
   ./run.sh
   ```
1. Enjoy!
   ```
   $ ./run.sh 
   [    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd083]
   [    0.000000] Linux version 5.4.51-v8+ (dom@buildbot) (gcc version 5.4.0 20160609 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9)) #1333 SMP PREEMPT Mon Aug 10 16:58:35 BST 2020
   [    0.000000] Machine model: Raspberry Pi 4 Model B
   (snip)

   Debian GNU/Linux 10 raspberrypi ttyAMA0

   raspberrypi login:    
   ```
   - ユーザ名pi、パスワードraspberryでログインしてください。

# さいごに
ネットワークがまだ使えない状態ですが、Raspberry Pi OSを起動することに成功しました。

- https://wiki.qemu.org/ChangeLog/9.0
  - raspi4b : the Raspberry Pi 4 Model B. Note that QEMU does not yet model PCI or ethernet; we hope to implement those devices for the next QEMU release.

なお、[QEMU 9.1.0](https://qiita.com/fukunagt/items/a8cf4f4cd113f24bd2be)でも同様の手順を試しましたが、まだネットワークが使えないようです。
```
qemu-system-aarch64-9.1.0 \
-m 2048 \
-M raspi4b \
-kernel kernel8.img \
-dtb bcm2711-rpi-4-b.dtb \
-drive format=raw,file=2020-08-20-raspios-buster-arm64.img \
-append "root=/dev/mmcblk1p2 rw rootwait rootfstype=ext4 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 earlyprintk" \
-no-reboot \
-usb \
-device usb-kbd \
-device usb-mouse \
-device usb-net,netdev=net0 \
-netdev tap,id=net0,ifname=tap0,script=no \
-nographic
```