# [SOLVED] AMD RX 6600 GPU passthrough: VFIO NULL pointer dereference on VM shutdown — one-line AMDGPU fix

> Source: <https://forum.level1techs.com/t/solved-amd-rx-6600-gpu-passthrough-vfio-null-pointer-dereference-on-vm-shutdown-one-line-amdgpu-fix/259958#post_1>
> Published: 2026-11-02 20:04:35+00:00

Hi everyone!

I’ve been working on getting GPU passthrough running reliably on my Linux workstation, allowing me to switch between my Ubuntu desktop and a Windows 11 VM using the same physical GPU.

The Windows VM itself was working perfectly. The RX 6600 was successfully passed through, Windows recognized it, and all my monitors switched over.

The problem appeared when shutting down the VM.

Instead of returning the GPU to the Linux host, the kernel would crash with a NULL pointer dereference inside `vfio_pci_core`.

After spending quite some time debugging this, I found a potential root cause in AMDGPU’s device cleanup code and successfully tested a one-line patch.

I thought I’d share the findings in case someone else runs into the same problem.

I should probably mention that I did most of this with a fairly superficial understanding of what was actually happening inside the Linux kernel.

I relied heavily on AI throughout basically the entire process, from analyzing kernel logs and reading source code to identifying the suspected cause and building the patched module. My contribution was mostly running commands, providing feedback, and testing the results.

While the fix worked on my machine, I wouldn’t automatically assume that every technical explanation in this post is 100% accurate. A significant part of it is based on AI-assisted analysis that I am not personally qualified to fully verify.

**I also wouldn’t experiment with something like this on a system I actually depend on.** This is my personal workstation, and I’m perfectly willing to break things, reinstall Linux, or spend a weekend figuring out why something stopped working.

So please treat this as an interesting experiment and a potentially useful starting point, rather than an authoritative kernel debugging guide. Corrections from people who understand the internals better than I do are very welcome!

**Motherboard:** ASUS X99-WS/IPMI

**CPU:** Intel Xeon E5-2680 v4

**GPU:** AMD Radeon RX 6600 (Navi 23)

**Host OS:** Ubuntu Linux

**Kernel:** 7.0.0-38-generic (Ubuntu 26.04)

**Virtualization:** QEMU/KVM with libvirt and virt-manager

**Guest:** Windows 11

**GPU passthrough:** VFIO-PCI, managed by libvirt

The workstation has no integrated GPU. The RX 6600 is the only graphics card, so returning it to the Linux host after VM shutdown is essential.

The GPU and its audio function are passed through as PCI devices:

`0000:03:00.0` — AMD Radeon RX 6600

`0000:03:00.1` — AMD HDMI/DP audio

Starting the Windows VM worked.

Libvirt detached the RX 6600 from AMDGPU, VFIO took ownership, and Windows operated normally.

However, when shutting down Windows, the kernel would crash while VFIO was being removed.

The relevant error was:

```
BUG: kernel NULL pointer dereference,
address: 0000000000000470

RIP: vfio_pci_core_sriov_configure+0x19/0x1f0
CR2: 0000000000000470

Call Trace:
 vfio_pci_core_unregister_device
 vfio_pci_remove
 pci_device_remove
 device_remove
 device_release_driver_internal
 device_driver_detach
 unbind_store
```

The interesting part was that the crash consistently happened during device removal, not during GPU initialization or while Windows was running.

I had also encountered the problem with a 6.17 kernel.

I downloaded the matching Ubuntu kernel source and built a modified `vfio-pci` module containing additional logging.

The instrumentation recorded the VFIO device pointer during initialization, after successful registration, and when the removal callback was entered.

During VM startup, everything looked correct:

```
18:24:25 vfio-pci 0000:03:00.0:
VFIO-DEBUG: probe initialized
vdev=ffff8c1a90c46800
drvdata=ffff8c1a90c46800

18:24:25 vfio-pci 0000:03:00.0:
VFIO-DEBUG: registration succeeded
vdev=ffff8c1a90c46800
drvdata=ffff8c1a90c46800
```

Both pointers were valid and identical.

However, during VM shutdown:

```
18:32:08 vfio-pci 0000:03:00.0:
VFIO-DEBUG: remove entered
vdev_null=1 drvdata_null=1
```

Immediately afterward, the kernel crashed.

So something had cleared the PCI device’s driver-private data after VFIO had successfully registered the GPU.

That pointed toward a driver lifecycle problem rather than a GPU reset problem.

While examining the AMDGPU driver source, I found this function in:

`drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c`

