[SOLVED] High Power Usage for Passthrough GPU When VM Is Stopped

ovidiugm

New Member
Apr 29, 2023
3
2
3
I am running Proxmox installed on top of Debian 12 Bookworm, as per guide here: https://pve.proxmox.com/wiki/Install_Proxmox_VE_on_Debian_12_Bookworm
pveversion shows pve-manager/8.0.3/bbf3993334bfa916 (running kernel: 6.2.16-5-pve)
Hardware config is Ryzen 7 5700G, MSI B450 Gaming Plus Max.
Passthrough ASUS GeForce 1660S GPU for a Win10 VM.

Win10 VM uses the 1660S just fine. When idle with VM on, power usage at outlet is 28-29W.
With Win10 VM stopped, power usage goes up to 45W.

Right after boot, lspci --vv would show:
10:00.0 VGA compatible controller: NVIDIA Corporation TU116 [GeForce GTX 1660 SUPER] (rev a1) (prog-if 00 [VGA controller]) [...] LnkCtl: ASPM Disabled [...] Kernel driver in use: vfio-pci Kernel modules: nvidiafb, nouveau

1. With the Win10 VM stopped, unbind from vfio-pci and bind to nouveau - this gets me a very small drop in power usage (1-5W) but system is still idling at 40-45W.
echo 0000:10:00.0 > /sys/bus/pci/drivers/vfio-pci/unbind echo 0000:10:00.0 > /sys/bus/pci/drivers/nouveau/bind
Device correctly binds to nouveau as confirmed by lspci.


2. I also tried the omnipresent internet enable_aspm script to turn on ASPM, this changes the link control but makes no difference at all in power usage:
LnkCtl: ASPM L0s L1 Enabled; RCB 64 bytes, Disabled- CommClk+

