Modern microprocessors include dedicated Performance Monitoring Units (PMUs)—specialised hardware registers that count low-level CPU architectural events such as clock cycles, retired instructions, branch mispredictions, L1/L2/L3 cache misses, and pipeline stalls. In virtualised environments under Microsoft Hyper-V on Windows 11, the hypervisor defaults to hiding physical PMU registers from guest virtual machines to maintain workload isolation and prevent microarchitectural side-channel leakage. Consequently, software profilers running inside guest OS environments—including Linux perf, Windows Performance Recorder (WPR), Intel VTune, Visual Studio Diagnostics, and AMD µProf—fail to capture hardware execution metrics. By enabling hardware performance counter virtualization via PowerShell, developers and systems engineers can pass physical PMU capabilities directly into Hyper-V guest machines.
Understanding Hyper-V Virtualised PMU (vPMU) Architecture
Hyper-V supports architectural performance monitoring unit virtualization (vPMU) across Intel VT-x and AMD-V processors:
- Intel Processors: Implements architectural PMU v1, v2, and v3 counters, allowing guest operating systems to program Model-Specific Registers (MSRs) such as
IA32_PERFCTR0,IA32_PMC0-7, andIA32_FIXED_CTR0-2. - AMD Processors: Implements AMD Core Performance Monitor registers (
MSR0000_00C0throughMSR0000_00C3). - Hypervisor Trapping: When PMU virtualization is disabled, guest reads or writes to performance MSRs generate hypervisor traps (VM-exits) that return zeroes or throw general protection faults (
#GP). When enabled, Hyper-V context-switches the PMU state during guest entry and exit, allowing guest profilers to read hardware performance counters with native accuracy. - Live Migration Constraints: Because PMU capabilities depend on identical CPU microarchitectures, virtual machines with hardware performance counters enabled cannot be live-migrated to physical host nodes featuring differing CPU stepping or models.
Prerequisites and Compatibility Requirements
Before enabling PMU passthrough on a Hyper-V virtual machine in Windows 11:
- Host CPU: Intel Nehalem (or newer) or AMD Bulldozer/Zen (or newer) with virtualization extensions enabled in host UEFI/BIOS.
- Virtual Machine Generation: Compatible with both Generation 1 and Generation 2 virtual machines, though Generation 2 (UEFI) is strongly recommended.
- VM State: The target virtual machine must be powered off before altering CPU processor features. Attempting to modify processor properties on a running or saved-state VM will generate a PowerShell exception.
- Administrative Privileges: An elevated PowerShell session (Run as Administrator) is required.
Verifying Current Hardware Performance Counter Status
Launch an elevated PowerShell console on your Windows 11 host. Query the processor properties of your target virtual machine using the Get-VMProcessor cmdlet:
Get-VMProcessor -VMName "Ubuntu-DevVM" | Select-Object VMName, CompatibilityForOlderOperatingSystemsEnabled, HwPerfCounterStatus, Count
A typical default output shows:
VMName CompatibilityForOlderOperatingSystemsEnabled HwPerfCounterStatus Count
------ -------------------------------------------- ------------------- -----
Ubuntu-DevVM False Disabled 8
Notice that HwPerfCounterStatus is set to Disabled, indicating that guest profilers will have no access to the underlying processor PMU registers.
Enabling Guest Hardware Performance Counters with Set-VMProcessor
To pass architectural PMU registers to the virtual machine, ensure the VM is powered down and execute the Set-VMProcessor cmdlet with the -HwPerfCounterStatus parameter set to Enabled:
# Ensure VM is stopped
Stop-VM -VMName "Ubuntu-DevVM" -Force
# Enable virtualised PMU counters
Set-VMProcessor -VMName "Ubuntu-DevVM" -HwPerfCounterStatus Enabled
# Start the virtual machine
Start-VM -VMName "Ubuntu-DevVM"
To verify that the configuration applied successfully:
Get-VMProcessor -VMName "Ubuntu-DevVM" | Format-List VMName, HwPerfCounterStatus
Configuring Nested Virtualization Alongside Hardware Counters
Developers running Docker Desktop, WSL2, or nested hypervisors (such as KVM or QEMU) inside a Windows 11 Hyper-V VM frequently need both nested virtualization and hardware PMU counters active simultaneously. You can enable both properties in a single PowerShell command:
Stop-VM -VMName "Ubuntu-DevVM" -Force
# Enable both nested virtualization and hardware performance counters
Set-VMProcessor -VMName "Ubuntu-DevVM" `
-ExposeVirtualizationExtensions $true `
-HwPerfCounterStatus Enabled
Start-VM -VMName "Ubuntu-DevVM"
Verifying PMU Access Inside the Guest Operating System
Once the virtual machine starts, log in to the guest operating system to verify that the PMU registers are now detected and usable by system profilers.
Inside a Linux Guest VM
Execute dmesg and perf to verify hardware event support:
# Check kernel PMU driver initialization
dmesg | grep -i pmu
# Expected output: Performance Events: Intel architected/AMD PMU driver, ... PMU counters detected
# Test hardware performance profiling
perf stat -e cycles,instructions,cache-misses,branch-misses ls -la /usr
If PMU virtualization was disabled, perf stat would fail with <not supported> or exit with hardware counter initialization errors. With HwPerfCounterStatus Enabled, perf stat reports exact hardware counter values, IPC (instructions per cycle), and branch metrics.
Inside a Windows Guest VM
Inside a Windows 11 or Windows Server guest VM, open an elevated command prompt and profile a short task using Windows Performance Recorder (WPR) with CPU sampling counters:
wpr -start GeneralProfile -start CPU -filemode
timeout /t 5
wpr -stop C:\perf_trace.etl
Open the resulting ETL trace in Windows Performance Analyzer (WPA) to review hardware event sampling data.
Disabling Hardware Performance Counters
If you need to prepare the virtual machine for migration across heterogeneous hosts or restore default isolation boundaries:
Stop-VM -VMName "Ubuntu-DevVM" -Force
Set-VMProcessor -VMName "Ubuntu-DevVM" -HwPerfCounterStatus Disabled
Start-VM -VMName "Ubuntu-DevVM"
By using PowerShell’s Set-VMProcessor cmdlet to expose architectural PMU registers, developers and performance engineers can execute rigorous hardware profiling, benchmark algorithms, and diagnose compiler optimizations directly within Hyper-V virtual machines.