Skip to main content
Qualcomm® Linux supports hardware-assisted virtualization through KVM (Kernel-based Virtual Machine), which integrates directly into the Linux kernel and runs guest operating systems at near-native performance. Virtual Host Extensions (VHE) are enabled by default on Qualcomm SoCs that implement Armv8.1 or later, allowing the host kernel to run at EL2 while guest kernels and user space run at EL1 and EL0.

Supported targets

All Qualcomm® Linux development kits support KVM-based virtualization. Each target uses either KVM or Gunyah as its default boot mode. Table: Virtualization support by target
Refer release notes to know about platform capability and support for hypervisor solution.

Prerequisites and Kconfig

Enable the following in the host kernel configuration:
KVM requires the kernel to boot in exception level 2 (EL2). Verify KVM is available on the device after boot:

Boot the kernel in EL2

Skip this section if the target uses KVM as its default boot mode (see Supported targets), the host boots in EL2. If the target uses Gunyah as its default boot mode, follow these instructions to switch to KVM. Complete the steps in the order presented.
  1. Boot using the default images.
  2. Update the EFI variable to select the KVM device tree overlay:
  3. Reboot into fastboot mode. Run the following command on the device shell:
  4. Flash the KVM XBL config image from the host:
    The xbl_config_kvm.elf file is located under build/tmp/deploy/images/<machine-name> in the Yocto build output. Replace the following:
    • <machine-name> by the actual Yocto machine configuration name, for example iq-9075-evk.
  5. Reboot the device.

Build the guest VM artifacts

Before you launch a guest VM, build a guest kernel image and a guest root file system. The host image doesn’t include either component.

Build the guest kernel

The guest runs at EL1 and doesn’t require Qualcomm board device trees or EL2 configuration. Build the guest kernel by using the upstream arm64 defconfig. Use the same kernel source tree that you use for the host:
  1. Build the kernel with the standalone kmake workflow. For host setup, see Build the kernel without Yocto.
  2. Add the virtio front-end drivers the guest needs. The upstream defconfig already enables the common ones; confirm and add any that are missing using a configuration fragment:
    For the full list of virtio Kconfig symbols by device, see Supported virtio devices.
The build process writes the guest kernel image to ../kobj-guest/arch/arm64/boot/Image.

Build the guest root file system

Use Yocto to build a minimal guest root file system. The same recipe generates both the CPIO ramdisk and the ext4 disk image.
  1. Open a kas shell in your workspace:
  2. Add the required image types to build/conf/local.conf so the build produces both a ramdisk and a disk image:
  3. Build the console image, which is the smallest supported image and adequate for a guest:
  4. Collect the artifacts from the deploy directory:
You can use any arm64 root file system as a guest. If you don’t need a Yocto-built guest image, use an aarch64 distribution cloud image with the -drive option instead of rootfs.ext4.

Stage the artifacts on the device

Copy the guest kernel and root file system to the host device and place them in the directory that the following examples use:
Confirm the guest kernel is the raw image that QEMU expects:

Launch a guest VM

Before launching a guest VM, ensure the guest kernel image (Image), root file system CPIO (rootfs.cpio.gz), and root file system image (rootfs.ext4) are present in the /mnt/overlay/guest/ directory on the host. To produce them, see Build the guest VM artifacts.

Using QEMU

Boot with a ramdisk:
Boot with a root file system image:

Using libvirt

Libvirt manages VMs through the virsh command-line utility and the libvirtd daemon. Define a VM from an XML domain file, then control it with the following commands: Table: Common virsh VM management commands Replace the following:
  • <xml-file> by the path to the libvirt XML domain definition file.
  • <domain> by the VM domain name as defined in the XML <name> element.
For libvirt XML domain definition examples, see the libvirt domain format documentation.

Virtio device support

Virtio provides a paravirtualized I/O framework for high-performance device emulation between guest VMs and the host. Front-end drivers run in the guest OS; back-end drivers run in QEMU or the kernel. Communication uses virtqueues (ring buffers) to minimize guest-to-host transitions. Table: Supported virtio devices

Host-to-guest file sharing (virtio-9p)

Pass a host directory to a guest VM using the 9P file system:
Mount the shared directory inside the guest:
Replace the following:
  • <mount-point> by the directory inside the guest to mount the shared folder.

Virtual sockets (VSOCK)

VSOCK enables socket communication between guest VMs and the host using a context identifier (CID). The host CID is always 2; guest CIDs start from 3. Table: Reserved CID values Add VSOCK to a QEMU invocation:
Replace the following:
  • <cid> by the CID to assign to the guest VM, for example 73.

Device passthrough

Physical devices can be passed through to a guest VM using VFIO (PCI), libusb (USB), or a chardev backend (UART). Identify USB devices on the host:
Identify PCI devices on the host:
Add USB passthrough to a QEMU invocation using the vendor and product IDs from lsusb:
Add PCI passthrough using the domain, bus, slot, and function from lspci:
Replace the following:
  • <vid> and <pid> by the USB vendor and product ID in hex, for example 0x0781 and 0x5567.
  • <bus>, <slot>, <function> by the PCI address components from lspci output.
For UART passthrough, configure a chardev backend pointing to the host TTY device and expose it to the guest as a virtserialport.

Observability and maintenance

KVM traces

Enable KVM event tracing via tracefs:
QEMU trace events can be redirected to the kernel ftrace buffer. To launch a guest VM with virtio traces enabled:

Watchdog

QEMU emulates an I6300 ESB watchdog device, exposed to the guest as a standard watchdog character device. Enable it in the guest kernel:
Add the watchdog to the libvirt domain XML:
The action attribute controls behavior on timeout: reset restarts the guest, poweroff shuts it down. For details, see the libvirt watchdog documentation.

Remote command execution

The QEMU guest agent (qemu-ga) allows commands to be run on a guest VM from the host without a network connection. Enable qemu-ga in the guest OS user space and configure it through a virtio-serial interface. Use virsh qemu-agent-command with the guest-exec subcommand to execute commands remotely:
Replace the following:
  • <domain> by the VM domain name.
For more information, see QEMU Guest Agent.