3. Installed non-free Nvidia drivers (nvidia-smi). This brings the idle system to 27W with the Win10 VM off. However the passthrough does not work any more (bind/unbind don't work, VM does not start, device /dev/nvidia0 is locked by nvidia-persistenced service/process).

Anything else I could try?
Thanks so much!
 
You need drivers to power down parts of the GPU but nouveau often does not get the information from NVidia on how to do that. Keep the VM running in idle or create a smaller VM with the NVidia drivers to reduce the power draw of the GPU. Or switch to an AMD or Intel GPU that is properly supported by the Linux kernel drivers.
 
  • Like
Reactions: ovidiugm
You need drivers to power down parts of the GPU but nouveau often does not get the information from NVidia on how to do that. Keep the VM running in idle or create a smaller VM with the NVidia drivers to reduce the power draw of the GPU. Or switch to an AMD or Intel GPU that is properly supported by the Linux kernel drivers.
Isn't that impossible in his situation.

What i mean is, he is passing through the gpu to the VM.
If the VM turns off (shutdown or whatever)
There is only on the host vfio-pcie bound to the GPU.
Means no driver and no kernel driver or anything.

I actually never thought of such an scenario, what happens with the GPU power consumption.
So it's actually a pretty interesting thread.

In an optimal case, i would say that the vm, should send the GPU to the highest powersave state during shutdown.
But not sure if that's happening or the right usual scenario.

However, im curious to read the replyes here and see what people say, or how the GPU should behave actually.

Cheers

Edit: Forget it, i didn't readed the entire thread xD
Unbind vfio-pcie and bind to the driver is already a solution. Just seems not pretty to me.
 
Last edited:
You need drivers to power down parts of the GPU but nouveau often does not get the information from NVidia on how to do that. Keep the VM running in idle or create a smaller VM with the NVidia drivers to reduce the power draw of the GPU. Or switch to an AMD or Intel GPU that is properly supported by the Linux kernel drivers.
Indeed, I saw this mentioned as a solution before. I would prefer not to keep the current Win10 VM active - it's configured to hug a lot of total available RAM.
Question - is there any way to (reliably and programatically) turn on the small VM when the other is shut down, and the other way around?

AMD was my first option, as my CPU has an integrated AMD Vega 8 GPU.
My first attempt was to passthrough this GPU to Win10. Spent almost a week with that, following all the guides I could find. The farther I got was to have the GPU show up in the Win10 VM Device Manager, with the dreaded Error 43 - the drivers would not work properly.
I gave up on it and to my amazement the Nvidia GPU needed no config, it worked on first try.
If anybody have an up-to-date guide on Ryzen integrated GPU passthrough, that would be also great.
 
Indeed, I saw this mentioned as a solution before. I would prefer not to keep the current Win10 VM active - it's configured to hug a lot of total available RAM.
And all VMs with PCI(e) passthrough always use all of its memory because of possible device-initiated DMA.
Question - is there any way to (reliably and programatically) turn on the small VM when the other is shut down, and the other way around?
Use a hookscipt to start a smaller Windows VM (or try NVidia's Linux drivers inside a VM) when your big VM has stopped.
 
  • Like
Reactions: ovidiugm
Isn't that impossible in his situation.

What i mean is, he is passing through the gpu to the VM.
If the VM turns off (shutdown or whatever)
There is only on the host vfio-pcie bound to the GPU.
Means no driver and no kernel driver or anything.

I actually never thought of such an scenario, what happens with the GPU power consumption.
So it's actually a pretty interesting thread.
You might also be interested in all the other threads about this on this forum.
In an optimal case, i would say that the vm, should send the GPU to the highest powersave state during shutdown.
But not sure if that's happening or the right usual scenario.
For that you need a driver that has knowledge about the GPU. As measured (by multiple people), the GPU does not power down completely without drivers. It's not what you expect or what people want, but that's what how they work.
However, im curious to read the replyes here and see what people say, or how the GPU should behave actually.
You might also be interested in all the other threads about this on this forum.
Unbind vfio-pcie and bind to the driver is already a solution. Just seems not pretty to me.
But there is no (open source) Linux driver with enough knowledge about the GPU power settings, that's also why nouveau is slow on many NVidia GPUs: it cannot change clockspeeds of various components. That's why you need NVidia's drivers, which work best on a Windows VM.
 
Using a whole VM for power-saving doesn't look like an elegant solution, however I must say at first sight it's working great. No race conditions between the starting/stopping VMs, power usage stays low with the dummy Debian VM running, with Nvidia official drivers installed.

On guest VM, Debian w. 512MB RAM, 2 CPU cores, 4GB storage:
  • Add the PCI device for passthrough
  • Add non-free repository in /etc/apt/sources.list deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware
  • Install nvidia drivers: apt install nvidia-smi
  • Reboot

On Proxmox host, create the hookscript, make it executable:
cd /var/lib/vz/snippets touch nvidiavm.sh chmod +x nvidiavm.sh nano nvidiavm.sh

Insert the following in the sh file, change VM id's as necessary:
Bash:
#!/bin/bash
VMID=$1
PHASE=$2

if [ "$VMID" = "105" ]; then
  if [ "$PHASE" = "pre-start" ]; then
    echo "Win10 VM pre-start: Stopping Nvidia Dummy VM"
    qm stop 200

  elif [ "$PHASE" = "post-stop" ]; then
    echo "Win10 VM post-stop: Starting Nvidia Dummy VM"
    qm start 200
  fi
fi

Attach it to your resource-consuming VM:
qm set 105 --hookscript local:snippets/nvidiavm.sh

Execution steps will show in journal:
journalctl -b
Jul 29 01:53:48 deb qmeventd[135980]: Win10 VM post-stop: Starting Nvidia Dummy VM


Thanks for everyone's contribution on this!
 
Using a whole VM for power-saving doesn't look like an elegant solution, however I must say at first sight it's working great. No race conditions between the starting/stopping VMs, power usage stays low with the dummy Debian VM running, with Nvidia official drivers installed.

On guest VM, Debian w. 512MB RAM, 2 CPU cores, 4GB storage:
  • Add the PCI device for passthrough
  • Add non-free repository in /etc/apt/sources.list deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware
  • Install nvidia drivers: apt install nvidia-smi
  • Reboot

On Proxmox host, create the hookscript, make it executable:
cd /var/lib/vz/snippets touch nvidiavm.sh chmod +x nvidiavm.sh nano nvidiavm.sh

Insert the following in the sh file, change VM id's as necessary:
Bash:
#!/bin/bash
VMID=$1
PHASE=$2

if [ "$VMID" = "105" ]; then
  if [ "$PHASE" = "pre-start" ]; then
    echo "Win10 VM pre-start: Stopping Nvidia Dummy VM"
    qm stop 200

  elif [ "$PHASE" = "post-stop" ]; then
    echo "Win10 VM post-stop: Starting Nvidia Dummy VM"
    qm start 200
  fi
fi

Attach it to your resource-consuming VM:
qm set 105 --hookscript local:snippets/nvidiavm.sh

Execution steps will show in journal:
journalctl -b
Jul 29 01:53:48 deb qmeventd[135980]: Win10 VM post-stop: Starting Nvidia Dummy VM


Thanks for everyone's contribution on this!
You might also want to create a vzdump hook script. As otherwise the backup of your big VM will fail while the small VM is running (and reverse), because a VM needs to be started in order to back it up and you can't start two VMs that are using the same PCIe device.

Edit:
Here is what I use, which shuts down both VMs before doing the backup and then starts that VM again after the backup job has finished:
https://forum.proxmox.com/threads/backup-vm-same-pcie-device-iommu-on-two-vm.129600/#post-567803
 
Last edited:
  • Like
Reactions: ovidiugm
I have the same issue as ovidiugm

Proxmox: VE 8.0.4, Linux 6.2.16-12-pve
Hardware: AMD EPYC 7532 32-Core, NVIDIA RTX A4000 GPU (140 W)

So I have a Windows 11 VM for games with the above GPU passed through. And the power consumption is as follows:
1) When Windows 11 VM is active and I play video games in Windows 11 VM: 270-290W
2) When Windows 11 VM is active and I do not play games in Windows 11 VM: 200-210W
3) When Windows 11 VM is shutdown: 250-260W

