Ubuntu20.04@x86_64のLinuxKVM上にaarch64のUbuntu20.04仮想マシンを立てる

# 1. はじめに
- armの組込ボードをターゲットとしたソフトウェア開発をしていると、たくさんarmボードが欲しくなりますが、場所を食うし、お金もかかります。
  - 素直にラズパイとかのシングルボードコンピュータを大量に買うのがいいかもですが。
- 仮想環境として簡単に一元管理できるといいな、と思ったので、armの模擬環境を仮想マシンで立られるか検証してみました。

# 2. 参考資料
- [仮想 Arm64 マシンの作り方](https://www.mztn.org/dragon/arm64_01.html)
  - 本記事の実施事項の前半はこちらのサイトの内容をUbuntu20.04で再実施したものとなります。
- [ローカルインストール時もcloud-initを活用する](https://gihyo.jp/admin/serial/01/ubuntu-recipe/0561?page=1)
  - arm版Ubuntu20.04をcloud-initを用いてインストールするときに参考にしました。
- [KVM をインストールして設定する](https://qiita.com/tkarube/items/7e02d1f9e93d107c616b)
  - ubuntu20.04へのKVMインストールはこちらを参照ください。

# 3. 動作環境
- OS : Ubuntu 20.04
- CPU : Intel(R) Pentium(R) CPU G4560 @ 3.50GHz
- RAM : 8GB
- Software
  - qemu-system-aarch64 : 4.2.1
  - virt関連 : 2.2.1
  - genisoimage : 1.1.11

# 4. 構築
## 4.1. qemu-system-aarch64の準備
- aptを用いて、以下のパッケージをインストールします。

```bash
$ sudo apt install -y qemu qemu-kvm libvirt-daemon libvirt-clients bridge-utils virt-manager
$ sudo apt install -y qemu-system-arm qemu-efi-aarch64 qemu-efi-arm qemu-system-arm
```

- qemu関連のパッケージを確認して、arm関連のパッケージが入っていることを確認します。

<details><summary>ログが長いので折りたたんでいます。</summary><div>

```bash
$ dpkg -l | grep qemu
ii  ipxe-qemu                                  1.0.0+git-20190109.133f4c4-0ubuntu3.2   all          PXE boot firmware - ROM images for qemu
ii  ipxe-qemu-256k-compat-efi-roms             1.0.0+git-20150424.a25a16d-0ubuntu4     all          PXE boot firmware - Compat EFI ROM images for qemu
ii  libvirt-daemon-driver-qemu                 6.0.0-0ubuntu8.12                       amd64        Virtualization daemon QEMU connection driver
ii  qemu                                       1:4.2-3ubuntu6.17                       amd64        fast processor emulator, dummy package
ii  qemu-block-extra:amd64                     1:4.2-3ubuntu6.17                       amd64        extra block backend modules for qemu-system and qemu-utils
ii  qemu-efi-aarch64                           0~20191122.bd85bf54-2ubuntu3.2          all          UEFI firmware for 64-bit ARM virtual machines
ii  qemu-efi-arm                               0~20191122.bd85bf54-2ubuntu3.2          all          UEFI firmware for 32-bit ARM virtual machines
ii  qemu-kvm                                   1:4.2-3ubuntu6.17                       amd64        QEMU Full virtualization on x86 hardware
ii  qemu-system-arm                            1:4.2-3ubuntu6.17                       amd64        QEMU full system emulation binaries (arm)
ii  qemu-system-common                         1:4.2-3ubuntu6.17                       amd64        QEMU full system emulation binaries (common files)
ii  qemu-system-data                           1:4.2-3ubuntu6.17                       all          QEMU full system emulation (data files)
ii  qemu-system-gui:amd64                      1:4.2-3ubuntu6.17                       amd64        QEMU full system emulation binaries (user interface and audio support)
ii  qemu-system-x86                            1:4.2-3ubuntu6.17                       amd64        QEMU full system emulation binaries (x86)
ii  qemu-utils                                 1:4.2-3ubuntu6.17                       amd64        QEMU utilities

```
</div></details>


- aarch64関連のqemuコマンドがインストールされているか確認します。

<details><summary>ログが長いので折りたたんでいます。</summary><div>

```bash
$ ls -l /usr/bin/qemu*
-rwxr-xr-x 1 root root  1997016  7月 13 00:03 /usr/bin/qemu-img
-rwxr-xr-x 1 root root  1940184  7月 13 00:03 /usr/bin/qemu-io
-rwxr-xr-x 1 root root  1948824  7月 13 00:03 /usr/bin/qemu-nbd
-rwxr-xr-x 1 root root   722848  7月 13 00:03 /usr/bin/qemu-pr-helper
-rwxr-xr-x 1 root root 18712856  7月 13 00:03 /usr/bin/qemu-system-aarch64
-rwxr-xr-x 1 root root 17759128  7月 13 00:03 /usr/bin/qemu-system-arm
-rwxr-xr-x 1 root root 16236552  7月 13 00:03 /usr/bin/qemu-system-i386
-rwxr-xr-x 1 root root 16275080  7月 13 00:03 /usr/bin/qemu-system-x86_64
lrwxrwxrwx 1 root root       18  7月 13 00:03 /usr/bin/qemu-system-x86_64-spice -> qemu-system-x86_64
```
</div></details>

- qemu-system-aarch64でエミュレートできるCPUアーキテクチャを確認します。
  - 今回は、特に指定しなかったら`cortex-a57`を使用していました。

<details><summary>ログが長いので折りたたんでいます。</summary><div>

```bash
$ qemu-system-aarch64 -cpu help -machine virt
Available CPUs:
  arm1026
  arm1136
  arm1136-r2
  arm1176
  arm11mpcore
  arm926
  arm946
  cortex-a15
  cortex-a53
  cortex-a57
  cortex-a7
  cortex-a72
  cortex-a8
  cortex-a9
  cortex-m0
  cortex-m3
  cortex-m33
  cortex-m4
  cortex-r5
  cortex-r5f
  max
  pxa250
  pxa255
  pxa260
  pxa261
  pxa262
  pxa270-a0
  pxa270-a1
  pxa270
  pxa270-b0
  pxa270-b1
  pxa270-c0
  pxa270-c5
  sa1100
  sa1110
  ti925t
```
</div></details>


## 4.2. arm版Ubuntuイメージ(cloud-init版)の準備
- cloud-init版のubuntuイメージをwgetで取得します。

```bash
& wget http://ubuntutym2.u-toyama.ac.jp/cloud-images/releases/20.04/release/ubuntu-20.04-server-cloudimg-arm64.img
```

- cloud-init版をそのまま使用すると容量がすごく小さいので、20GBまで拡張します。
  - 20GBはテキトーに決めています。自分が使用したい容量に合わせてください。

```
$ qemu-img resize ubuntu-20.04-server-cloudimg-arm64.img 20G
```

## 4.3. NoCloudデータの準備
- 初期ユーザとしてtomotenユーザを作成するため、以下のようなuser-data（テキストファイル）を作成します。
  - passwordはテキトーに書いてます。

```
#cloud-config
user: tomoten
password: hogehoge
chpasswd: { expire: Fail }
ssh_pwauth: True
```

- NoCloud用でマウントするisoファイルを作成するときに必要なmeta-data（空ファイル）を作成します。

```bash
$ touch meta-data
```

- NoCloud用でマウントするuser-data.isoファイルを作成します。

```bash
$ genisoimage -output ./udata.iso -volid cidata -joliet -rock user-data meta-data
```

## 4.3. 仮想マシンのインストール
- 何も仮想マシンを作成していない状態では、virt-managerを開いても何も仮想マシンはありません。

![virt-manager_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/ec03a085-f8af-b6f2-6282-08bba724d9ac.png)

- virt-installを用いて、以下のようなコマンドで仮想マシンを作成します。
  - なお、virt-managerのGUIからでも仮想マシンは作成可能です。下記コマンドを実行して作成される仮想マシンの設定情報をGUIから入力することで作成できます。
  - 注意点：connectにはqemuを指定します。x86_64アーキテクチャ上でaarch64を動かす場合、kvm仮想化支援機能が動作しません。qemuによるソフトウェアエミュレートなので遅いです。

```bash
$ virt-install \
--connect qemu:///system \
--name ubuntu-arm \
--vcpus 2 --ram 2048 \
--hvm --virt-type qemu \
--arch aarch64 \
--os-type linux --os-variant ubuntu20.04 \
--import --noreboot \
--disk path=$PWD/ubuntu-20.04-server-cloudimg-arm64.img \
--disk path="$PWD/udata.iso,device=cdrom"

インストールの開始中...
error: The domain is not running

仮想マシンの作成が完了しました。
現在、稼働中の仮想マシンを再起動することができます。
virsh --connect qemu:///system start ubuntu-arm
```

- 上記コマンドを実行すると、virt-manager上に仮想マシンが構築されます。
  - 設定を追加したい場合は、この段階でGUIから変更を加えられます。
  - 今回は自動でインターネットにつながるホスト側のbridgeにつながっていました。インターネットにつながるbridgeやNATを接続しておくといいです。

![virt-manager_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/ef70c0ab-7a1b-c135-ffa9-132e94f07132.png)
![virt-manager_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/9c7dac5f-af71-56d5-8bef-9b2cf887e398.png)

- 仮想マシンの画面を表示して、仮想マシンを起動します。（「▷」ボタン押下）
  - うまくいくと、下のようにUbuntuが選択できる画面がでます。
  - Ubuntuを選択すると起動を開始します。3分くらい時間がかかります。（仮想マシンに割り振ったスペックがしょぼいだけかも）

![virt-manager_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/6a08c51d-51d3-c49c-4652-8268eef8b290.png)


- 「ubuntu login: 」と表示されますが、この段階ではcloud-initの設定が完了していないのでtomotenユーザでログインできません。体感10分くらい待ちます。以下のようなログが表示されたら、完了です。

<details><summary>ログが長いので折りたたんでいます。</summary><div>

```bash
ubuntu login: [  480.037467] cloud-init[1876]: Cloud-init v. 20.3-2-g371b392c-0ubuntu1~20.04.1 running 'modules:config' at Sun, 05 Sep 2021 15:12:57 +0000. Up 465.67 seconds.
ci-info: no authorized SSH keys fingerprints found for user tomoten.
<14>Sep  5 15:13:25 ec2: 
<14>Sep  5 15:13:25 ec2: #############################################################
<14>Sep  5 15:13:25 ec2: -----BEGIN SSH HOST KEY FINGERPRINTS-----
<14>Sep  5 15:13:25 ec2: （省略）
<14>Sep  5 15:13:26 ec2: -----END SSH HOST KEY FINGERPRINTS-----
<14>Sep  5 15:13:26 ec2: #############################################################
-----BEGIN SSH HOST KEY KEYS-----
（省略）
[  494.850728] cloud-init[1922]: Cloud-init v. 20.3-2-g371b392c-0ubuntu1~20.04.1 running 'modules:final' at Sun, 05 Sep 2021 15:13:22 +0000. Up 491.03 seconds.
[  494.857657] cloud-init[1922]: ci-info: no authorized SSH keys fingerprints found for user tomoten.
[  494.866746] cloud-init[1922]: Cloud-init v. 20.3-2-g371b392c-0ubuntu1~20.04.1 finished at Sun, 05 Sep 2021 15:13:26 +0000. Datasource DataSourceNoCloud [seed=/dev/sr0][dsmode=net].  Up 494.65 seconds

（Enterを押下すると）
ubuntu login:
```
</div></details>

- user-dataで設定したtomotenユーザでログインできれば成功です。
- 「uname -a」で確認すると、aarch64であることが確認できます。

```bash
$ uname -a
Linux ubuntu 5.4.0-53-generic #59-Ubuntu SMP Wed Oct 21 09:37:28 UTC 2020 aarch64 aarch64 aarch64 GNU/Linux
```

- cloud-initの設定を止める場合は、以下のようにcloud-init.disabled（空ファイル）を作成してください。

```bash
$ sudo touch /etc/cloud/cloud-init.disabled
```

# 5. 所感
- aarch64のUbuntu仮想マシンが構築できました。
  - ただ、やはりx86_64アーキテクチャ上でaarch64のCPUエミュレートは重いです。
  - あくまで検証用、もしくは設備集約用、という感じです。
- 本当はAndroidを動かしたい思いがあったので、まずはYoctoを用いてarm向けLinuxをビルドしてqemuで動かすところを実施していきます。