```
void amdgpu_driver_release_kms(struct drm_device *dev)
{
    struct amdgpu_device *adev = drm_to_adev(dev);

    amdgpu_device_fini_sw(adev);
    pci_set_drvdata(adev->pdev, NULL);
}
```

The last line immediately caught my attention:

``` php
pci_set_drvdata(adev->pdev, NULL);
```

This clears the PCI device’s driver-private pointer.

The important detail is that `amdgpu_driver_release_kms()` is a DRM device release callback, not the PCI driver’s removal callback.

DRM devices are reference-counted, meaning their final release can happen some time after the PCI driver has already been detached.

In my logs, AMDGPU cleanup was apparently still happening after VFIO had registered the device:

```
18:24:25 VFIO successfully registers the GPU
18:24:39 "ttm finalized"
18:32:08 VFIO removal receives NULL drvdata
```

The `ttm finalized` message was especially interesting because it appeared under the `vfio-pci` device prefix, despite originating from AMDGPU cleanup code.

My working theory is that an old AMDGPU DRM object was released after VFIO had already attached to the same PCI device.

When that happened, AMDGPU’s release callback could clear the driver-private pointer now belonging to VFIO.

Later, when VFIO attempted to unregister the device, it retrieved NULL and crashed.

I haven’t captured the exact write with a hardware watchpoint, so the timing relationship is not conclusively proven. However, the source code, the logs, and the result of the fix strongly support this explanation.

The proposed fix is surprisingly simple: remove the PCI driver-data clearing operation from AMDGPU’s delayed release callback.

```
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -1608,7 +1608,6 @@
     struct amdgpu_device *adev = drm_to_adev(dev);

     amdgpu_device_fini_sw(adev);
-    pci_set_drvdata(adev->pdev, NULL);
 }
```

The Linux driver core already clears driver-private data when unbinding a PCI driver, so the additional clearing in this delayed callback appears unnecessary and potentially unsafe.

After identifying this, I discovered that Matthew Auld had already proposed essentially this exact change in May 2024, in a patch titled:

**[PATCH 02/20] drm/amdgpu: don’t trample pdev drvdata**

The patch describes the same driver-data lifetime issue. It appears that the problematic statement is still present in my Ubuntu kernel source.

Reference: [Original upstream patch discussion](https://www.mail-archive.com/search?f=1&l=amd-gfx%40lists.freedesktop.org&o=newest&q=from%3A%22Matthew+Auld%22)

I applied the change to the matching Ubuntu `linux-source-7.0.0` source and rebuilt the AMDGPU kernel module against the installed kernel headers.

For this kernel, I used an external-module build with an additional include path for AMDGPU’s tracing headers:

```
make -j4 \
  -C /lib/modules/$(uname -r)/build \
  M="$PWD/drivers/gpu/drm/amd/amdgpu" \
  KCFLAGS="-I$PWD/drivers/gpu" \
  modules
```

The resulting `amdgpu.ko` compiled successfully.

I then installed it as a module override under:

```
/lib/modules/7.0.0-38-generic/updates/amdgpu.ko
```

Ubuntu’s module search configuration prioritizes `updates/`, allowing the patched module to load while preserving the original distribution module for rollback.

After rebuilding the module dependency database and rebooting, I repeated the GPU passthrough test.

**It worked!**

The Windows 11 VM started, the RX 6600 was passed through successfully, and Windows operated normally.

After shutting down the VM, the GPU returned to the Linux host without the VFIO NULL pointer crash.

This was the first successful test with the patched driver. I still want to perform additional start/stop cycles before calling it completely stable, but the original failure did not occur.

This is a custom kernel module modification, not an official Ubuntu fix.

I tested it on my particular hardware and kernel combination. I would not recommend blindly installing a custom AMDGPU module built for another kernel version.

If you want to experiment with this, make sure you have:

The exact matching kernel source and headers

A backup of the original module

SSH access or another recovery mechanism

A way to recover if the GPU driver fails to initialize

In my case, having only one GPU made remote access particularly important.

Initially, I was convinced the problem was somewhere inside VFIO because that’s where the kernel crashed.

The debugging logs revealed something more interesting: VFIO had correctly initialized its device context, but the pointer disappeared before removal.

That eventually led me to AMDGPU’s delayed DRM cleanup callback.

The actual change was just one deleted line.

I’m posting this both to help anyone experiencing a similar issue and to get feedback from people who know the DRM and PCI driver lifecycle better than I do.

**Has anyone else encountered this behavior, or does anyone know why the original 2024 patch hasn’t made it into the kernel source I’m using?**

I’d be especially interested in knowing whether this is already addressed by another upstream change or whether the original patch could be revisited.

Thanks for reading!
