Software developers, kernel engineers, and systems performance analysts running virtualised test environments frequently rely on hardware performance counters to profile execution bottlenecks. Profilers such as Linux perf, Intel VTune, Visual Studio Diagnostic Tools, and Windows Performance Recorder (WPR) sample architectural CPU events—including instruction retired rates, branch mispredictions, L1/L2/L3 cache misses, and pipeline stalls.
By default, the Windows 11 Hyper-V hypervisor intercepts and masks hardware Performance Monitoring Unit (PMU) registers to isolate host CPU execution and maintain workload security. When developers attempt to run hardware event sampling inside a guest virtual machine, profiling tools report that hardware performance counters are unsupported or unavailable. Using PowerShell, administrators can virtualise and expose host PMU counters directly to guest virtual machines.
Understanding Hyper-V PMU Virtualization
The Hyper-V hypervisor supports passing architectural performance counters to guest processors through the Set-VMProcessor cmdlet using the -Perfmon parameter. Enabling virtual PMU allows the guest operating system kernel to access hardware Model-Specific Registers (MSRs) corresponding to CPU execution counters:
- Pmu: Exposes standard architectural hardware performance counters (such as instructions retired, CPU clock unhalted cycles, and branch execution metrics).
- Lbr: Exposes Last Branch Record (LBR) execution tracking registers on supported Intel processors, enabling accurate branch prediction debugging and call-stack reconstruction.
- Ipt: Exposes Intel Processor Trace on supported architectures for full instruction trace capture.
Prerequisites and Compatibility Requirements
Before exposing hardware performance monitoring counters to a Hyper-V guest, verify the following prerequisites:
- Windows 11 Host: The host system must be running Windows 11 Pro, Enterprise, or Education with the Hyper-V role enabled.
- Hardware Virtualization: Intel VT-x with Extended Page Tables (EPT) or AMD-V with Nested Page Tables (NPT) must be enabled in the system UEFI/BIOS.
- VM Configuration Version: The guest virtual machine must use configuration version 9.0 or higher (Generation 2 virtual machines recommended).
- VM State: The target virtual machine must be powered off before modifying CPU architectural features.
Checking VM State and Current PMU Configuration
Open an elevated PowerShell prompt on Windows 11 and check the power state and configuration version of the target virtual machine:
Get-VM -Name "DevVM-Ubuntu" | Select-Object Name, State, Version, Generation
If the virtual machine is running, shut it down gracefully:
Stop-VM -Name "DevVM-Ubuntu"
Inspect the current processor performance monitoring configuration:
Get-VMProcessor -VMName "DevVM-Ubuntu" | Select-Object VMName, Count, Perfmon
In default configurations, the Perfmon property is empty or returns {}.
Enabling Virtual PMU Hardware Counters
To enable standard Performance Monitoring Unit counters for the virtual machine, pass Pmu to the -Perfmon array parameter:
Set-VMProcessor -VMName "DevVM-Ubuntu" -Perfmon @("Pmu")
On supported Intel hardware platforms where advanced call-stack profiling and Last Branch Recording are needed alongside PMU counters, expose both features simultaneously:
Set-VMProcessor -VMName "DevVM-Ubuntu" -Perfmon @("Pmu", "Lbr")
Confirm that the performance monitoring flags have been assigned successfully:
(Get-VMProcessor -VMName "DevVM-Ubuntu").Perfmon
The command returns Pmu (or Pmu and Lbr).
Starting the Virtual Machine and Verifying PMU in Guest OS
Start the virtual machine using PowerShell:
Start-VM -Name "DevVM-Ubuntu"
Once the guest operating system has booted, verify that hardware performance counters are detected and functional:
Verifying in Linux Guests (Ubuntu / Debian / RHEL)
Log in to the Linux guest terminal and check kernel dmesg logs for performance counter detection:
dmesg | grep -i pmu
The kernel will report available performance monitoring counters (for example, Performance Events: PMU driver: intel_pmu or amd_pmu). Run a test benchmark using perf stat:
perf stat ls -la /usr/bin
The output displays architectural counters including cycles, instructions retired, branch misses, and page faults:
Performance counter stats for 'ls -la /usr/bin':
4.25 msec task-clock # 0.852 CPUs utilized
1 context-switches # 235.294 /sec
0 cpu-migrations # 0.000 /sec
142 page-faults # 33.412 K/sec
14,520,180 cycles # 3.416 GHz
18,924,105 instructions # 1.30 insn per cycle
3,812,400 branches # 897.035 M/sec
85,210 branch-misses # 2.24% of all branches
Verifying in Windows Guests
Inside a Windows 11 guest virtual machine, run Windows Performance Recorder (WPR) or check CPU counter sampling using Sysinternals Coreinfo:
coreinfo64.exe -v
The utility confirms that hardware performance monitoring and architectural MSRs are accessible within the guest OS.
Disabling PMU Counter Virtualization
If hardware profiling is complete and you wish to isolate the guest CPU registers to the default security state, stop the virtual machine and clear the Perfmon collection:
Stop-VM -Name "DevVM-Ubuntu"
Set-VMProcessor -VMName "DevVM-Ubuntu" -Perfmon @()
Start-VM -Name "DevVM-Ubuntu"
By enabling PMU counter profiling through PowerShell, developers can accurately assess code efficiency, algorithmic bottlenecks, and memory access patterns within isolated Hyper-V development environments.