#!/bin/bash # Install patched KVM modules for the RUNNING kernel and prove they went live. # # install-modules.sh [dir] dir holds the built kvm*.ko, default arch/x86/kvm # # Modules land in updates/, which modprobe prefers over kernel/. On Arch the # vfio-native-kvm package does all of this; this script is the manual path. # Back out with restore-stock-kvm.sh. set -euo pipefail SRC=${1:-arch/x86/kvm} KVER=$(uname -r) DEST=/usr/lib/modules/$KVER/updates [ "$EUID" -eq 0 ] || { echo "run as root"; exit 1; } if virsh -c qemu:///system list --state-running --name 2>/dev/null | grep -q .; then echo "a domain is running; modprobe -r kvm needs the refcount at zero"; exit 1 fi VENDOR=$(lsmod | grep -oE '^kvm_(amd|intel)' | head -1) [ -n "$VENDOR" ] || { echo "neither kvm_amd nor kvm_intel is loaded"; exit 1; } # vermagic must match the running kernel exactly or the module will silently not load want="$KVER SMP preempt mod_unload" found=0 for m in kvm kvm-amd kvm-intel; do [ -f "$SRC/$m.ko" ] || continue got=$(modinfo -F vermagic "$SRC/$m.ko" | tr -s ' ' | sed 's/ *$//') [ "$got" = "$want" ] || { echo "vermagic mismatch on $m: '$got' != '$want'"; exit 1; } found=1 done [ "$found" = 1 ] || { echo "no kvm modules found in $SRC"; exit 1; } install -d "$DEST" for m in kvm kvm-amd kvm-intel; do [ -f "$SRC/$m.ko" ] || continue zstd -q -f -19 "$SRC/$m.ko" -o "$DEST/$m.ko.zst" echo "installed $DEST/$m.ko.zst" done depmod -a "$KVER" modprobe -r "$VENDOR" kvm modprobe "$VENDOR" # Check BOTH. The #GP fix lands in svm.c (kvm-amd.ko) and the hypercall fixes in # emulate.c/x86.c (kvm.ko), so verifying one passes on a stale build of the other. for m in kvm "$VENDOR"; do built=$(modinfo -F srcversion "$SRC/${m//_/-}.ko") live=$(cat "/sys/module/$m/srcversion") echo "$m built=$built live=$live" [ "$built" = "$live" ] || { echo "FATAL: patched $m is NOT live"; exit 1; } done echo "OK - patched modules are live"