> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Enable virtualization

Qualcomm<sup>®</sup> 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.

<Note>
  Refer release notes to know about platform capability and support for hypervisor solution.
</Note>

## **Prerequisites and Kconfig**

Enable the following in the host kernel configuration:

```text theme={null}
CONFIG_KVM=y
CONFIG_VIRTUALIZATION=y
```

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

```bash theme={null}
ls -l /dev/kvm
```

## **Boot the kernel in EL2**

Platforms are now configured to boot into KVM as default except few. Please
refer to release notes to know about each platform capability.

For platforms that boot into Gunyah instead of KVM, use following instructions
to switch to KVM. Follow the steps in the order given.

<Note>
  Platforms that are configured to boot into KVM as default will not require
  below steps.
</Note>

1. Boot using the default images.

2. Update the EFI variable to select the KVM device tree overlay:

   ```bash theme={null}
   echo -n "el2kvm" > /var/data
   efivar -n 882f8c2b-9646-435f-8de5-f208ff80c1bd-VendorDtbOverlays -w -f /var/data
   efivar -n 882f8c2b-9646-435f-8de5-f208ff80c1bd-VendorDtbOverlays -p
   sync
   ```

3. Reboot into fastboot mode. Run the following command on the device shell:

   ```bash theme={null}
   reboot bootloader
   ```

4. Flash the KVM XBL config image from the host:

   ```bash theme={null}
   fastboot flash xbl_config_a xbl_config_kvm.elf
   ```

   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.

## **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.

### Using QEMU

Boot with a ramdisk:

```bash theme={null}
qemu-system-aarch64 \
    -M virt -m 2G \
    -kernel /mnt/overlay/guest/Image \
    -initrd /mnt/overlay/guest/rootfs.cpio.gz \
    -cpu host --enable-kvm -smp 4 -nographic
```

Boot with a root file system image:

```bash theme={null}
qemu-system-aarch64 \
    -M virt -m 2G \
    -kernel /mnt/overlay/guest/Image \
    -drive file=/mnt/overlay/guest/rootfs.ext4,if=virtio,format=raw \
    -append "root=/dev/vda" \
    -cpu host --enable-kvm -smp 4 -nographic
```

### 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**

| Command                   | Purpose                                                 |
| ------------------------- | ------------------------------------------------------- |
| `virsh define <xml-file>` | Register a new VM domain from an XML definition file    |
| `virsh list --all`        | List all defined VM domains and their state             |
| `virsh start <domain>`    | Start a stopped VM                                      |
| `virsh console <domain>`  | Connect to the VM serial console (Ctrl+] to disconnect) |
| `virsh shutdown <domain>` | Gracefully shut down a running VM                       |
| `virsh undefine <domain>` | Remove a VM definition                                  |

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](https://libvirt.org/formatdomain.html).

## **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**

| Device         | Host Kconfig                            | Guest Kconfig                                           | Purpose                                              |
| -------------- | --------------------------------------- | ------------------------------------------------------- | ---------------------------------------------------- |
| virtio-block   | —                                       | `CONFIG_VIRTIO_BLK`                                     | Block storage device for guest VMs                   |
| virtio-net     | —                                       | `CONFIG_VIRTIO_NET`                                     | Network interface for guest VMs                      |
| virtio-serial  | —                                       | `CONFIG_VIRTIO_CONSOLE`                                 | Serial communication channels between host and guest |
| virtio-9p      | `CONFIG_NET_9P`, `CONFIG_NET_9P_VIRTIO` | `CONFIG_NET_9P`, `CONFIG_NET_9P_VIRTIO`, `CONFIG_9P_FS` | Host-to-guest directory sharing over the 9P protocol |
| VSOCK          | `CONFIG_VSOCKETS`, `CONFIG_VHOST_VSOCK` | `CONFIG_VSOCKETS`, `CONFIG_VIRTIO_VSOCKETS`             | Host-to-guest socket communication                   |
| virtio-IOMMU   | —                                       | `CONFIG_VIRTIO_IOMMU`                                   | Paravirtualized IOMMU for DMA management             |
| virtio-balloon | —                                       | `CONFIG_VIRTIO_BALLOON`                                 | Dynamic guest memory reclaim and allocation          |

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

Pass a host directory to a guest VM using the 9P file system:

```bash theme={null}
qemu-system-aarch64 \
    -M virt -m 2G \
    -kernel /mnt/overlay/guest/Image \
    -drive file=/mnt/overlay/guest/rootfs.ext4,if=virtio,format=raw \
    -append "root=/dev/vda" \
    -cpu host --enable-kvm -smp 4 -nographic \
    -fsdev local,id=fsdev0,path=/mnt/overlay/test_dir,security_model=passthrough \
    -device virtio-9p-pci,fsdev=fsdev0,mount_tag=hostshare
```

Mount the shared directory inside the guest:

```bash theme={null}
mount -t 9p -o trans=virtio hostshare <mount-point>
```

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**

| CID | Description               |
| --- | ------------------------- |
| -1  | Any address (for binding) |
| 0   | Hypervisor                |
| 1   | Loopback                  |
| 2   | Host                      |

Add VSOCK to a QEMU invocation:

```bash theme={null}
-device vhost-vsock-pci,guest-cid=<cid>
```

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:

```bash theme={null}
lsusb
```

Identify PCI devices on the host:

```bash theme={null}
lspci
```

Add USB passthrough to a QEMU invocation using the vendor and product IDs from `lsusb`:

```bash theme={null}
-device qemu-xhci -device usb-host,vendorid=<vid>,productid=<pid>
```

Add PCI passthrough using the domain, bus, slot, and function from `lspci`:

```bash theme={null}
-device vfio-pci,host=<bus>:<slot>.<function>
```

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:

```bash theme={null}
echo 1 > /sys/kernel/tracing/events/kvm/enable
cat /sys/kernel/tracing/trace
```

QEMU trace events can be redirected to the kernel ftrace buffer. To launch a guest VM with virtio traces enabled:

```bash theme={null}
qemu-system-aarch64 \
    -M virt -m 2G \
    -kernel /mnt/overlay/guest/Image \
    -drive file=/mnt/overlay/guest/rootfs.ext4,if=virtio,format=raw \
    -append "root=/dev/vda" \
    -cpu host --enable-kvm -smp 4 -nographic \
    -trace "virtio*"
```

### Watchdog

QEMU emulates an I6300 ESB watchdog device, exposed to the guest as a standard watchdog character device. Enable it in the guest kernel:

```text theme={null}
CONFIG_I6300ESB_WDT=y
```

Add the watchdog to the libvirt domain XML:

```xml theme={null}
<devices>
  <watchdog model='i6300esb' action='reset'/>
</devices>
```

The `action` attribute controls behavior on timeout: `reset` restarts the guest, `poweroff` shuts it down. For details, see the [libvirt watchdog documentation](https://libvirt.org/formatdomain.html#watchdog-devices).

### 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:

```bash theme={null}
virsh qemu-agent-command <domain> '{"execute":"guest-exec","arguments":{"path":"cat","arg":["/proc/meminfo"],"capture-output":true}}'
```

Replace the following:

* `<domain>` by the VM domain name.

For more information, see [QEMU Guest Agent](https://qemu-project.gitlab.io/qemu/interop/qemu-ga.html).
