Note
Target single-node homelab setups using AVX2-capable processors.
Tip
Always install the latest CPU microcode for your CPU.
Details: https://pve.proxmox.com/pve-docs/pve-admin-guide.html#sysadmin_firmware_cpu
For basic Windows guests without WSL2, Hyper-V, or VBS enabled, use named QEMU CPU models corresponding to your hardware. For example, if you have Skylake CPUs, use Skylake-Client-v4.
Note
Using the default host model in Proxmox VE will result in the following QEMU -cpu argument when starting the Windows VM:
qm show VMID --pretty
-cpu 'host,hv_ipi,hv_relaxed,hv_reset,hv_runtime,hv_spinlocks=0x1fff,hv_stimer,hv_synic,hv_time,hv_vapic,hv_vpindex,+kvm_pv_eoi,+kvm_pv_unhalt'
This is fine as long as you don't have any of these enabled in your Windows VM: WSL2, Hyper-V, or VBS.
To achieve the best performance with Hyper-V, WSL2, and VBS enabled, we need to create a custom CPU model:
- Create the file
/etc/pve/virtual-guest/cpu-models.confwith the following content:
# Proxmox VE Custom CPU Models
cpu-model: amd-hide-vm-for-windows
flags -hypervisor;+invtsc;+hv-frequencies;+hv-reenlightenment;+hv-emsr-bitmap;+hv-tlbflush-direct
phys-bits host
hidden 1
hv-vendor-id amd
reported-model host
cpu-model: intel-hide-vm-for-windows
flags -hypervisor;+invtsc;+hv-frequencies;+hv-evmcs;+hv-reenlightenment;+hv-emsr-bitmap;+hv-tlbflush-direct
phys-bits host
hidden 1
hv-vendor-id intel
reported-model host
- Select either
amd-hide-vm-for-windowsorintel-hide-vm-for-windowsCPU model in the Proxmox web GUI, depending on your processor.
Note
Using these custom CPU models will result in the following QEMU -cpu argument when starting the Windows VM:
qm show VMID --pretty
-cpu 'host,+hv-emsr-bitmap,+hv-evmcs,+hv-frequencies,+hv-reenlightenment,+hv-tlbflush-direct,hv_ipi,hv_relaxed,hv_reset,hv_runtime,hv_spinlocks=0x1fff,hv_stimer,hv_synic,hv_time,hv_vapic,hv_vendor_id=intel,hv_vpindex,-hypervisor,+invtsc,kvm=off,+kvm_pv_eoi,+kvm_pv_unhalt,host-phys-bits=true'
Tip
With these custom CPU models configured, you can now run Android emulators very smoothly inside your Windows VM. You need to have a GPU passthrough to the VM and enable Hyper-V:
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
Tested with MEmu Play.
- Always use named QEMU CPU models instead of
hostpassthrough - The
hostpassthrough can result in ~30% slower single-core and ~44% slower multi-core performance compared to named QEMU CPU models
The macOS kernel checks CPUID model and vendor during boot. When using CPU models like SapphireRapids or GraniteRapids (which were never shipped in real Macs), you must override the CPUID model to a known Mac-compatible model. While this can be configured in OpenCore's config.plist (Kernel > Emulate Properties), QEMU-level configuration is recommended.
Tip
CPUID Models Used in Recent Intel Macs:
| Generation | CPUID Model |
|---|---|
| Kaby Lake / Coffee Lake | 158 |
| Comet Lake | 165 |
Example Configuration:
qm set <VMID> --args "-cpu SapphireRapids,vendor=GenuineIntel,model=165"
When using named QEMU CPU models like Skylake-Client-v4, the guest OS will report the CPU as Intel Core Processor (Skylake, IBRS, no TSX). You can customize this using the model-id parameter.
For modern CPUs, you can spoof the reported base speed using the tsc-frequency parameter.
To spoof a 10GHz CPU with the brand name "Intel Core i8-8800KS":
# Using global parameters
qm set <VMID> --args "-global cpu.model-id='Intel Core i8-8800KS' -global cpu.tsc-frequency=10000000000"
Many more CPU parameters are available, including:
family=andmodel=- CPU family and model numbersstepping=andlevel=- CPU stepping and CPUID levelhost-cache-info=on- Pass through host cache information
For complete details, see: https://github.com/qemu/qemu/blob/master/target/i386/cpu.c