I guess I will just keep the VM active all the time, but I wish I could keep it shutdown when I do not need it.
 
Using a whole VM for power-saving doesn't look like an elegant solution, however I must say at first sight it's working great. No race conditions between the starting/stopping VMs, power usage stays low with the dummy Debian VM running, with Nvidia official drivers installed.

On guest VM, Debian w. 512MB RAM, 2 CPU cores, 4GB storage:
  • Add the PCI device for passthrough
  • Add non-free repository in /etc/apt/sources.list deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware
  • Install nvidia drivers: apt install nvidia-smi
  • Reboot

On Proxmox host, create the hookscript, make it executable:
cd /var/lib/vz/snippets
touch nvidiavm.sh
chmod +x nvidiavm.sh
nano nvidiavm.sh

Insert the following in the sh file, change VM id's as necessary:
Bash:
#!/bin/bash
VMID=$1
PHASE=$2

if [ "$VMID" = "105" ]; then
  if [ "$PHASE" = "pre-start" ]; then
    echo "Win10 VM pre-start: Stopping Nvidia Dummy VM"
    qm stop 200

  elif [ "$PHASE" = "post-stop" ]; then
    echo "Win10 VM post-stop: Starting Nvidia Dummy VM"
    qm start 200
  fi
fi

Attach it to your resource-consuming VM:
qm set 105 --hookscript local:snippets/nvidiavm.sh

Execution steps will show in journal:
journalctl -b
Jul 29 01:53:48 deb qmeventd[135980]: Win10 VM post-stop: Starting Nvidia Dummy VM


Thanks for everyone's contribution on this!
Thanks for your solution.

its been a while now is this still the best option?
 
You might also want to create a vzdump hook script. As otherwise the backup of your big VM will fail while the small VM is running (and reverse), because a VM needs to be started in order to back it up and you can't start two VMs that are using the same PCIe device.

Edit:
Here is what I use, which shuts down both VMs before doing the backup and then starts that VM again after the backup job has finished:
https://forum.proxmox.com/threads/backup-vm-same-pcie-device-iommu-on-two-vm.129600/#post-567803
noob here whats a vzdump?
 
I’ve been running a home server setup where my GTX 1060 was dedicated to a windows gaming/streaming VM, while my P400 served another VM for different workloads. One of the challenges I quickly ran into was the **power consumption** of having both GPUs always powered, even when idle. The GTX 1060, in particular, tends to draw a noticeable amount of power when sitting idle in a VM passthrough scenario, and the P400, while less hungry, still added to the total.

After experimenting with GPU passthrough management and driver unbinding techniques, I managed to **significantly reduce idle power draw**, saving roughly **40 watts**. This improvement not only helps reduce electricity costs but also lessens heat output and wear on the hardware — which is important for a system that runs 24/7.

The struggle was balancing **VM accessibility** with **host control**, making sure I could still assign the GPUs to VMs when needed without leaving them permanently consuming power on the host.
**Important:** Both GPUs **must be present on the host during driver installation** so that the NVIDIA persistence daemon can manage both devices properly.

---


## **Step 0 — Preparation**

1. Update system and install build tools:


Bash:
apt update && apt full-upgrade -y

apt install build-essential dkms pve-headers pkg-config

2. Check kernel and headers:

Bash:
uname -r

dpkg -l | grep pve-headers

- Ensure headers match the running kernel (e.g., `6.14.11-2-pve`).


3. Blacklist conflicting modules in /etc/modprobe.d/blacklist.conf:


```text
# /etc/modprobe.d/blacklist.conf
blacklist nouveau
blacklist radeon
#blacklist nvidia
```
Update initramfs and reboot:

Code:
update-initramfs -u
reboot
---

## **Step 1 — Prepare GPUs for Driver Installation**

