Chapter 5: Hardware-Assisted Multi-Kernel with KVM/QEMU
Chapter 5: Hardware-Assisted Multi-Kernel with KVM/QEMU
When true concurrent multi-kernel execution is required on commodity x86_64 or ARM64 servers, hardware-assisted virtualization through KVM and QEMU provides the most robust, battle-tested foundation. However, running a secondary kernel with bare-metal performance guarantees requires abandoning default cloud-style overcommit behaviors. Every vCPU must be strictly pinned, memory statically backed by hugepages, and NUMA locality rigorously preserved.
KVM Setup and Kernel Module Configuration
To prepare an Ubuntu 26.04 host for low-latency multi-kernel operations:
Verify Hardware Virtualization Extensions:
egrep -c '(vmx|svm)' /proc/cpuinfo # Must return core count > 0Load and Configure KVM Modules: Create
/etc/modprobe.d/kvm.conf:# For Intel platforms options kvm_intel nested=1 options kvm_intel preemption_timer=0 options kvm_intel enable_shadow_vmcs=1 options kvm ignore_msrs=1Verify Module Initialization:
sudo modprobe kvm_intel ls -la /dev/kvm # Verify crw-rw----+ root kvm
Guest Kernel Installation and Configuration
Secondary kernels running alongside the host should be purpose-built to eliminate unnecessary drivers, emulated device probing, and ACPI bloat:
- Minimalist
.config: Compile the guest kernel with onlyCONFIG_VIRTIO,CONFIG_VFIO, and specific hardware drivers needed for passed-through PCIe devices. - Direct Kernel Boot: Rather than emulating a virtual disk containing a virtual bootloader (GRUB), QEMU can boot the guest kernel image directly from the host filesystem using the
-kernel,-initrd, and-appendarguments. This eliminates seconds of virtual firmware negotiation.
CPU Pinning and NUMA-Aware VM Placement
To eliminate scheduling latency, context-switching overhead, and cross-socket bus contention:
Identify Host NUMA Topology:
numactl --hardware # Node 0: CPUs 0-15, 64GB RAM # Node 1: CPUs 16-31, 64GB RAMIsolate Physical Cores for the Secondary Kernel: Host boot command line:
isolcpus=domain,managed_irq,16-31 nohz_full=16-31 rcu_nocbs=16-31.Pin QEMU vCPUs to Dedicated Physical Cores: Each guest vCPU thread is mapped 1:1 to an isolated physical core. In libvirt XML:
<vcpu placement='static'>16</vcpu> <cputune> <vcpupin vcpu='0' cpuset='16'/> <vcpupin vcpu='1' cpuset='17'/> <vcpupin vcpu='2' cpuset='18'/> <!-- ... through core 31 ... --> <emulatorpin cpuset='0-1'/> </cputune> <numatune> <memory mode='strict' nodeset='1'/> </numatune>
Memory Ballooning vs Static Allocation
Default virtualization relies on memory ballooning (virtio-balloon) to dynamically reclaim memory from idle guests, and KSM (Kernel Samepage Merging) to deduplicate shared memory pages. Both must be disabled for multi-kernel bare-metal workloads:
Memory Ballooning Penalties: Causes random guest kernel page allocation latency spikes when the balloon driver inflates.
KSM Overhead: Periodically scans physical memory, invalidating page table entries and triggering TLB shootdowns.
Static Hugepages Allocation: Back the secondary kernel’s entire memory footprint with 1GB static hugepages allocated exclusively from NUMA Node 1:
echo 64 | sudo tee /sys/devices/system/node/node1/hugepages/hugepages-1048576kB/nr_hugepages
In QEMU/libvirt configuration:
<memoryBacking>
<hugepages>
<page size='1' unit='G' nodeset='1'/>
</hugepages>
<locked/>
</memoryBacking>The <locked/> directive executes mlock(), guaranteeing the secondary kernel’s pages are permanently locked in physical RAM and cannot be swapped out under any circumstance.
Complete Working Deployment Example
Here is a standalone bash script launching an independent Linux kernel on NUMA Node 1:
#!/usr/bin/env bash
set -euo pipefail
GUEST_KERNEL="/opt/kernels/vmlinuz-6.8.0-rt"
GUEST_INITRD="/opt/kernels/initrd.img-6.8.0-rt"
GUEST_CMDLINE="console=ttyS0 root=/dev/nvme0n1p1 rw isolcpus=1-15 nohz_full=1-15"
taskset -c 16-31 qemu-system-x86_64 \
-name worker-kernel-node1,debug-threads=on \
-enable-kvm \
-cpu host,migratable=off,+invtsc \
-smp 16,sockets=1,cores=16,threads=1 \
-m 64G \
-object memory-backend-memfd,id=mem1,size=64G,hugetlb=on,hugetlbsize=1G,host-nodes=1,policy=strict \
-numa node,memdev=mem1,nodeid=0 \
-kernel "$GUEST_KERNEL" \
-initrd "$GUEST_INITRD" \
-append "$GUEST_CMDLINE" \
-nographic \
-serial mon:stdioThis configuration delivers deterministic microsecond execution directly on bare metal alongside the primary management kernel.