| # Guest | |
| The `vmm` app enables booting a guest operating system using the Zircon | |
| hypervisor. The hypervisor and VMM are collectively referred to as "Machina". | |
| These instructions will guide you through creating minimal Zircon and Linux | |
| guests. For instructions on building a more comprehensive Linux guest system | |
| see the [debian_guest](../packages/debian_guest/README.md) package. | |
| These instructions assume a general familiarity with how to netboot the target | |
| device. | |
| ## Build host system with the guest package | |
| Configure, build, and boot the guest package as follows: | |
| ``` sh | |
| fx set core.${ARCH} --with-base //src/virtualization | |
| fx build | |
| ``` | |
| Where `${ARCH}` is one of `x64` or `arm64`. | |
| ### Note for external developers | |
| (Googlers: You don't need to do this, the Linux images are downloaded from CIPD | |
| by jiri.) | |
| The `linux_guest` package expects the Linux kernel binaries to be in | |
| `prebuilt/virtualization/packages/linux_guest`. You should create them before | |
| running `fx build` by running the following scripts: | |
| ```sh | |
| ./src/virtualization/packages/linux_guest/mklinux.sh \ | |
| -l /tmp/linux/source \ | |
| -o prebuilt/virtualization/packages/linux_guest/images/${ARCH}/Image \ | |
| -b machina-4.18 \ | |
| ${ARCH} | |
| ./src/virtualization/packages/linux_guest/mksysroot.sh \ | |
| -o prebuilt/virtualization/packages/linux_guest/images/${ARCH}/disk.img \ | |
| -d /tmp/toybox \ | |
| -s /tmp/dash \ | |
| -u \ | |
| ${ARCH} | |
| ``` | |
| Note: `-b` specifies the branch of `zircon_guest` to use. You can modify this | |
| value if you need a different version or omit it to use a local version. | |
| ## Running guests | |
| After netbooting the target device, to run Zircon: | |
| ```sh | |
| guest launch zircon_guest | |
| ``` | |
| Likewise, to launch a Linux guest: | |
| ```sh | |
| guest launch linux_guest | |
| ``` | |
| ## Running on QEMU | |
| Running a guest on QEMU on x64 requires kvm (i.e. pass `-k` to `fx qemu`): | |
| ```sh | |
| fx qemu -k | |
| ``` | |
| You may also need to enable nested KVM on your host machine. The following | |
| instructions assume a Linux host machine with an Intel processor. | |
| To check whether nested virtualization is enabled, run the following command: | |
| ```sh | |
| cat /sys/module/kvm_intel/parameters/nested | |
| ``` | |
| An output of `Y` indicates nested virtualization is enabled, `0` or `N` | |
| indicates not enabled. | |
| To enable nested virtualization until the next reboot: | |
| ```sh | |
| modprobe -r kvm_intel | |
| modprobe kvm_intel nested=1 | |
| ``` | |
| To make the change permanent add the following line to | |
| `/etc/modprobe.d/kvm.conf`: | |
| ``` | |
| options kvm_intel nested=1 | |
| ``` | |
| Running an arm64 guest on QEMU requires either using GICv2 (pass `-G 2`). | |
| ```sh | |
| fx qemu -G 2 | |
| ``` | |
| Or using a more recent version of QEMU (try 2.12.0). Older versions of QEMU do | |
| not correctly emulate GICv3 when running with multiple guest VCPUs. | |
| ```sh | |
| fx qemu -q /path/to/recent/qemu/aarch64-softmmu | |
| ... | |
| guest launch (linux_guest|zircon_guest) | |
| ``` | |
| ## Running from Workstation | |
| To run from Workstation, configure the guest package as follows: | |
| ```sh | |
| fx set workstation.x64 --with-base //src/virtualization | |
| ``` | |
| After booting the guest packages can be launched from the system launcher as | |
| `linux_guest` and `zircon_guest`. | |
| ## Integration tests | |
| Machina has a set of integration tests that launch Zircon and Debian guests to test the VMM, | |
| hypervisor, and each of the virtio devices. To run the tests: | |
| ```sh | |
| fx set core.${ARCH} --with-base //src/virtualization | |
| fx run-test guest_integration_tests | |
| ``` | |
| # Guest Configuration | |
| Guest systems can be configured by including a config file inside the guest | |
| package: | |
| ```json | |
| { | |
| "type": "object", | |
| "properties": { | |
| "kernel": { | |
| "type": "string" | |
| }, | |
| "ramdisk": { | |
| "type": "string" | |
| }, | |
| "block": { | |
| "type": "string" | |
| }, | |
| "cmdline": { | |
| "type": "string" | |
| } | |
| } | |
| } | |
| ``` | |
| # Monitor Guest exit statistics | |
| "kstats -v" can print the number of Guest exits per second and the reason. | |
| For arm64: | |
| cpu vm_entry vm_exit inst_abt data_abt wfx_inst sys_inst smc_inst ints | |
| 0 43 43 0 6 27 1 0 9 | |
| 1 226 225 0 111 3 17 0 94 | |
| 2 109 109 0 60 8 7 0 35 | |
| 3 58 58 0 21 12 2 0 23 | |
| Fields: | |
| - `inst_abt`: The amount of instruction abort exit. | |
| - `data_abt`: The amount of data abort exit. | |
| - `wfx_inst`: The amount of instruction wfe/wfi exit. | |
| - `sys_inst`: The amount of systen register access exit. | |
| - `smc_inst`: The amount of instruction smc exit. | |
| - `ints` : The amount of interrupt exit. | |
| For x86_64: | |
| cpu vm_entry vm_exit ints ints_win ept ctrl_reg msr(rd wr) inst(io hlt cpuid pause vmcall xsetbv) | |
| 0 40 40 10 0 0 0 10 10 5 5 0 0 0 0 | |
| Fields: | |
| - `ints` : The amount of interrupt exit. | |
| - `ints_win` : The amount of interrupt window exit. | |
| - `ept` : The amount of EPT violation exit. | |
| - `ctrl_reg` : The amount of control register(CRx) access exit. | |
| - `msr` : The amount of MSR register access exit (`rd/wr` is read/write). | |
| - `inst` : the amount of some kinds of instruction exit. |