<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Open Source Tech blog]]></title><description><![CDATA[Open Source Tech blog]]></description><link>https://opensourcetechblog.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Mon, 09 Nov 2026 11:55:48 GMT</lastBuildDate><atom:link href="https://opensourcetechblog.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to fix Windows 11 VBS and WSL2 performance on Proxmox (and keep live migration working) ]]></title><description><![CDATA[As part of a larger effort to migrate our VDIs from VMware over to Proxmox, I recently hit an issue with Windows 11. Because both VBS and WSL2 rely heavily…]]></description><link>https://opensourcetechblog.hashnode.dev/how-to-fix-windows-11-vbs-and-wsl2-performance-on-proxmox-and-keep-live-migration-working</link><guid isPermaLink="true">https://opensourcetechblog.hashnode.dev/how-to-fix-windows-11-vbs-and-wsl2-performance-on-proxmox-and-keep-live-migration-working</guid><dc:creator><![CDATA[robert]]></dc:creator><pubDate>Sun, 19 Jul 2026 13:32:01 GMT</pubDate><content:encoded><![CDATA[<p>As part of a larger effort to migrate our VDIs from VMware over to Proxmox, I recently hit an issue with Windows 11.</p>
<p>Because both VBS and WSL2 rely heavily on nested virtualization (requiring the host CPU type), they add a massive layer of overhead. If you search the forums, there is no universal fix. And I guess there is none, as it depends on the underlying hardware. In my enterprise setup, I have 3rd generation Xeon processors with two sockets.</p>
<p>One of the potential fixes I found is to use <code>cpu: host</code> and <code>hv-passthrough</code>. The performance instantly feels like bare metal. But there’s a massive catch: <code>hv-passthrough</code> completely breaks live migration. If you try to migrate a VM with <code>hv-passthrough</code> enabled, QEMU will block it outright.</p>
<p>The reason <code>hv-passthrough</code> breaks migration is that it asks the host kernel for every possible Hyper-V feature and passes it to the guest. This includes highly volatile timing states like <code>hv-frequencies</code> and <code>hv-reenlightenment</code>.</p>
<p>What is the alternative if VBS and/or WSL2 are required? Manually adding all the features to the <code>args:</code> field in the VM config file.</p>
<p>We can ask QEMU what it's actually doing—instead of guessing which flags we need—by interrogating it directly via the QEMU Machine Protocol (QMP) socket. While the VM is running with <code>hv-passthrough</code>, you can connect to its UNIX socket from the Proxmox host shell:</p>
<p><code>socat - UNIX-CONNECT:/var/run/qemu-server/&lt;VM_ID&gt;.qmp</code></p>
<p>After sending a quick JSON handshake: <code>{ "execute": "qmp_capabilities" }</code></p>
<p>and</p>
<p><code>{ "execute": "query-cpu-model-expansion", "arguments": { "type": "full", "model": { "name": "host", "props": { "hv-passthrough": true } } } }</code></p>
<p>to ask what features are being passed to the guest, QEMU spits back a massive JSON wall of text showing the true/false state of every single hardware flag. By pulling out the <code>hv-*</code> flags that return true, we get our exact, explicit hardware baseline.</p>
<p>So, we take that explicit list, remove the volatile clock flags (<code>hv-frequencies</code> and <code>hv-reenlightenment</code>), and paste it into our config. Migration works! But... performance degrades again.</p>
<p>Based on the research I did into this specific topic, my understanding is: without <code>hv-frequencies</code>, Windows loses the ability to sync with the hardware's Time Stamp Counter (TSC). Because VBS and WSL2 demand perfect timing, the lack of physical frequency data forces them back onto a slow, software-emulated timer.</p>
<p>Luckily, the story does not end here. With a bit of help from AI, I found a way to overcome this limitation by hardcoding the TSC. I needed to tell Windows the exact physical speed of our silicon, but mark it as "invariant" so QEMU knows the clock won't drift between cluster nodes.</p>
<ul>
<li><p><code>+invtsc</code> (Invariant TSC): This tells Windows 11, "The physical CPU clock will never fluctuate or desync, so you can safely use it for high-performance VBS."</p>
</li>
<li><p><code>tsc-frequency=2900000000</code>: By hardcoding this exact number, QEMU knows that the source and destination nodes will have the exact same clock expectation, allowing it to authorize the live migration.</p>
</li>
</ul>
<p><code>args: -cpu host,+vmx,+kvm_pv_eoi,+kvm_pv_unhalt,hv-relaxed,hv-vapic,hv-time,hv-synic,hv-stimer,hv-vpindex,hv-ipi,hv-runtime,hv-reset,hv-crash,hv-spinlocks=0xfff,hv-tlbflush,hv-tlbflush-ext,hv-tlbflush-direct,hv-stimer-direct,hv-apicv,hv-avic,hv-evmcs,hv-xmm-input,hv-emsr-bitmap,host-cache-info=on,l3-cache=on,+invtsc,tsc-frequency=2900000000</code></p>
<p>This allowed me to regain the performance I had when using the <code>host</code> CPU type and <code>hv-passthrough</code>.</p>
<p>While I was testing all those features, I noticed that my lab setup did not behave the same way. To get the performance back in my lab—where I have a quite recent desktop CPU (Intel Core Ultra 9 285K)—I did not have to specify the clock speed and <code>invtsc</code>.</p>
<p>This simplifies the setup because, as of Proxmox release 9.2.4 (or 5), it is possible to define a custom CPU type with <code>hv-</code>flags. By doing so, I can have VBS and WSL2 enabled in my lab setup with a custom CPU type defined. In my enterprise setup, the custom <code>args:</code> still need to be defined due to the custom clock frequency.</p>
<p>This workaround does not solve the issue of significantly higher idle CPU usage with Win 11 24H2+.</p>
]]></content:encoded></item></channel></rss>