Files
vfio-native/patches/README.md
T

7.4 KiB

Patchsets, by the detection each one clears

Every patch here is grouped by the VMAware check it targets, so a patchset can be taken or left on its own. Apply from the relevant source root with patch -p1 < <file>.

KVM - kvm/

Built against kernel 7.2.x. Builds as arch/x86/kvm only, about five minutes; no full kernel build is needed. See packaging/ for a PKGBUILD that does it and keeps it rebuilt.

Patch Clears What it does
0001-KVM-SVM-intercept-GP-when-guest-EFER.SVME-is-clear SVM_EXCEPTIONS Closes a FIXME KVM already carries: a CPL3 SVM instruction faults #GP where hardware gives #UD.
0002-KVM-x86-emulator-UD-not-GP-for-VMCALL-at-CPL-0 KVM_INTERCEPTION Adds PrivUD so VMCALL at CPL>0 raises #UD like hardware.
0003-KVM-x86-UD-for-KVM-hypercalls-issued-at-CPL-0 KVM_INTERCEPTION A CPL>0 hypercall raised no exception at all; now raises #UD.
0004-KVM-SVM-intercept-ICEBP-and-skip-it-before-injecting-its-DB DBVM SVM re-injected the ICEBP #DB with RIP still on the F1 byte; VMX and hardware report the next instruction.
0005-KVM-selftests-verify-ICEBP-DB-reports-RIP-past-the-ICEBP - The selftest for 0004: fails on unpatched SVM, passes with it.
EXPERIMENTAL-0006-runtime-cpuid-passthrough TIMER Drops CPUID and RDPRU interception on a 1:1-pinned vCPU and reprograms the AMD Processor Name String MSRs so raw CPUID still returns the declared brand. Opt-in via the cpuid_passthrough module parameter.

0002 and 0003 are a pair. Either alone leaves KVM_INTERCEPTION standing, because the check tries two stubs and only reports the first one that misbehaves.

The first five are written to be acceptable upstream: they make KVM match the architecture rather than add anything on top of it, each carries its rationale in the commit message, and all four pass checkpatch.pl --strict. 0000-cover-letter.txt is the series cover letter. They have been tested on AMD only; 0002 and 0003 are vendor-neutral code and the Intel reasoning is in the cover letter.

EXPERIMENTAL-0006 is built into the vfio-native-kvm-dkms package but off by default. It removes the cost the TIMER instruction-latency detector measures, and with it the guest reads raw host CPUID, so it applies itself only to vCPU threads confined to exactly one CPU and must be enabled through the cpuid_passthrough module parameter after the guest has booted. docs/ANALYSIS.md has the measurements and the constraints.

QEMU - qemu/

Against QEMU v11.1.2. Apply in numeric order.

Patch Clears
01-firmware FIRMWARE - ACPI link-device names, PNP0A06 stubs, FADT C-state latencies
02-disk-identity VIRTUAL_DISK, DISK_SERIAL - QEMU HARDDISK, empty serials, SCSI inquiry strings
03-pci-ids PCI_VENDOR, DEVICES - Red Hat/QEMU vendor and subsystem IDs, ICH9 layout
04-fw-cfg QEMU_FW_CFG - the fw_cfg device signature
05-usb-identity QEMU_USB - USB HID descriptor strings, and the usb-net CDC/RNDIS device-identity strings (keeps the 0525:a4a1 CDC id so generic CDC-ECM drivers still bind it)
06-audio DEVICES - HDA codec and controller identity
07-edid none. Carried for other detectors; VMAware does not read EDID.
08-cpu-misc none. CPU feature plumbing and one upstream backport.
09-firmware-chain FIRMWARE - the DSDT links current VMAware added after 01-firmware
10-smbios CTYPE, SMBIOS_VM_BIT, FIRMWARE - what QEMU's synthesised SMBIOS leaks: chassis type Other, the type 0 VM bit, pc-q35 default strings; adds -smbios type=3,chassis-type=N
11-macos-cpu-hotplug FIRMWARE - re-adds the \_SB.CPUS CPU objects macOS needs, with the CPU-hotplug I/O base 0x0CD8 hidden from the scanner (renamed _UID, Add()-split OperationRegion base) rather than removed

The numbered patches are the default series and score 0/85 on both VMAware HEAD and v2.8.1. 03-pci-ids scopes the virtio subsystem-id change so OVMF still binds virtio (its generic default goes to Intel/0, virtio devices keep the Red Hat subsystem ids their drivers and OVMF expect). It also leaves the ICH9 SATA controller at its stock slot 1f.2: OVMF locates the q35 AHCI there, so moving it broke first-boot for SATA-booted UEFI guests (macOS fell through to PXE) while buying nothing for the score - the dummy-SATA FIRMWARE tell needs both the D0FA name and _ADR 0x1F0002, and device 31's functions emit neither. See docs/ANALYSIS.md.

11-macos-cpu-hotplug makes the series universal: macOS boots (it needs the \_SB.CPUS.Cxxx objects from build_cpus_aml) and both VMAware builds still read bare metal, with no opt-in. The block's only tell, the 0x0CD8 CPU-hotplug port that v2.8.1 FIRMWARE byte-matches, is removed at the AML level without moving the port, so the same series boots Windows and Linux unchanged. The earlier opt-in split and the relocate-the-base approach are in "Approaches tried and rejected".

Apply in numeric order, then build with the prefix set to /opt so the system QEMU package is left alone:

for p in qemu/[0-9][0-9]-*.patch; do patch -p1 < "$p"; done
./configure --prefix=/opt/qemu-native --target-list=x86_64-softmmu
ninja -C build && ninja -C build install

Approaches tried and rejected - kept so they are not re-derived

Approach Result
Patched OVMF firmware (edk2) Builds, then hangs before console init at 100% CPU, cause undiagnosed. Stock OVMF is fine and costs only the boot-logo warning.
TSC compensation for TIMER (BetterTiming) No detection change, 6x slower boot.
CPUID leaf override (Hypervisor-Phantom) Halved the timing signature, still detected, and added a SINGLE_STEP detection.
Clearing INTERCEPT_CPUID outright Guest never boots.
Intercept clearing, minimal hypercall Triple fault, or no effect.
Opt-in macOS CPU block (optional/macos-cpu-hotplug) Worked but split the series in two; a macOS-capable build scored 2/85 on v2.8.1. Folded into 11 instead.
Relocating the CPU-hotplug I/O base off 0x0CD8 Clears the scanner but hangs every SMM/OVMF guest (macOS spins 10 cores at boot, Windows too): OVMF hardcodes 0x0CD8 in OvmfPkg and reads the register block directly. 11 keeps the port and hides only the AML operand.

TIMER has two detectors that OR together. The exception-latency one passes on stock KVM once it is measured the way VMAware measures it; the instruction-latency one is removable with EXPERIMENTAL-0006. docs/ANALYSIS.md has the measurements, including a direct reproduction of both in bench/timerprobe.c.

Identity values in these patches

Several patches carry a concrete make and model because no real machine leaves the field blank. Every one of them is a placeholder. Change them before you use this, or a detector gains a fingerprint shared by everyone who ran the same patch series.

Where Value Replace with
02-disk-identity disk serial S0123456789ABCD set <serial> on the disk in the domain XML; this fallback then never runs
02-disk-identity disk and optical drive model strings a drive you actually own, from lsblk -o NAME,MODEL
07-edid monitor vendor and model your own panel, from edid-decode < /sys/class/drm/*/edid

The SMBIOS values are not patched into QEMU at all - they are domain XML, taken from a real machine with dmidecode. Change every serial there too.