PetaLinux (rel-v2023.2) をビルドしてQEMUで動かしてみた

# はじめに
AMDが提供するPetaLinuxをビルドし、QEMUで動かしてみました。

# 参考にしたサイト
- https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/821854264/Launching+QEMU+Using+Xilinx+Yocto+toolchains
- https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/821395464/QEMU+User+Documentation

# 構成図
```
+------------------------------------------------------+
| +--------------------------------------------------+ |
| | +----------------------------------------------+ | |
| | | +------------------------------------------+ | | |
| | | | PetaLinux (2023.2)                       | | | |
| | | +------------------------------------------+ | | |
| | | Zynq UltraScale+ MPSoC ZCU102 Evaluation Kit | | |
| | +----------------------------------------------+ | |
| | 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
```
$ ./qemu-system-aarch64 --version 
QEMU emulator version 7.1.0 (v2.6.0-55433-g23b643ba16-dirty)
Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers
```
- QEMUはPetaLinuxビルド時に生成されたqemu-system-aarch64コマンドを使用しました。
  ```
  /home/petalinux/github/petalinux/build/tmp/work/x86_64-linux/qemu-helper-native/1.0-r1/recipe-sysroot-native/usr/bin
  ```

# 前提条件
- repo init時に、GitHubのアカウントが必要になります。事前に作成しておいてください。
- 以降の作業は、自分で作成したpetalinuxというユーザを使用しました。petalinuxユーザにはsudo権限を付与しています。
- petalinuxユーザのホームディレクトリは/home/petalinuxです。以降の作業は/home/petalinux上で行いました。

# 必要なパッケージのインストール
1. 以下のコマンドを実行し、必要なパッケージをインストールしてください。
   ```sh
   sudo apt install -y gcc net-tools xterm autoconf libtool \
   texinfo zlib1g-dev gcc-multilib build-essential ncurses-dev \
   chrpath diffstat lz4
   ```

# PetaLinuxリポジトリのクローン
1. curlコマンドでrepoコマンドを入手してください。
   ```sh
   curl -k https://storage.googleapis.com/git-repo-downloads/repo > repo
   ```
1. repoコマンドに実行権限を付与してください。
   ```sh
   chmod a+x repo
   ```
1. Proxyサーバがある場合、vimコマンドなどで、repoファイルを開き、以下を追記してください。
   ```
   # (snip)
   import sys
   
   # 追加部分
   os.environ['http_proxy'] = '<your proxy server name>:<port number>'
   os.environ['https_proxy'] = '<your proxy server name>:<port number>'
   
   # (snip)
   ```

1. repo initコマンドで初期化を行ってください。
   ```sh
   repo init -u https://github.com/Xilinx/yocto-manifests -b rel-v2023.2
   ```
1. repo syncコマンドで、必要なファイルをダウンロードしてください。
   ```sh
   repo sync
   ```
   - 以下のような実行結果が出力されます。
     ```
     $ repo sync 
     Fetching: 100% (16/16), done in 20.536s
     Checking out:  93% (15/16), done in 0.818s
     repo sync has finished successfully.
     ```

# PetaLinuxのビルド
1. 以下のコマンドを実行し、ビルドのために必要な環境変数を設定してください。
   ```sh
   source setupsdk
   ```
1. bitbakeコマンドでPetaLinuxをビルドしてください。
   ```sh
   MACHINE=zcu102-zynqmp bitbake petalinux-image-minimal
   ```
# PetaLinuxの起動
1. runqemuコマンドで、PetaLinuxをQEMUで起動してください。
   ```sh
   MACHINE=zcu102-zynqmp runqemu petalinux-image-minimal nographic
   ```
   ```
   [    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
   [    0.000000] Linux version 6.1.30-xilinx-v2023.2 (oe-user@oe-host) (aarch64-xilinx-linux-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.39.0.20220819) #1 SMP Fri Sep 22 10:41:01 UTC 2023
   [    0.000000] Machine model: ZynqMP ZCU102 Rev1.0
   (snip)
   ```
1. ユーザpetalinuxでログインすると、初期パスワードの設定が求められますので、パスワードを設定し、ログインしてください。
   ```
   zcu102-zynqmp login: petalinux
   You are required to change your password immediately (administrator enforced).
   New password: 
   Retype new password: 
   ```
   ```
   $ cat /etc/os-release 
   ID=petalinux
   NAME="PetaLinux"
   VERSION="2023.2+snapshot-9b5053b49a808cbb3136c40900da8f9126d46e5e (langdale)"
   VERSION_ID=2023.2-snapshot-9b5053b49a808cbb3136c40900da8f9126d46e5e
   PRETTY_NAME="PetaLinux 2023.2+snapshot-9b5053b49a808cbb3136c40900da8f9126d46e5e (langdale)"
   DISTRO_CODENAME="langdale"
   ```
   ```
   $ uname -r 
   6.1.30-xilinx-v2023.2
   ```

# IPアドレスを有効にする
1. OS起動後はIPv4のアドレスが、eth0に割り当てられていません。
   ```
   $ ip a 
   1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
       link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
       inet 127.0.0.1/8 scope host lo
          valid_lft forever preferred_lft forever
       inet6 ::1/128 scope host 
          valid_lft forever preferred_lft forever
   2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
       link/sit 0.0.0.0 brd 0.0.0.0
   3: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN group default qlen 10
       link/can 
   5: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
       link/ether 36:ae:4f:94:62:7e brd ff:ff:ff:ff:ff:ff
       inet6 fe80::34ae:4fff:fe94:627e/64 scope link 
          valid_lft forever preferred_lft forever
   ```
1. 以下のコマンドを実行し、eth0にIPアドレスを付与してください。
   ```sh
   sudo ip addr add 192.168.7.2/24 dev eth0
   ```
1. 必要に応じて、デフォルトゲートウェイも設定してください。
   ```sh
   sudo ip route add default via 192.168.7.1
   ```

# さいごに
PetaLinux (rel-v2023.2) をビルドして、QEMUでエミュレートしたZynq UltraScale+ MPSoC ZCU102 Evaluation Kitで動かしてみました。


# 付録
- runqemuを実行すると、実際には以下のプロセスが生成されます。
  - 本来は1行ですが、見づらいため改行しています。
```
python3 /home/petalinux/github/petalinux/sources/poky/scripts/runqemu \
petalinux-image-minimal nographic
```
```
python3 /home/petalinux/github/petalinux/build/tmp/work/x86_64-linux/qemu-helper-native/1.0-r1/recipe-sysroot-native/usr/bin/qemu-system-aarch64-multiarch \
-net nic -net nic -net nic -net nic,netdev=net0,macaddr=52:54:00:12:34:02 \
-netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
-drive if=sd,index=1,file=/home/petalinux/github/petalinux/build/tmp/deploy/images/zcu102-zynqmp/petalinux-image-minimal-zcu102-zynqmp.wic.qemu-sd,format=raw \
-hw-dtb /home/petalinux/github/petalinux/build/tmp/deploy/images/zcu102-zynqmp/qemu-hw-devicetrees/multiarch/zcu102-arm.dtb \
-global xlnx,zynqmp-boot.cpu-num=0 \
-global xlnx,zynqmp-boot.use-pmufw=true \
-device loader,addr=0xfffc0000,data=0x584c4e5801000000,data-be=true,data-len=8 \
-device loader,addr=0xfffc0008,data=0x0000000800000000,data-be=true,data-len=8 \
-device loader,addr=0xfffc0010,data=0x1000000000000000,data-be=true,data-len=8 \
-device loader,addr=0xffd80048,data=0xfffc0000,data-len=4,attrs-secure=on \
-device loader,file=/home/petalinux/github/petalinux/build/tmp/deploy/images/zcu102-zynqmp/arm-trusted-firmware.elf,cpu-num=0 \
-device loader,file=/home/petalinux/github/petalinux/build/tmp/deploy/images/zcu102-zynqmp/u-boot.elf \
-device loader,file=/home/petalinux/github/petalinux/build/tmp/deploy/images/zcu102-zynqmp/system.dtb,addr=0x100000,force-raw=on \
-boot mode=5 -pmu-args -M microblaze-fdt -display none \
-hw-dtb /home/petalinux/github/petalinux/build/tmp/deploy/images/zcu102-zynqmp/qemu-hw-devicetrees/multiarch/zynqmp-pmu.dtb \
-kernel /home/petalinux/github/petalinux/build/tmp/deploy/images/zcu102-zynqmp/pmu-rom.elf \
-device loader,file=/home/petalinux/github/petalinux/build/tmp/deploy/images/zcu102-zynqmp/pmu-firmware-zcu102-zynqmp.elf \
-device loader,addr=0xfd1a0074,data=0x1011003,data-len=4 \
-device loader,addr=0xfd1a007C,data=0x1010f03,data-len=4 \
-machine arm-generic-fdt -m 4096 -serial mon:stdio \
-serial null -nographic
```
```
/home/petalinux/github/petalinux/build/tmp/work/x86_64-linux/qemu-helper-native/1.0-r1/recipe-sysroot-native/usr/bin/qemu-system-microblazeel \
-M microblaze-fdt -display none \
-hw-dtb /home/petalinux/github/petalinux/build/tmp/deploy/images/zcu102-zynqmp/qemu-hw-devicetrees/multiarch/zynqmp-pmu.dtb \
-kernel /home/petalinux/github/petalinux/build/tmp/deploy/images/zcu102-zynqmp/pmu-rom.elf \
-device loader,file=/home/petalinux/github/petalinux/build/tmp/deploy/images/zcu102-zynqmp/pmu-firmware-zcu102-zynqmp.elf \
-device loader,addr=0xfd1a0074,data=0x1011003,data-len=4 \
-device loader,addr=0xfd1a007C,data=0x1010f03,data-len=4 \
-machine-path /tmp/tmpwe62lzgn
```
```
/home/petalinux/github/petalinux/build/tmp/work/x86_64-linux/qemu-helper-native/1.0-r1/recipe-sysroot-native/usr/bin/qemu-system-aarch64 \
-net nic -net nic -net nic \
-net nic,netdev=net0,macaddr=52:54:00:12:34:02 \
-netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
-drive if=sd,index=1,file=/home/petalinux/github/petalinux/build/tmp/deploy/images/zcu102-zynqmp/petalinux-image-minimal-zcu102-zynqmp.wic.qemu-sd,format=raw \
-hw-dtb /home/petalinux/github/petalinux/build/tmp/deploy/images/zcu102-zynqmp/qemu-hw-devicetrees/multiarch/zcu102-arm.dtb \
-global xlnx,zynqmp-boot.cpu-num=0 \
-global xlnx,zynqmp-boot.use-pmufw=true \
-device loader,addr=0xfffc0000,data=0x584c4e5801000000,data-be=true,data-len=8 \
-device loader,addr=0xfffc0008,data=0x0000000800000000,data-be=true,data-len=8 \
-device loader,addr=0xfffc0010,data=0x1000000000000000,data-be=true,data-len=8 \
-device loader,addr=0xffd80048,data=0xfffc0000,data-len=4,attrs-secure=on \
-device loader,file=/home/petalinux/github/petalinux/build/tmp/deploy/images/zcu102-zynqmp/arm-trusted-firmware.elf,cpu-num=0 \
-device loader,file=/home/petalinux/github/petalinux/build/tmp/deploy/images/zcu102-zynqmp/u-boot.elf \
-device loader,file=/home/petalinux/github/petalinux/build/tmp/deploy/images/zcu102-zynqmp/system.dtb,addr=0x100000,force-raw=on \
-boot mode=5 -machine arm-generic-fdt -m 4096 \
-serial mon:stdio -serial null -nographic \
-machine-path /tmp/tmpwe62lzgn
```