# 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: ![](https://i.imgur.com/loAVPAG.png) 需要以下設定: * 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 能夠單步執行和設定中斷點