I had a long post WIP about my detailed findings, but it's no more needed, as the proposed solution will not be effective (check the end).
So just a short recap:
I can confirm that both platforms (AMD + Intel) are affected.
Since Win11-24H2 and Windows Server 2025, MS made a huge changes in terms of extensive abuse of Hyper-V "Enlightenments" calls.
This
feature is here to Windows VM instances believe they're running on Hyper-V compatible hypervisor and can use some specific enhancements.
Up to Win11-23H2 and Window Server 2022, so far so good. No abuse, C3 states are working, Turbo Boost is happy.
But since the latest Windows builds, this
complex HV framework around synthetic timers is "firing for effect".
So what's inside: When VM boots, WinOS is checking CPU flags like:
Code:
hv_ipi, hv_relaxed, hv_reset, hv_runtime, hv_spinlocks=0x1fff, hv_stimer, hv_synic, hv_time, hv_vapic, hv_vpindex
And when found ("Wow, I'm running on HV-compatible machine!"), it'll activate (now harmful) "bad boys", in our case especially
Hyper-V synthetic timers (STIMER0) and Hyper-V APIC-EOI MSR for its timer/interrupt machinery on KVM – even when the VM is “idle”.
OK, but how to block it? I don't know, because it's activated automatically, based on Win-VM version and BIOS type (
PVE/QEMU/CPU Config).
I wasn't able to deactivate this stuff in any way, because:
-- nothing like "hv=off" switch in CPU params (to enforce complete HV flags deactivation)
-- nothing like "args: -cpu host,-hv_ipi,-hv_relaxed,-hv_reset,-hv_runtime,-hv_spinlocks,-hv_stimer,-hv_synic,-hv_time,-hv_vapic,-hv_vpindex" worked for me
Based on this,
I wasn't able to confirm that disabling synthetic HV timers will solve this problem, but now I know it will not.
I've found that either it's on Intel (
MSR_WRITE), or on AMD (
MSR), in both cases the final root cause is the same, i.e. extensive abuse of these
Hyper-V Enlightenments calls:
- STIMER0_CONFIG (0x400000b0)
- STIMER0_COUNT (0x400000b1)
- HV_X64_MSR_EOI (0x40000070)
- HV_X64_MSR_ICR (0x40000071)
Some of the commands used:
Code:
perf kvm --host stat live
perf record -a -g -e kvm:kvm_exit -- sleep 5
perf script | grep -i msr | head -n 200
perf record -a -g -e kvm:kvm_msr -- sleep 5
perf script | grep -i msr | head -n 200
And then you'll see something like:
Code:
msr_write 400000b0 = 0x30008 / 0x3000a / ...
msr_write 400000b1 = <big changing values> / 0x43f8
msr_write 40000070 = 0x0
msr_write 40000071 = 0x2f / 0x40000000000002f / 0x20000000000002f
These are all
Hyper-V synthetic MSRs:
- 0x40000070 → HV_X64_MSR_EOI
Fast APIC EOI MSR (End Of Interrupt).
- 0x40000071 → HV_X64_MSR_ICR
APIC ICR (Interrupt Command Register) in MSR form – used to send IPIs via Hyper-V.
- 0x400000B0 → HV_X64_MSR_STIMER0_CONFIG
Configuration of synthetic timer 0 (enable/periodic/oneshot, vector, etc.).
- 0x400000B1 → HV_X64_MSR_STIMER0_COUNT
Expiration time / counter for synthetic timer 0.
So the pattern is now clearly:
- Configure synthetic timer 0 (
msr_write 400000b0)
- Program synthetic timer 0’s expiration time (
msr_write 400000b1)
- Signal End Of Interrupt via SynIC EOI MSR (
msr_write 40000070)
- Occasionally program the Hyper-V ICR (
msr_write 40000071)
All of these are
exclusively Hyper-V enlightenment paths – they don't exist on bare metal, only when Windows thinks it’s on a Hyper-V-capable hypervisor.
So if you've read this far, you're probably thinking: this guy decomposed the problem, so it should be good!
Yes and not, because @lovesyk (author of that QEMU thread) revealed
here, that:
Disabling some of those flags like stimer will however increase idle CPU consumption by more than 24H2 does so even if some of those are able to work around whatever changed in 24H2, I'll probably be a net loss in the end regarding CPU load.
Based on this, I am giving up on my further research. I don't know what else to explore or how to do it. I'm sorry.
I think now it's your turn, I cannot help you more:
@fweber,
@t.lamprecht,
@fabian,
@aaron,
@fiona
CC (just for curiosity):
@benyamin,
@JonKohler