[PATCH v2 2/2] crosvm-image-minimal: add a reference image for crosvm demo

Keerthivasan Raghavan <[email protected]> Sat, 13 Jun 2026 11:37:43 +0530
Newsgroups org.yoctoproject.lists.meta-virtualization
Message-ID <[email protected]>
A reference image called `crosvm-image-minimal` is provided
for testing/validation on supported machines(arm64 and x86-64).
Instructions are provided to test on QEMU(x86-64 only).

Testing was done on x86-64 by achieving boot to shell on a crosvm vm
instance running inside a vm instance on QEMU, i.e nested virtualization
with machine as qemux86-64.
Testing was done on arm64 by achieving boot to shell on a crosvm vm
instance running directly on meta-qcom machine qcs9100-ride-sx.

Signed-off-by: Keerthivasan Raghavan <[email protected]>
---
 recipes-extended/images/README-crosvm.md      | 68 +++++++++++++++
 .../images/crosvm-image-minimal.bb            | 82 +++++++++++++++++++
 2 files changed, 150 insertions(+)
 create mode 100644 recipes-extended/images/README-crosvm.md
 create mode 100644 recipes-extended/images/crosvm-image-minimal.bb

diff --git a/recipes-extended/images/README-crosvm.md b/recipes-extended/images/README-crosvm.md
new file mode 100644
index 00000000..2c36da7d
--- /dev/null
+++ b/recipes-extended/images/README-crosvm.md
@@ -0,0 +1,68 @@
+# crosvm-image-minimal: build and test
+
+Steps to test/validate crosvm are given below.
+A reference image `crosvm-image-minimal` is provided
+for this purpose.
+
+## local.conf example
+
+```conf
+# virtualization
+MACHINE ??= "qemux86-64"
+DISTRO ??= "nodistro"
+BBMULTICONFIG ?= ""
+
+DISTRO_FEATURES += " kvm virtualization"
+IMAGE_FEATURES += " empty-root-password allow-empty-password allow-root-login"
+IMAGE_FSTYPES = "ext4"
+IMAGE_FSTYPES:remove = "ext4.zst"
+```
+
+## Build
+
+```bash
+bitbake crosvm-image-minimal
+```
+
+## Boot in QEMU
+
+When the target `MACHINE` is `qemux86-64`, the host running QEMU must support:
+- nested virtualization
+- Intel VT-x or AMD SVM
+- exposed `/dev/kvm`
+
+Run from `tmp/deploy/images/qemux86-64/` (or adjust paths):
+
+```bash
+qemu-system-x86_64 \
+  -enable-kvm \
+  -machine q35 \
+  -cpu host \
+  -smp 4 \
+  -m 4096 \
+  -kernel bzImage \
+  -drive file=crosvm-image-minimal-qemux86-64.rootfs.ext4,format=raw,if=virtio \
+  -append "root=/dev/vda rw console=ttyS0 earlyprintk=serial nokaslr" \
+  -nographic
+```
+
+## Run crosvm inside the guest
+
+The image bundles:
+
+- `/var/lib/crosvm/images/guest-kernel`
+- `/var/lib/crosvm/images/guest.ext4`
+
+```bash
+crosvm --log-level "debug,disk=off" run \
+  --disable-sandbox  /var/lib/crosvm/images/guest-kernel \
+  --block /var/lib/crosvm/images/guest.ext4,root \
+  -p "root=/dev/vda rw console=ttyS0 earlyprintk=serial nokaslr"
+```
+
+## Quick sanity checks
+
+```bash
+test -e /dev/kvm && echo "/dev/kvm present"
+ls -l /var/lib/crosvm/images/
+```
diff --git a/recipes-extended/images/crosvm-image-minimal.bb b/recipes-extended/images/crosvm-image-minimal.bb
new file mode 100644
index 00000000..59ba7c9b
--- /dev/null
+++ b/recipes-extended/images/crosvm-image-minimal.bb
@@ -0,0 +1,82 @@
+SUMMARY = "A minimal image containing crosvm to demo its uage."
+
+KVM_MODULES = ""
+
+# arm64 linux kernels have kvm inbuilt
+KVM_MODULES:aarch64 = ""
+
+KVM_MODULES:x86-64 = " \
+    kernel-module-kvm \
+    kernel-module-kvm-intel \
+    kernel-module-kvm-amd \
+"
+
+IMAGE_INSTALL = "packagegroup-core-boot crosvm"
+IMAGE_INSTALL:append = " ${KVM_MODULES}"
+
+IMAGE_LINGUAS = " "
+
+LICENSE = "MIT"
+
+inherit core-image
+
+# Guest artifact source settings.
+# This is intentionally a normal variable
+# assignment so it can be overridden in local.conf. The do_rootfs[depends]
+# is added at parse time, so any local.conf override is picked up correctly.
+CROSVM_GUEST_IMAGE_RECIPE ?= "core-image-minimal"
+CROSVM_GUEST_IMAGE_FSTYPE ?= "ext4"
+CROSVM_GUEST_ROOTFS ?= "${CROSVM_GUEST_IMAGE_RECIPE}-${MACHINE}.rootfs.${CROSVM_GUEST_IMAGE_FSTYPE}"
+CROSVM_GUEST_KERNEL ?= "${KERNEL_IMAGETYPE}"
+
+# Final location inside the host/root image.
+CROSVM_GUEST_TARGET_DIR ?= "/var/lib/crosvm/images"
+CROSVM_GUEST_TARGET_ROOTFS_NAME ?= "guest.${CROSVM_GUEST_IMAGE_FSTYPE}"
+CROSVM_GUEST_TARGET_KERNEL_NAME ?= "guest-kernel"
+
+# Ensure guest image and kernel are available before rootfs postprocess runs.
+# The image also depends on guest rootfs to avoid stale consumption
+# of deployed guest image artifact.
+# The same kernel is used for both the host and guest.
+do_rootfs[depends] += "\
+	${CROSVM_GUEST_IMAGE_RECIPE}:do_image_complete \
+	${CROSVM_GUEST_IMAGE_RECIPE}:do_rootfs \
+	virtual/kernel:do_deploy \
+"
+
+# Copy guest rootfs+kernel into the host rootfs for crosvm demo runtime.
+bundle_crosvm_guest() {
+    set -e
+
+    local deploy_dir="${DEPLOY_DIR_IMAGE}"
+    local rootfs_src="${deploy_dir}/${CROSVM_GUEST_ROOTFS}"
+    local kernel_src="${deploy_dir}/${CROSVM_GUEST_KERNEL}"
+    local target_dir="${IMAGE_ROOTFS}${CROSVM_GUEST_TARGET_DIR}"
+
+    if [ ! -e "$rootfs_src" ]; then
+        bbfatal "Cannot find guest rootfs. Tried: \
+                ${deploy_dir}/${CROSVM_GUEST_ROOTFS} and \
+                ${deploy_dir}/${CROSVM_GUEST_IMAGE_RECIPE}-${MACHINE}.rootfs.${CROSVM_GUEST_IMAGE_FSTYPE}"
+    fi
+
+    if [ ! -e "$kernel_src" ]; then
+        bbfatal "Cannot find guest kernel. Tried: \
+                ${deploy_dir}/${CROSVM_GUEST_KERNEL}"
+    fi
+
+    install -d "$target_dir"
+
+    install -m 0644 "$(readlink -f "$rootfs_src")" \
+                    "$target_dir/${CROSVM_GUEST_TARGET_ROOTFS_NAME}"
+
+    install -m 0644 "$(readlink -f "$kernel_src")" \
+                    "$target_dir/${CROSVM_GUEST_TARGET_KERNEL_NAME}"
+}
+
+ROOTFS_POSTPROCESS_COMMAND += "bundle_crosvm_guest;"
+
+IMAGE_ROOTFS_SIZE = "0"
+
+KERNEL_MODULE_AUTOLOAD:append:x86-64 = " kvm kvm_amd kvm_intel"
+
+
-- 
2.34.1