面向移動及嵌入式平臺的輕量級開源ARMv8-A Hypervisor
Minos - Type 1 Hypervisor for ARMv8-A
Minos是一款輕量級的面向移動及嵌入式系統的開源Type 1 Hypervisor, 直接運行於裸機環境。Minos實現了一套完整的虛擬化框架,可以在同一硬體平臺上同時執行多個不同作業系統的VM(Linux or RTOS). Minos提供了包括CPU虛擬化; 中斷虛擬化; 記憶體虛擬化; Timer虛擬化; 以及一些常用外設虛擬化的支援。
Minos提供一個運行於VM0上的應用程式"mvm"來支援Guest VM的管理。同時mvm提供基於virtio的半虛擬化解決方案, 支援virtio-console, virtio-blk(測試中),virtio-net(測試中)等裝置。
Minos適用於移動及嵌入式平臺,目前只支援ARMv8-A架構。硬體上支援Marvell的Esspressobin開發板,且理論上ARMv8-A + GICV3組合的硬體平臺都可以被支援。軟體除錯平臺支援ARM官方的Fix Virtual Platform (簡稱FVP), 開發者可以用ARM DS5工具來進行模擬和除錯。
Download Source Code And Tools for Minos
-
建立工作目錄
# mkdir ~/minos-workspace # cd ~/minos-workspace
-
安裝gcc交叉編譯工具
# wget https://releases.linaro.org/components/toolchain/binaries/latest/aarch64-linux-gnu/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz # tar xjf gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz # sudo mv gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu /opt # echo "export PATH=/opt/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin:$PATH" >> ~/.bashrc # source ~/.bashrc
-
安裝abootimg工具
# sudo apt-get install abootimg
abootimg 工具用來製作Linux VM的bootimge,mvm使用此格式image來載入linux核心,ramdisk和dtb檔案
-
安裝device tree程式碼編譯工具
# sudo apt-get install device-tree-compiler
-
下載Minos sample
# git clone https://github.com/minos-project/minos-samples.git
minos-sample提供了Guest VM的dts/dtb檔案,以及製作好的Guest VM boot.img檔案
-
下載Minos hypervisor 原始碼
# git clone https://github.com/minos-project/minos-hypervisor.git
-
下載Linux Kernel 原始碼
# git clone https://github.com/minos-project/linux-marvell.git # cd linux-marvell # git checkout -b minos origin/minos
預設下載的是添加了Minos驅動的Marvell平臺的Linux Kernel, 如果用的是別的硬體平臺,只需要新增Minos驅動就行,下面命令可以獲取Minos驅動以及必要的Kernel Patch
# git clone https://github.com/minos-project/minos-linux-driver.git
-
下載ATF原始碼
# git clone https://github.com/ARM-software/arm-trusted-firmware.git
在FVP上執行和除錯Minos時需要用到
Run Minos on Marvell Esspressobin
-
編譯Minos
# cd ~/minos-workspace/minos # make
Minos預設平臺為Marvel Esspressobin,編譯完成後會在 hypervisor/out目錄下生成minos.bin以及在mvm目錄下生成mvm應用程式
-
編譯Marvell Linux Kernel
# cd ~/minos-workspace/linux-marvell # export ARCH=arm64 # export CROSS_COMPILE=aarch64-linux-gnu- # make mvebu_v8_lsp_defconfig # make -j4
編譯完成後會在arch/arm64/boot目錄下生成Image核心二進位制檔案。
-
Esspressobin預設的核心存放在開發板的/boot目錄下,把minos.bin和新的Kernel Image拷貝到/boot目錄下, 並把mvm應用拷貝到開發板的使用者根目錄下。
-
更新開發板Uboot啟動設定
啟動開發板到命令列狀態,執行以下命令更新Uboot啟動設定(這裡以EMMC版本的Esspressobin開發板舉例,採用SD卡方式啟動的開發板,方法類似)
# setenv bootcmd “mmc dev 1; ext4load mmc 1:1 0x3c000000 boot/minos.bin; ext4load mmc 1:1 0x280000 boot/Image; ext4load mmc 1:1 0xfe00000 boot/armada-3720-community-v5.dtb; setenv bootargs console=ttyMV0,115200 earlycon=ar3700_uart,0xd0012000 root=PARTUUID=89708921-01 rw rootwait net.ifnames=0 biosdevname=0; booti 0x3c000000 - 0xfe00000” # saveenv
-
設定完之後重啟開發板,之後每次開機將會先跳轉到Minos執行hypervisor相關設定,然後再啟動VM0
提示: 如果因為Minos程式碼錯誤導致系統啟動不了,只需要用原來的啟動引數先啟動到非虛擬化環境,然後把能正常執行的minos.bin替換到/boot目錄下就可以
# mmc dev 1; ext4load mmc 1:1 $kernel_addr $image_name; ext4load mmc 1:1 $fdt_addr $fdt_name; setenv bootargs $console root=PARTUUID=89708921-01 rw rootwait net.ifnames=0 biosdevname=0; booti $kernel_addr - $fdt_addr
Run Minos on ARM FVP
-
下載ARM FVP,建立工作目錄
# mkdir ~/minos-workspace/arm-fvp
FVP可以在ARM的官網下載,Minos支援FVP_Base_AEMv8A 以及FVP_Base_Cortex-A57x2-A53x4 ,這裡我們預設使用FVP_Base_AEMv8A來進行測試。另外如果想基於Minos做相關開發,也可以直接安裝ARM DS5除錯工具,安裝完之後自帶以上兩個FVP。以下是安裝使用DS5的相關教程
-
編譯Minos
# cd ~/minos-workspace/minos # make distclean (每次改變編譯target前需要執行 make distclean) # make PLATFORM=fvp
-
編譯FVP Kernel
# cd ~/minos-workspace/minos # make ARCH=arm64 defconfig && make ARCH=arm64 -j8 Image
-
編譯ARM Trusted Firmware
# cd ~/minos-workspace/arm-trusted-firmware # make PLAT=fvp RESET_TO_BL31=1 ARM_LINUX_KERNEL_AS_BL33=1 PRELOADED_BL33_BASE=0xc0000000 ARM_PRELOADED_DTB_BASE=0x83e00000
-
下載ARM64 virtio-block image
# cd ~/minos-workspace # wget https://releases.linaro.org/archive/14.07/openembedded/aarch64/vexpress64-openembedded_minimal-armv8-gcc-4.9_20140727-682.img.gz # gunzip vexpress64-openembedded_minimal-armv8-gcc-4.9_20140727-682.img.gz # mv vexpress64-openembedded_minimal-armv8-gcc-4.9_20140727-682.img sd.img
-
執行FVP
# cd ~/minos-workspace/arm-fvp # ln -s ~/minos-workspace/sd.img sd.img # ln -s ~/minos-workspace/arm-trusted-firmware/build/fvp/release/bl31.bin bl31.bin # ln -s ~/minos-workspace/linux-marvell/arch/arm64/boot/Image Image # ln -s ~/minos-workspace/minos-sample/foundation-v8-gicv3.dtb fdt.dtb # ln -s ~/minos-workspace/minos/hypervisor/out/minos.bin minos.bin # /usr/local/DS-5_v5.27.0/bin/FVP_Base_AEMv8A \ -C pctl.startup=0.0.0.0 \ -C bp.secure_memory=0 \ -C cluster0.NUM_CORES=4 \ -C cache_state_modelled=1 \ -C cluster0.cpu0.RVBAR=0x04020000 \ -C cluster0.cpu1.RVBAR=0x04020000 \ -C cluster0.cpu2.RVBAR=0x04020000 \ -C cluster0.cpu3.RVBAR=0x04020000 \ -C bp.hostbridge.userNetPorts="8022=22" \ -C bp.hostbridge.userNetworking=true \ -C bp.dram_size=8 \ -C bp.smsc_91c111.enabled=true \ -C bp.virtioblockdevice.image_path=sd.img \ --data [email protected] \ --data [email protected] \ --data [email protected] \ --data [email protected]
-
啟動FVP之後,可以在主機上執行以下命令通過ssh來登入FVP
# ssh -p 8022 [email protected]
mvm使用方法
Minos提供兩種方式來建立VM, 一種是使用Minos原始碼下的JSON檔案(例如hypervisor/config/fvp/fvp.json.cc),通過建立一個vmtag的json成員來建立對應的VM,且這種VM的記憶體, IRQ等硬體資源都是通過對應的json檔案來管理的,此方式適合用來建立嵌入式系統中擁有真實硬體許可權的VM, Minos支援將特定的硬體裝置分配給特定的VM。通過這種方式建立的VM當前沒法被mvm管理。
#include "fvp_config.h"
{
"version": "0.0.1",
"platform": "armv8-fvp",
"vmtags": [
{
"vmid": 0,
"name": "linux-01",
"type": "linux",
"nr_vcpu": 1,
"entry": "0x80080000",
"setup_data": "0x83e00000",
"vcpu0_affinity": 0,
"vcpu1_affinity": 1,
"vcpu2_affinity": 2,
"vcpu3_affinity": 3,
"cmdline": "",
"bit64": 1
}
],
#include "fvp_irq.json.cc"
#include "fvp_mem.json.cc"
"others" : {
"comments": "minos virtualization config json data"
}
}
另外一種方式就是通過Minos提供的VM管理工具mvm來配置, 當前mvm已經支援了VM的建立,銷燬,重啟和關機操作。
Usage: mvm [options]
-c <vcpu_count> (set the vcpu numbers of the vm)
-m <mem_size_in_MB> (set the memsize of the vm - 2M align)
-i <boot or kernel image> (the kernel or bootimage to use)
-s <mem_start> (set the membase of the vm if not a boot.img)
-n <vm name> (the name of the vm)
-t <vm type> (the os type of the vm )
-b <32 or 64> (32bit or 64 bit )
-r (do not load ramdisk image)
-v (verbose print debug information)
-d (run as a daemon process)
-D (device argument)
-C (set the cmdline for the os)
例如以下命令用來建立一個擁有 2 個vcpu, 84M記憶體, bootimage為boot.img以及帶有virtio-console裝置的64位的(當前Minos只支援64位VM)Linux虛擬機器.
#./mvm -c 2 -m 84M -i boot.img -n elinux -t linux -b 64 -v -d -C "console=hvc0 loglevel=8 consolelog=9 loglevel=8 consolelog=9" -D virtio_console,@pty:
建立成功的話會有以下log輸出
[INFO ] no rootfs is point using ramdisk if exist
[email protected]:~# [INFO ] boot image infomation :
[INFO ] magic - ANDROID!
[INFO ] kernel_size - 0x877800
[INFO ] kernel_addr - 0x80080000
[INFO ] ramdisk_size - 0x104e21
[INFO ] ramdisk_addr - 0x83000000
[INFO ] dtb_size - 0xcc4
[INFO ] dtb_addr - 0x83e00000
[INFO ] tags_addr - 0x0
[INFO ] page_size - 0x800
[INFO ] name -
[INFO ] cmdline - console=hvc0 loglevel=8 consolelog=9
[INFO ] create new vm *
[INFO ] -name : elinux
[INFO ] -os_type : linux
[INFO ] -nr_vcpus : 2
[INFO ] -bit64 : 1
[INFO ] -mem_size : 0x5400000
[INFO ] -mem_start : 0x80000000
[INFO ] -entry : 0x80080000
[INFO ] -setup_data : 0x83e00000
[DEBUG] load kernel image: 0x80000 0x800 0x877800
[DEBUG] load ramdisk image:0x3000000 0x878000 0x104e21
[DEBUG] vdev : irq-32 gpa-0x7fad895000 gva-0x40000000
[INFO ] ***********************************************
[INFO ] virt-console backend redirected to /dev/pts/1
[INFO ] ***********************************************
[INFO ] add cmdline - console=hvc0 loglevel=8 consolelog=9 loglevel=8 consolelog=9
[INFO ] - delete [email protected]
[INFO ] - delete [email protected]
[INFO ] - delete [email protected]
[INFO ] - delete [email protected]
[INFO ] - delete [email protected]
[INFO ] - delete [email protected]
[DEBUG] found 1 rsv memory region
[DEBUG] add rsv memory region : 0x80000000 0x10000
[INFO ] setup memory 0x0 0x80 0x0 0x4005
[INFO ] set ramdisk : 0x83000000 0x104e21
[INFO ] add vdev success addr-0x40000000 virq-32
Minos當前已經支援virtio-console後端驅動,建立完VM之後可以用minicom等終端工具登入VM
# minicom /dev/pts/1
製作自定義bootimage
Minos預設提供的boot.img的ramdisk.img基於busybox預設rootfs配置,如果需要自定義自己定製ramdisk,也很簡單,只需要將製作好ramdisk.img和Image以及dtb檔案重新打包:
# dtc -I dts -O dtb -o guest-vm.dtb guest-vm.dts
# abootimg --create boot.img -c kerneladdr=0x80080000 -c ramdiskaddr=0x83000000 -c secondaddr=0x83e00000 -c cmdline="console=hvc0 loglevel=8 consolelog=9" -k Image -s guest-vm.dtb -r ramdisk.img