1. List all NVIDIA GPUs:

Bash:
lspci -nn | grep -i nvidia

- Example output:

```
02:00.0 Quadro P400
02:00.1 P400 Audio
65:00.0 GTX 1060
65:00.1 GTX 1060 Audio
```

2. **Important:** Both P400 and GTX 1060 **must be visible to the host** when installing the NVIDIA driver. This ensures the NVIDIA persistence daemon can manage both GPUs, allowing idle power management and avoiding errors during passthrough.

3. Temporarily unbind the GPU you want to dedicate to VFIO (GTX 1060) **only for driver installation**, so the driver can see it:
For my GTX 1060

Bash:
echo 0000:65:00.0 > /sys/bus/pci/devices/0000:65:00.0/driver/unbind

echo 0000:65:00.1 > /sys/bus/pci/devices/0000:65:00.1/driver/unbind

echo "" > /sys/bus/pci/devices/0000:65:00.0/driver_override

echo "" > /sys/bus/pci/devices/0000:65:00.1/driver_override

- For my Quadro P400

Bash:
echo 0000:02:00.0 > /sys/bus/pci/devices/0000:02:00.0/driver/unbind

echo 0000:02:00.1 > /sys/bus/pci/devices/0000:02:00.1/driver/unbind

echo "" > /sys/bus/pci/devices/0000:02:00.0/driver_override

echo "" > /sys/bus/pci/devices/0000:02:00.1/driver_override
- After installation, both GPUs should be visible to the host again under ```nvidia-smi```
---

## **Step 2 — Install NVIDIA Driver**

1. Make installer executable (this can be downloaded from Nvidia page):
Bash:
chmod +x NVIDIA-Linux-x86_64-*.run

2. Run installer:

Bash:
./NVIDIA-Linux-x86_64-*.run
- **Important:** Make sure both GPUs are visible on the host **during installation**. This ensures the NVIDIA persistence daemon can initialize both devices.

- Choose **No** for module signing if Secure Boot is disabled.

- Ignore X or 32-bit warnings; they are not needed for headless VFIO setups.

- Confirm installation of `nvidia-persistenced` if prompted.
---

## **Step 3 — Verify Driver Installation**
Bash:
nvidia-smi

lsmod | grep nvidia

- Both P400 and GTX 1060 should appear.
1758496237180.png
- Persistence mode for both GPUs can now be managed via the NVIDIA persistence daemon.

- If one GPU is missing, **persistence mode will not work correctly** for that device, potentially causing errors during passthrough or idle power issues.

## **Step 4 — Enable NVIDIA Persistence Daemon**

Create the systemd service:
Bash:
cat <<EOF > /etc/systemd/system/nvidia-persistenced.service

[Unit]

Description=NVIDIA Persistence Daemon

After=network.target



[Service]

Type=forking

ExecStart=/usr/bin/nvidia-persistenced --user root --no-persistence-mode

ExecStop=/usr/bin/nvidia-persistenced --terminate

RemainAfterExit=yes



[Install]

WantedBy=multi-user.target

EOF

Reload systemd and enable:
Bash:
systemctl daemon-reload

systemctl enable nvidia-persistenced

systemctl start nvidia-persistenced

systemctl status nvidia-persistenced
- **Both GPUs must be visible to the host** at this point for the daemon to manage persistence mode correctly.

## **Step 5 — Return GTX 1060 to VFIO for Passthrough**
Bash:
echo vfio-pci > /sys/bus/pci/devices/0000:65:00.0/driver_override

echo vfio-pci > /sys/bus/pci/devices/0000:65:00.1/driver_override

echo 0000:65:00.0 > /sys/bus/pci/drivers_probe

echo 0000:65:00.1 > /sys/bus/pci/drivers_probe

- VM 311 will now use GTX 1060.

- Host keeps control of P400 for persistence and idle management.


---

## **Step 6 — Hook Scripts for Automatic Passthrough**
I have created two files with:
Bash:
nano /var/lib/vz/snippets/gtx1060.sh

nano /var/lib/vz/snippets/p400.sh

### **GTX 1060 → VM 311**
Bash:
#!/usr/bin/env bash

# GTX 1060 GPU passthrough hook for VM 311



GPU_VGA="0000:65:00.0"    # Replace with your GPU PCI ID

GPU_AUDIO="0000:65:00.1"  # Replace with HDMI/audio PCI ID



