diff --git a/packaging/vfio-native-kvm-dkms/.SRCINFO b/packaging/vfio-native-kvm-dkms/.SRCINFO new file mode 100644 index 0000000..02e8293 --- /dev/null +++ b/packaging/vfio-native-kvm-dkms/.SRCINFO @@ -0,0 +1,26 @@ +pkgbase = vfio-native-kvm-dkms + pkgdesc = KVM modules patched to raise the exceptions the architecture specifies (DKMS, 7.2.x kernels) + pkgver = 7.2.3 + pkgrel = 1 + url = https://git.archworks.co/sandwich/vfio-native + install = vfio-native-kvm-dkms.install + arch = x86_64 + license = GPL-2.0-only + makedepends = git + depends = dkms + optdepends = vfio-native: the setup and verification tooling + provides = vfio-native-kvm + conflicts = vfio-native-kvm + noextract = linux-7.2.3.tar.xz + source = git+https://git.archworks.co/sandwich/vfio-native.git#tag=v1.1.0 + source = https://cdn.kernel.org/pub/linux/kernel/v7.x/linux-7.2.3.tar.xz + source = dkms.conf + source = dkms-out-of-tree.patch + source = kvm-native.hook + sha256sums = SKIP + sha256sums = 8ba259e8e7b13ec6ef0941c8a39ad90b24bd4a4d6c0010ba6bafb794550ecd03 + sha256sums = SKIP + sha256sums = SKIP + sha256sums = SKIP + +pkgname = vfio-native-kvm-dkms diff --git a/packaging/vfio-native-kvm-dkms/PKGBUILD b/packaging/vfio-native-kvm-dkms/PKGBUILD new file mode 100644 index 0000000..1a5aea9 --- /dev/null +++ b/packaging/vfio-native-kvm-dkms/PKGBUILD @@ -0,0 +1,74 @@ +# Maintainer: Sandwich +# +# KVM modules patched for architectural conformance, built by DKMS against +# whichever 7.2.x kernels are installed. Three VMAware checks stop firing as a +# direct consequence, because the fix is to raise the exception the +# architecture specifies: +# +# SVM_EXCEPTIONS a CPL>0 SVM instruction must raise #UD, not #GP +# KVM_INTERCEPTION a CPL>0 VMCALL/hypercall must raise #UD, not #GP or nothing +# DBVM an ICEBP #DB must report the RIP after the instruction +# +# The experimental CPUID-passthrough patch is built in as well but is OFF by +# default (module parameter cpuid_passthrough). It clears the last software +# check, TIMER, on a 1:1-pinned guest; vm-native-setup prints how to enable it. +# +# KVM is in-tree, so the DKMS tree carries arch/x86/kvm and virt/kvm from the +# vanilla kernel of the same version and builds them against the installed +# headers; the two Makefile paths that assume an in-tree build are redirected. +# The KVM sources do not differ between the Arch flavours of one version (the +# module srcversion is identical on linux and linux-cachyos-bore 7.2.3), so one +# source tree serves all of them. +# +# THE PIN: the sources are 7.2.3's. They build against any 7.2.x headers and +# are refused for anything else, so after a kernel upgrade past 7.2 the stock +# modules load silently and the three checks come back. Bump _kver here. + +pkgname=vfio-native-kvm-dkms +_pkgbase=vfio-native-kvm +_kver=7.2.3 +_tag=1.1.0 +pkgver=${_kver} +pkgrel=1 +pkgdesc="KVM modules patched to raise the exceptions the architecture specifies (DKMS, 7.2.x kernels)" +arch=('x86_64') +url="https://git.archworks.co/sandwich/vfio-native" +license=('GPL-2.0-only') +depends=('dkms') +makedepends=('git') +optdepends=('vfio-native: the setup and verification tooling') +provides=("${_pkgbase}") +conflicts=("${_pkgbase}") +install=${pkgname}.install +source=("git+${url}.git#tag=v${_tag}" + "https://cdn.kernel.org/pub/linux/kernel/v7.x/linux-${_kver}.tar.xz" + 'dkms.conf' + 'dkms-out-of-tree.patch' + 'kvm-native.hook') +noextract=("linux-${_kver}.tar.xz") +sha256sums=('SKIP' + '8ba259e8e7b13ec6ef0941c8a39ad90b24bd4a4d6c0010ba6bafb794550ecd03' + 'SKIP' + 'SKIP' + 'SKIP') + +prepare() { + tar -xf "linux-${_kver}.tar.xz" --wildcards \ + "linux-${_kver}/arch/x86/kvm/*" "linux-${_kver}/virt/kvm/*" + cd "linux-${_kver}" + for p in "${srcdir}"/vfio-native/patches/kvm/000[1234]-KVM-*.patch \ + "${srcdir}"/vfio-native/patches/kvm/EXPERIMENTAL-0006-*.patch; do + msg2 "applying ${p##*/}" + patch -Np1 -i "$p" + done + patch -Np1 -i "${srcdir}/dkms-out-of-tree.patch" +} + +package() { + local dest="${pkgdir}/usr/src/${_pkgbase}-${pkgver}" + install -dm755 "${dest}/arch/x86" "${dest}/virt" + cp -r "linux-${_kver}/arch/x86/kvm" "${dest}/arch/x86/" + cp -r "linux-${_kver}/virt/kvm" "${dest}/virt/" + sed "s/@PKGVER@/${pkgver}/" dkms.conf > "${dest}/dkms.conf" + install -Dm644 kvm-native.hook "${pkgdir}/usr/share/libalpm/hooks/90-vfio-native-kvm.hook" +} diff --git a/packaging/vfio-native-kvm-dkms/dkms-out-of-tree.patch b/packaging/vfio-native-kvm-dkms/dkms-out-of-tree.patch new file mode 100644 index 0000000..36289a8 --- /dev/null +++ b/packaging/vfio-native-kvm-dkms/dkms-out-of-tree.patch @@ -0,0 +1,27 @@ +Build arch/x86/kvm as an external module: the include path and the shared +virt/kvm makefile must come from the module tree, not from the headers. +--- a/arch/x86/kvm/Makefile ++++ b/arch/x86/kvm/Makefile +@@ -1,9 +1,9 @@ + # SPDX-License-Identifier: GPL-2.0 + +-ccflags-y += -I $(srctree)/arch/x86/kvm ++ccflags-y += -I $(src) + ccflags-$(CONFIG_KVM_WERROR) += -Werror + +-include $(srctree)/virt/kvm/Makefile.kvm ++include $(src)/../../../virt/kvm/Makefile.kvm + + kvm-y += x86.o emulate.o irq.o lapic.o cpuid.o pmu.o mtrr.o \ + debugfs.o mmu/mmu.o mmu/page_track.o mmu/spte.o +--- a/arch/x86/kvm/trace.h ++++ b/arch/x86/kvm/trace.h +@@ -1968,7 +1968,7 @@ + #endif /* _TRACE_KVM_H */ + + #undef TRACE_INCLUDE_PATH +-#define TRACE_INCLUDE_PATH ../../arch/x86/kvm ++#define TRACE_INCLUDE_PATH . + #undef TRACE_INCLUDE_FILE + #define TRACE_INCLUDE_FILE trace + diff --git a/packaging/vfio-native-kvm-dkms/dkms.conf b/packaging/vfio-native-kvm-dkms/dkms.conf new file mode 100644 index 0000000..e751073 --- /dev/null +++ b/packaging/vfio-native-kvm-dkms/dkms.conf @@ -0,0 +1,16 @@ +PACKAGE_NAME="vfio-native-kvm" +PACKAGE_VERSION="@PKGVER@" +# 7.2.3's KVM sources build against 7.2.x headers only; refuse anything else +# loudly instead of producing a module that will not load. +BUILD_EXCLUSIVE_KERNEL="^7\.2\." +MAKE[0]="make -C /usr/lib/modules/${kernelver}/build M=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build/arch/x86/kvm modules" +BUILT_MODULE_NAME[0]="kvm" +BUILT_MODULE_LOCATION[0]="arch/x86/kvm" +DEST_MODULE_LOCATION[0]="/updates" +BUILT_MODULE_NAME[1]="kvm-amd" +BUILT_MODULE_LOCATION[1]="arch/x86/kvm" +DEST_MODULE_LOCATION[1]="/updates" +BUILT_MODULE_NAME[2]="kvm-intel" +BUILT_MODULE_LOCATION[2]="arch/x86/kvm" +DEST_MODULE_LOCATION[2]="/updates" +AUTOINSTALL="yes" diff --git a/packaging/vfio-native-kvm-dkms/kvm-native.hook b/packaging/vfio-native-kvm-dkms/kvm-native.hook new file mode 100644 index 0000000..b12e471 --- /dev/null +++ b/packaging/vfio-native-kvm-dkms/kvm-native.hook @@ -0,0 +1,16 @@ +# Warns when a kernel outside the DKMS tree's 7.2.x range is installed. +# +# Without this the failure is silent: DKMS skips the build, the stock modules +# load, the guest boots normally, and the only symptom is three detections +# coming back. +[Trigger] +Operation = Install +Operation = Upgrade +Type = Path +Target = usr/lib/modules/*/vmlinuz + +[Action] +Description = Checking that vfio-native-kvm-dkms can build for the new kernel... +When = PostTransaction +NeedsTargets +Exec = /usr/bin/sh -c 'while read -r p; do k=${p#usr/lib/modules/}; k=${k%/vmlinuz}; case "$k" in 7.2.*) ;; *) echo ">>> vfio-native-kvm-dkms carries 7.2.3 sources and will not build for $k."; echo ">>> Stock KVM loads there and SVM_EXCEPTIONS, KVM_INTERCEPTION and DBVM come back.";; esac; done' diff --git a/packaging/vfio-native-kvm-dkms/vfio-native-kvm-dkms.install b/packaging/vfio-native-kvm-dkms/vfio-native-kvm-dkms.install new file mode 100644 index 0000000..5dcec4f --- /dev/null +++ b/packaging/vfio-native-kvm-dkms/vfio-native-kvm-dkms.install @@ -0,0 +1,24 @@ +post_install() { + cat <<'MSG' + + vfio-native-kvm-dkms: DKMS builds the patched kvm, kvm-amd and kvm-intel + for every installed 7.2.x kernel with headers, into updates/, which modprobe + prefers over the in-tree modules. They are NOT loaded yet. + + With every VM shut down: + + sudo modprobe -r kvm_amd kvm && sudo modprobe kvm_amd # or kvm_intel + + Confirm BOTH took - checking one passes on a stale build of the other: + + cat /sys/module/kvm/srcversion /sys/module/kvm_amd/srcversion + modinfo -F srcversion kvm kvm_amd + + THE PIN: these are 7.2.3's KVM sources. DKMS refuses to build them for a + kernel outside 7.2.x, the stock modules load silently, and three detections + come back. A pacman hook warns when that happens. + +MSG +} +post_upgrade() { post_install; } +post_remove() { echo " Stock KVM loads on the next boot, or reload the modules now."; } diff --git a/packaging/vfio-native-qemu/.SRCINFO b/packaging/vfio-native-qemu/.SRCINFO new file mode 100644 index 0000000..7294296 --- /dev/null +++ b/packaging/vfio-native-qemu/.SRCINFO @@ -0,0 +1,46 @@ +pkgbase = vfio-native-qemu + pkgdesc = QEMU 11.1.1 with the vfio-native platform-identity patches, in /opt/qemu-native + pkgver = 11.1.1 + pkgrel = 1 + url = https://git.archworks.co/sandwich/vfio-native + arch = x86_64 + license = GPL-2.0-only + makedepends = git + makedepends = meson + makedepends = ninja + makedepends = python + depends = glib2 + depends = pixman + depends = zlib + depends = zstd + depends = libaio + depends = liburing + depends = libcap-ng + depends = libseccomp + depends = gnutls + depends = nettle + depends = libslirp + depends = spice + depends = spice-protocol + depends = libepoxy + depends = virglrenderer + depends = mesa + depends = libjpeg-turbo + depends = libpng + depends = libusb + depends = usbredir + depends = numactl + depends = libxkbcommon + depends = libgcrypt + depends = libtasn1 + depends = lzo + depends = snappy + depends = pipewire + optdepends = vfio-native: the setup tooling that points a domain at this build + options = !strip + source = git+https://git.archworks.co/sandwich/vfio-native.git#tag=v1.1.0 + source = https://download.qemu.org/qemu-11.1.1.tar.xz + sha256sums = SKIP + sha256sums = 079ffbff8a7111bbc89022107cbabf3bbfd614d5fc9d7cc675991196aca12482 + +pkgname = vfio-native-qemu diff --git a/packaging/vfio-native-qemu/PKGBUILD b/packaging/vfio-native-qemu/PKGBUILD new file mode 100644 index 0000000..73deb4d --- /dev/null +++ b/packaging/vfio-native-qemu/PKGBUILD @@ -0,0 +1,50 @@ +# Maintainer: Sandwich +# +# QEMU 11.1.1 with the platform-identity patches from vfio-native, installed +# under /opt/qemu-native so the system qemu package is never touched. Clears +# FIRMWARE, VIRTUAL_DISK, DISK_SERIAL, PCI_VENDOR, DEVICES, QEMU_FW_CFG and +# QEMU_USB. Only the x86_64 system emulator is built. + +pkgname=vfio-native-qemu +_qver=11.1.1 +_tag=1.1.0 +pkgver=${_qver} +pkgrel=1 +pkgdesc="QEMU ${_qver} with the vfio-native platform-identity patches, in /opt/qemu-native" +arch=('x86_64') +url="https://git.archworks.co/sandwich/vfio-native" +license=('GPL-2.0-only') +depends=('glib2' 'pixman' 'zlib' 'zstd' 'libaio' 'liburing' 'libcap-ng' 'libseccomp' + 'gnutls' 'nettle' 'libslirp' 'spice' 'spice-protocol' 'libepoxy' 'virglrenderer' + 'mesa' 'libjpeg-turbo' 'libpng' 'libusb' 'usbredir' 'numactl' 'libxkbcommon' + 'libgcrypt' 'libtasn1' 'lzo' 'snappy' 'pipewire') +makedepends=('git' 'meson' 'ninja' 'python') +optdepends=('vfio-native: the setup tooling that points a domain at this build') +options=('!strip') +source=("git+${url}.git#tag=v${_tag}" + "https://download.qemu.org/qemu-${_qver}.tar.xz") +sha256sums=('SKIP' + '079ffbff8a7111bbc89022107cbabf3bbfd614d5fc9d7cc675991196aca12482') + +prepare() { + cd "qemu-${_qver}" + for p in "${srcdir}"/vfio-native/patches/qemu/0[1-8]-*.patch; do + msg2 "applying ${p##*/}" + patch -Np1 --no-backup-if-mismatch -i "$p" + done +} + +build() { + cd "qemu-${_qver}" + mkdir -p build && cd build + ../configure --prefix=/opt/qemu-native --target-list=x86_64-softmmu \ + --enable-kvm --enable-spice --enable-opengl --enable-virglrenderer \ + --enable-tpm --enable-slirp --disable-docs --disable-werror --disable-user \ + --disable-gtk --disable-sdl + ninja +} + +package() { + cd "qemu-${_qver}/build" + DESTDIR="${pkgdir}" ninja install +} diff --git a/packaging/vfio-native/.SRCINFO b/packaging/vfio-native/.SRCINFO new file mode 100644 index 0000000..c78dd6d --- /dev/null +++ b/packaging/vfio-native/.SRCINFO @@ -0,0 +1,23 @@ +pkgbase = vfio-native + pkgdesc = Present a libvirt guest as a self-consistent physical machine, and tune it + pkgver = 1.1.0 + pkgrel = 1 + url = https://git.archworks.co/sandwich/vfio-native + install = vfio-native.install + arch = any + license = GPL-2.0-only + makedepends = git + depends = libvirt + depends = qemu-base + depends = python + depends = openssh + depends = bash + depends = ethtool + optdepends = mingw-w64-gcc: build the in-guest benchmark and the TIMER probe + optdepends = cpupower: set the host CPU governor + optdepends = vfio-native-kvm-dkms: patched KVM modules for the full level + optdepends = vfio-native-qemu: patched QEMU for the full level + source = git+https://git.archworks.co/sandwich/vfio-native.git#tag=v1.1.0 + sha256sums = SKIP + +pkgname = vfio-native diff --git a/packaging/vfio-native/PKGBUILD b/packaging/vfio-native/PKGBUILD new file mode 100644 index 0000000..1443828 --- /dev/null +++ b/packaging/vfio-native/PKGBUILD @@ -0,0 +1,51 @@ +# Maintainer: Sandwich +# +# Platform-fidelity corrections and VFIO tuning for libvirt guests. +# +# Three packages: +# vfio-native scripts, patches, ACPI tables and the benchmark +# vfio-native-kvm-dkms the patched KVM modules, rebuilt by DKMS per kernel +# vfio-native-qemu QEMU 11.1.1 with the platform-identity patches, in /opt + +pkgname=vfio-native +pkgver=1.1.0 +pkgrel=1 +pkgdesc="Present a libvirt guest as a self-consistent physical machine, and tune it" +arch=('any') +url="https://git.archworks.co/sandwich/vfio-native" +license=('GPL-2.0-only') +depends=('libvirt' 'qemu-base' 'python' 'openssh' 'bash' 'ethtool') +makedepends=('git') +optdepends=('mingw-w64-gcc: build the in-guest benchmark and the TIMER probe' + 'cpupower: set the host CPU governor' + 'vfio-native-kvm-dkms: patched KVM modules for the full level' + 'vfio-native-qemu: patched QEMU for the full level') +install=vfio-native.install +source=("git+${url}.git#tag=v${pkgver}") +sha256sums=('SKIP') + +package() { + cd "${srcdir}/${pkgname}" + install -Dm755 scripts/setup-vm.sh "${pkgdir}/usr/bin/vm-native-setup" + install -Dm755 scripts/verify-perf.sh "${pkgdir}/usr/bin/vm-native-verify" + install -Dm755 scripts/gpu-passthrough.sh "${pkgdir}/usr/bin/vm-native-gpu" + + local share="${pkgdir}/usr/share/vfio-native" + install -Dm644 bench/vmbench.c "${share}/bench/vmbench.c" + install -Dm644 bench/timerprobe.c "${share}/bench/timerprobe.c" + install -Dm755 scripts/install-modules.sh "${share}/scripts/install-modules.sh" + install -Dm755 scripts/restore-stock-kvm.sh "${share}/scripts/restore-stock-kvm.sh" + install -Dm755 scripts/generate-tables.py "${share}/scripts/generate-tables.py" + install -Dm644 -t "${share}/acpi" acpi/*.aml acpi/*.dsl + install -dm755 "${share}/patches" + cp -r patches/. "${share}/patches/" + install -Dm644 -t "${share}/doc" README.md docs/*.md + + # libvirt runs every executable in qemu.d/ after the main qemu hook, so + # this coexists with whatever hook the host already has. + install -Dm755 scripts/libvirt-hook-cpu-isolation.sh \ + "${pkgdir}/etc/libvirt/hooks/qemu.d/10-cpu-isolation.sh" + # e1000e offloads corrupt integrity-checked traffic on libvirt taps; host-wide by nature + install -Dm644 scripts/99-vfio-native-vnet-offload.rules \ + "${pkgdir}/usr/lib/udev/rules.d/99-vfio-native-vnet-offload.rules" +} diff --git a/packaging/vfio-native/vfio-native.install b/packaging/vfio-native/vfio-native.install new file mode 100644 index 0000000..370193c --- /dev/null +++ b/packaging/vfio-native/vfio-native.install @@ -0,0 +1,83 @@ +post_install() { + cat <<'MSG' + + vfio-native installed. + + Three commands. You do not need to read anything else. + + vm-native-setup configure a libvirt domain + vm-native-verify check it is actually working + vm-native-gpu set up GPU passthrough + + --------------------------------------------------------------------------- + Getting a corrected, tuned guest: + + 1. In the Windows guest, once - turn off its own hypervisor. This is the + single most valuable change and it makes the VM FASTER: + + bcdedit /set hypervisorlaunchtype off + Disable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-All -NoRestart + + Reboot twice. Uninstall the QEMU and SPICE guest agents. + + 2. Move the guest disk to emulated NVMe (bus='nvme'), and give it a . + + 3. On the host, once: + + sudo cpupower frequency-set -g performance + + 4. Shut the domain down and run: + + vm-native-setup + + It detects your CPU layout - AMD CCDs or Intel P/E cores - and asks four + questions, all with sensible defaults. It pins vCPUs onto real SMT pairs, + keeps the emulator off the vCPU cores, and writes the corrected CPU and + firmware settings. It backs the domain up first and prints how to revert. + + 5. Start the guest, let it idle a minute, then: + + vm-native-verify + + --------------------------------------------------------------------------- + Fidelity levels, asked in step 4: + + tuned performance tuning only, no platform corrections + native tuning + domain-level corrections. No patched binaries, no upkeep. + full lowest score. Needs vfio-native-kvm and a patched QEMU, and a + module rebuild after each kernel update. + + 'native' is a good default if you would rather not maintain anything. + + A udev rule (99-vfio-native-vnet-offload.rules) turns TX offloads off on every + libvirt tap as it appears. The emulated e1000e NIC corrupts integrity-checked + traffic with them on; SSH to the guest fails with "Corrupted MAC on input". + It applies to every VM on the host; the throughput cost on a host<->guest + link is not measurable. + + A libvirt hook is installed at /etc/libvirt/hooks/qemu.d/10-cpu-isolation.sh. + It keeps host processes off the cores the guest is pinned to, automatically, + whenever the guest runs. Measured: stalls over 10us in a 10 second window fell + from ~100 to ~36. If your libvirt does not read qemu.d/, chain it from your + existing /etc/libvirt/hooks/qemu. + + --------------------------------------------------------------------------- + Leave the host at least 4 physical cores. Windows calibrates the TSC once at + boot, and if the host cannot schedule the guest's vCPU threads cleanly while + that runs, Windows abandons the TSC and every QueryPerformanceCounter call + costs ~1300ns instead of ~15 for the rest of that boot. Software that polls + the clock in a tight loop makes that call thousands of times a second, so it + shows up as constant hitching in an interactive session. 24 of 32 threads is + reliable, 32 of 32 is not, and vm-native-setup warns you when you go under + the margin. + + It is a race, so one slow reading proves nothing. If vm-native-verify shows + QPC over 1000ns, reboot and measure again before changing any setting. + + Patches, grouped by the detection each one clears: + /usr/share/vfio-native/patches/README.md + +MSG +} + +post_upgrade() { post_install; }