# 2019q1 Homework4 (smallsys)
contributed by < `atlantis0914` >
## 作業要求
- [ ] 透過 [buildroot](https://github.com/buildroot/buildroot) 工具產生針對 AArch64 的 linux kernel image (需要是 5.0 以上版本) 和 root file system,確保滿足以下要求:
* 得以透過 `qemu-system-aarch64` 開機並正確地執行 userspace 套件 (如 Busybox)
* 確認 qemu + gdb 能夠單步執行和設定中斷點
* 確保 VirtIO + 9P 得以運作
* 閱讀 [Embedded Linux size reduction
techniques](http://events17.linuxfoundation.org/sites/events/files/slides/opdenacker-embedded-linux-size-reduction-techniques_0.pdf),嘗試建構出更小但仍可符合上述需求的 Linux 核心
---
按照作業頁面提供的教學影片 [Debugging an ARM64 linux kernel using QEMU](https://www.youtube.com/watch?v=swniLhXg-3U)
找到同作者的上一集:[Starting Linux kernel exploration with Eukabuka!](https://www.youtube.com/watch?v=zK2Agg3U2cU)
詳細介紹了如何編譯 Arch64 的 kernel image ,搭配 Buildroot 產生的 rootfs ,以及使用 qemu 執行 kernel image 。主要分成三大步驟:
1. **設定一個可以運行 Aarch64 的 qemu:**
首先取得 qemu:
```shell
git clone https://git.qemu.org/git/qemu.git
cd qemu
```
產生 qemu 執行檔之前還需設定組態:
```shell
./configure --enable-virtfs --target-list=aarch64-softmmu
```
其中:
`--enable-virtfs` : 使得 VirtIO + 9P 可以運作,
`--target-list` : 只產生可以運行 aarch64 架構的 qemu,大幅降低之後 make 的時間。
有可能會出現:
```shell
error: virtfs requires libcap devel and libattr devel
```
安裝相關套件:
```shell
sudo apt-get install libcap-dev
sudo apt-get install libattr1-dev
```
若無異常,執行 make。耐心等待一段時間之後,在 aarch64-softmmu 目錄下可以找到
`qemu-system-aarch64`:
2. **建立 initramfs cpio:**
首先取得 Buildroot:
```shell
git clone https://git.buildroot.net/buildroot
cd buildroot
```
執行 make menuconfig:

需要以下設定:
* Target options ---> Target Architecture: 選擇 **AArch64 little-endian**
* Toolcahin ---> Toolchain type: 選擇 **External toolchain**
Toolchain: 選擇 **Linaro AArch64 2018.05**
* System configuration ---> Run a getty (login prompt) after boot
TTY port 改為 **ttyAMA0**
* Filesystem images ---> cpio the root filesystem (for use as an initial RAM filesystem)
儲存之後,進行 make。若無異常,可以在 `output/images` 目錄底下找到 `rootfs.cpio`。
3. **編譯 AArch64 kernel image:**
取得 Kernel source:
```shell
git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
```
編譯 kernel 時,會參考主目錄底下的 `.config` 檔案,產生客製化的 kernel image。
我們需要產生可運行 AArch64 架構的 image,可以在 `arch/arm64/config` 目錄底下找到 ARM 64位元架構組態設定。運行:
```
ARCH=arm64 make defconfig
```
可以將 `arch/arm64/config` 目錄底下的 `defconfig` 複製到主目錄底下並且命名為 .config。
為了運行 VirtIO + 9p 得以運行,需再確認 `.config` 包含以下設定:
```
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
CONFIG_NET_9P_DEBUG=y (Optional)
CONFIG_9P_FS=y
CONFIG_9P_FS_POSIX_ACL=y
CONFIG_PCI=y
CONFIG_VIRTIO_PCI=y
```
可以參考 [9psetup](https://wiki.qemu.org/Documentation/9psetup)
除此之外,還需要設定以下組態:
```
CONFIG_CMDLINE="console-ttyAMA0"
CONFIG_INITRAMFS_SOURCE="/home/annj/smallsys/buildroot/output/images/rootfs.cpio"
```
`CONFIG_CMDLINE` 為設定支援 command line 的 UART 裝置: `ttyAMA0`。
`CONFIG_INITRAMFS_SOURCE` 為指定要載入 rootfs 的路徑。這邊輸入在第二步驟編譯好的 `rootfs.cpio`。
一切就緒後,即可編譯 Kerenl:
```
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -j8
```
耐心等待之後,可以在 `arch/arm64/boot/` 目錄底下找到 `Image`。
並且在根目錄底下找到 `vmlinux`:
```
file vmlinux
```
預期看到輸出:
```shell
vmlinux: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked,
BuildID[sha1]=b20974b0a8a4c1f4e77cd5e38ef0c51d3c477375, with debug_info, not stripped
```
可以發現 `vmlinux` 為一個 ARM 64 位元架構的可執行檔。
4. 使用 qemu 執行 AArch64 kernel image:
首先建立一個空的目錄,待會用來與 qemu 執行 AArch64 kernel 之後的 rootfs共享
此時 qemu 環境底下的 rootfs 稱為 guest,而 Ubuntu 運行環境為 host。
```
mkdir share
```
編寫運行 qemu 的腳本 `start.sh`:
```script
#!/bin/bash
/home/annj/smallsys/qemu/aarch64-softmmu/qemu-system-aarch64 \
-machine virt \
-machine type=virt \
-cpu cortex-a57 \
-nographic -smp 1 \
-m 2048 \
-kernel /home/annj/smallsys/Image \
-fsdev local,security_model=passthrough,id=test_dev,path=/home/annj/smallsys/share \
-device virtio-9p-pci,id=fsdev0,fsdev=test_dev,mount_tag=test_mount \
--append "console=ttyAMA0" \
```
其中:
`-kernel` : 指定第二步驟編譯好的 image 路徑。
`-fsdev, path` : 指定共享目錄的路徑。
其他可以參考 [9psetup](https://wiki.qemu.org/Documentation/9psetup),有針對上述參數作的說明。
一切就緒之後,執行`start.sh`:
```
[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x411fd070]
[ 0.000000] Linux version 5.1.0-rc3-00251-gf654f0fc0bd3 (annj@annj-GP62MVR-7RF) (gcc version 7.3.0 (Ubuntu/Linaro 7.3.0-27ubuntu1~18.04)) #3 SMP PREEMPT Sun Apr 7 22:20:42 CST 2019
[ 0.000000] Machine model: linux,dummy-virt
[ 0.000000] efi: Getting EFI parameters from FDT:
[ 0.000000] efi: UEFI not found.
[ 0.000000] cma: Reserved 32 MiB at 0x00000000be000000
[ 0.000000] NUMA: No NUMA configuration found
...
...
Starting syslogd: OK
Starting klogd: OK
Initializing random number generator... [ 3.514800] random: dd: uninitialized urandom read (512 bytes read)
done.
Starting network: OK
Welcome to Buildroot
buildroot login:
```
可以看到成功執行 AArch64 kernel image。
輸入`uname -m`,預期可以看到:
```
aarch64
```
接著透過 VirtIO + 9P 使得 guest 與 host 共享目錄:
```
mount -t 9p -o trans=virtio test_mount /mnt
```
此時 guest環境的 `/mnt` 目錄會與 host 環境的 share 共享。
開啟另一個 Terminal,在 share底下創建一個文件:
```
cd /share
vi hello.txt
```
可以在 guest 的 `/mnt`底下找到一樣的文件,此時 VirtIO + 9P 得以正常運行。
- [ ] 確認 qemu + gdb 能夠單步執行和設定中斷點