if [ "$2" == "pre-start" ]; then

    # Disable persistence mode to allow unbinding

    nvidia-smi -i "$GPU_VGA" --persistence-mode=0



    # Unbind GPU and audio from NVIDIA driver

    echo "$GPU_VGA" > /sys/bus/pci/devices/$GPU_VGA/driver/unbind

    echo "$GPU_AUDIO" > /sys/bus/pci/devices/$GPU_AUDIO/driver/unbind



    # Override driver to vfio-pci

    echo vfio-pci > /sys/bus/pci/devices/$GPU_VGA/driver_override

    echo vfio-pci > /sys/bus/pci/devices/$GPU_AUDIO/driver_override



    # Bind GPU and audio to vfio-pci for VM passthrough

    echo "$GPU_VGA" > /sys/bus/pci/drivers/vfio-pci/bind

    echo "$GPU_AUDIO" > /sys/bus/pci/drivers/vfio-pci/bind



elif [ "$2" == "post-stop" ]; then

    # Unbind GPU and audio from vfio-pci

    echo "$GPU_VGA" > /sys/bus/pci/devices/$GPU_VGA/driver/unbind

    echo "$GPU_AUDIO" > /sys/bus/pci/devices/$GPU_AUDIO/driver/unbind



    # Rebind to NVIDIA driver

    echo nvidia > /sys/bus/pci/devices/$GPU_VGA/driver_override

    echo "$GPU_VGA" > /sys/bus/pci/drivers/nvidia/bind



    # Re-enable persistence mode for host use

    nvidia-smi -i "$GPU_VGA" --persistence-mode=1

fi



exit 0

### **P400 → VM 306
Bash:
#!/usr/bin/env bash

# GTX 1060 GPU passthrough hook for VM 311



GPU_VGA="0000:02:00.0"    # Replace with your GPU PCI ID

GPU_AUDIO="0000:02:00.1"  # Replace with HDMI/audio PCI ID



if [ "$2" == "pre-start" ]; then

    # Disable persistence mode to allow unbinding

    nvidia-smi -i "$GPU_VGA" --persistence-mode=0



    # Unbind GPU and audio from NVIDIA driver

    echo "$GPU_VGA" > /sys/bus/pci/devices/$GPU_VGA/driver/unbind

    echo "$GPU_AUDIO" > /sys/bus/pci/devices/$GPU_AUDIO/driver/unbind



    # Override driver to vfio-pci

    echo vfio-pci > /sys/bus/pci/devices/$GPU_VGA/driver_override

    echo vfio-pci > /sys/bus/pci/devices/$GPU_AUDIO/driver_override



    # Bind GPU and audio to vfio-pci for VM passthrough

    echo "$GPU_VGA" > /sys/bus/pci/drivers/vfio-pci/bind

    echo "$GPU_AUDIO" > /sys/bus/pci/drivers/vfio-pci/bind



elif [ "$2" == "post-stop" ]; then

    # Unbind GPU and audio from vfio-pci

    echo "$GPU_VGA" > /sys/bus/pci/devices/$GPU_VGA/driver/unbind

    echo "$GPU_AUDIO" > /sys/bus/pci/devices/$GPU_AUDIO/driver/unbind



    # Rebind to NVIDIA driver

    echo nvidia > /sys/bus/pci/devices/$GPU_VGA/driver_override

    echo "$GPU_VGA" > /sys/bus/pci/drivers/nvidia/bind



    # Re-enable persistence mode for host use

    nvidia-smi -i "$GPU_VGA" --persistence-mode=1

fi



exit 0

**Then make it executable:**
Bash:
chmod +x /var/lib/vz/snippets/gtx1060.sh

chmod +x /var/lib/vz/snippets/p400.sh

VM configs:
```ini
# VM 311
hookscript: local:snippets/gtx1060.sh

# VM 306
hookscript: local:snippets/p400.sh
```

---

## **Step 7 — Test Setup**

1. Reboot host for a clean state.

2. Start VM 311 → GTX 1060 is assigned to VM.

3. Stop VM 311 → GTX 1060 returns to host.

4. Start VM 312 → P400 is assigned to VM.

5. Stop VM 312 → P400 returns to host.


Verify:
1758496581620.png
Bash:
nvidia-smi   # Host GPU should be idle when not used by VMs

systemctl status nvidia-persistenced
---

✅ **Result**

- Both GPUs managed by host initially.

- Each GPU assigned to its own VM when running.

- NVIDIA persistence daemon ensures low idle power and proper GPU initialization.

- Host always regains control after VM shutdown.

- Future driver updates can be applied safely with temporary unbind/bind.


I think this approach is pretty elegant compared to putting the GPU in another low-power VM. The Linux driver from NVIDIA is kind of frustrating—it won’t allow the GPU to enter P8 state for power saving—but fortunately, there is still a small workaround for this problem.
 
Last edited: