FirePro D500 → Linux desktop on the physical monitor, via Proxmox
Published on July 11, 2026
The goal of this guide is to pass an AMD FirePro D500 (Tahiti GPU, GCN 1.0 architecture, from 2013) from a Mac Pro 6,1 (Late 2013, the “trashcan”) running Proxmox VE into a VM, with the video output appearing on the physical monitor (HDMI/DisplayPort) — not VNC/SPICE.
The result works end-to-end on Linux Mint and Bazzite (Fedora Atomic). On Windows the GPU passes through to the VM without the infamous Code 43, but the physical display doesn't come up — the reason is detailed in the Windows section.
It's an interesting problem because it combines two sources of quirkiness at once: it's a Mac GPU (vBIOS in EFI GOP, not legacy x86) running on 2013-era hardware (no interrupt remapping in the IOMMU). Each of these characteristics alone already requires a specific passthrough adjustment; together, they require a well-defined sequence of steps to work.
The FirePro D500 are Tahiti (GCN 1.0 / Southern Islands) GPUs from 2013, with Mac quirks on top. The table below summarizes the obstacles encountered and the solution applied to each:
| Obstacle | Symptom | Solution |
|---|---|---|
| Mac Pro 6,1 has no interrupt remapping | vfio: Failed to set iommu for container: Operation not
permitted |
allow_unsafe_interrupts=1 |
| Mac GPU has no x86 vBIOS (uses EFI GOP) | Invalid PCI ROM header signature: got 0xffff; GPU
doesn't enumerate in the VM |
extract the real vBIOS and pass it as romfile |
The host's amdgpu grabs the GPU at boot
and “dirties” it |
host console on screen; then reset
recovery - restoring BARs ... blocked, host may hang |
early-bind (vfio-pci.ids in the
cmdline) — binds the GPU to vfio before amdgpu |
x-vga=1 / Mac vBIOS POST in OVMF |
no signal at boot | do NOT use x-vga; use
vga: none (VM driver takes over) |
Legacy radeon driver doesn't scanout
on Tahiti |
black screen with signal | force amdgpu
(amdgpu.si_support=1) |
| Mac's HDMI is HDMI 1.4 (max 4K@30) | black with signal at 4K@60 | force 1080p/1440p (on Xorg); Wayland/KDE negotiates on its own |
root access via SSH.Warning: find out which GPU feeds
the physical port the monitor is connected to — plug in the monitor
and check which card shows connected:
for s in /sys/class/drm/card*/card*/status; do
[ "$(cat "$s")" = connected ] && echo "$(dirname "$s"|xargs basename) -> PCI $(readlink -f "$(dirname "$s")/../device"|grep -oE '[0-9a-f]{2}:[0-9a-f]{2}\.[0-9]'|tail -1)"
done
On a typical Mac Pro 6,1, the native HDMI is usually
fed by the GPU in PCI slot 0000:06:00 (the
primary/boot_vga); the other GPU sits at
0000:02:00. Always confirm with the command
above before proceeding.
Since both D500s share the same device-id
(1002:679e), early-bind by id sends both
GPUs to vfio and the host becomes headless (managed via
SSH/web). That's intentional and desired here.
Find out your hardware's IDs:
lspci -nn | grep -iE "VGA|Display|Audio" # Reference: GPU 1002:679e (Tahiti LE), HDMI audio 1002:aaa0, Mac analog audio 8086:1d20 (Cirrus CS4208)
In /etc/default/grub, on the
GRUB_CMDLINE_LINUX_DEFAULT line, add
intel_iommu=on iommu=pt. In /etc/modules,
add vfio, vfio_iommu_type1, and
vfio_pci.
# /etc/default/grub GRUB_CMDLINE_LINUX_DEFAULT="... intel_iommu=on iommu=pt" # /etc/modules vfio vfio_iommu_type1 vfio_pci
allow_unsafe_interrupts (required on the Mac Pro 6,1)echo "options vfio_iommu_type1 allow_unsafe_interrupts=1" > /etc/modprobe.d/iommu_unsafe_interrupts.conf
Without this, vfio refuses
(Operation not permitted). Security
implication: a malicious VM could, in theory, inject
interrupts into the host — acceptable in a
single-user/trusted environment; it's the only path on this
hardware (which has no interrupt remapping).
Bind the GPUs to vfio-pci
before amdgpu loads, otherwise the
amdgpu initializes the GPU at boot, it gets “dirtied”,
and passthrough fails (or hangs the host).
In GRUB_CMDLINE_LINUX_DEFAULT
add (use your hardware's IDs):
vfio-pci.ids=1002:679e,1002:aaa0 video=efifb:off
And make sure the driver order is enforced:
printf 'softdep amdgpu pre: vfio-pci\nsoftdep radeon pre: vfio-pci\n' > /etc/modprobe.d/vfio.conf
Apply and reboot the host:
update-grub && update-initramfs -u -k all && reboot
After the reboot, verify
(all should be on vfio-pci, and amdgpu should NOT
have initialized any of them):
for d in 0000:06:00.0 0000:06:00.1 0000:02:00.0 0000:02:00.1; do echo "$d -> $(basename "$(readlink /sys/bus/pci/devices/$d/driver)")"; done dmesg | grep -c "amdgpu .*initializing kernel" # should be 0
The Mac D500s don't expose an x86
expansion ROM, but the vBIOS (atombios) is accessible from the
host. The easiest way is to capture it before
early-bind (with the GPU still on amdgpu):
cat /sys/kernel/debug/dri/0000:06:00.0/amdgpu_vbios > /usr/share/kvm/d500.rom # validate: ~64KB, header 55aa, contains "ATOMBIOSBK-AMD ... AMD_TAHITI_LE" od -A x -t x1 -N 4 /usr/share/kvm/d500.rom # 55 aa ...
Alternative (always available, even post
early-bind): the ACPI VFCT table
(/sys/firmware/acpi/tables/VFCT contains the vBIOS +
header). Keep copies — it's
irreplaceable.
x-vga, with romfile, vga: none)qm set <VMID> -hostpci0 0000:06:00,pcie=1,romfile=d500.rom -vga none qm set <VMID> -cpu host # for Windows, use: -cpu host,hidden=1 (anti Code 43)
x-vga=1 (OVMF
can't POST the Mac vBIOS → no signal).vga: none makes the physical GPU the only
display. The VM must be OVMF/UEFI + q35.⚠️ With vga: none Proxmox's
SPICE/noVNC console won't connect (there's no
virtual display). For remote access/installation, use
vga: std temporarily; switch to
none only in “physical screen” mode.
amdgpu driver inside the VMThe legacy radeon driver
loads but doesn't scanout on Tahiti →
black screen. Force amdgpu:
Traditional distro (e.g.,
Linux Mint, Ubuntu, Debian) — in
/etc/default/grub:
radeon.si_support=0 amdgpu.si_support=1 amdgpu.cik_support=1
Then update-grub and
reboot the VM. (On Mint/Ubuntu
grub.d/50_linuxmint.cfg is also read; actually run
update-grub — just editing
/etc/default/grub.d/ on its own isn't enough.)
Fedora Atomic (e.g., Bazzite, Silverblue/Kinoite) — via kargs:
sudo rpm-ostree kargs --append-if-missing=radeon.si_support=0 --append-if-missing=amdgpu.si_support=1 \ --append-if-missing=amdgpu.cik_support=1 --append-if-missing=amdgpu.runpm=0
Then reboot the VM. (The
amdgpu.runpm=0 is the anti-freeze mitigation
— see below.)
⚠️ Kernel 7.0 (Bazzite 44) does
NOT eliminate the need for si_support
(correcting an earlier observation): the impression that it
“wasn't needed” was a lucky boot
— there's a radeon×amdgpu
race and sometimes neither driver
grabs the Tahiti (card0 ends up with no driver
→ “no signal”). Keep all 3
si_support flags. Atomic image upgrades
reset custom kargs → reapply after a major
upgrade.
⚠️ amdgpu.runpm=0 is
practically mandatory on Bazzite's kernel
7.0/-ogc for passthrough not to
hang the ENTIRE HOST: without it, the guest
GPU's runtime PM (BACO state) locks up the host's PCIe in a
silent deadlock (no AER/MCE; only a power
cycle recovers) — consistent with
CVE-2026-53293 (amdgpu deadlock, GCN 1.0+,
disclosed Jun/2026). With runpm=0 the reset comes
out clean (reset done) and the host stays stable
(validated: physical boot + VM reboot + usage, no freeze).
Verify on the VM:
cat /sys/bus/pci/devices/0000:01:00.0/uevent | grep DRIVER
→ DRIVER=amdgpu.
Resolution: the
Mac Pro's HDMI is HDMI 1.4 →
won't display 4K@60 (black with signal). On
Xorg (Mint), force 1080p or 1440p (modeline +
modesetting). On Wayland/KDE
(Bazzite) resolution is negotiated automatically
— no need to force it.
Keyboard/mouse: USB
passthrough — grab the IDs with lsusb and
pass each device:
qm set <VMID> -usb0 host=VVVV:PPPP -usb1 host=WWWW:QQQQ
Works hot-plugged (no need to reboot the VM).
Audio: if the monitor
has no speakers, HDMI audio is useless. Pass the
Mac's analog codec (on the Mac Pro 6,1 it's a
Cirrus CS4208, 0000:00:1b.0) to the VM:
qm set <VMID> -hostpci1 0000:00:1b.0,pcie=1
(shows up as “CS4208 Analog”
inside the VM). The Mac Pro 6,1 has two rear analog
outputs: headphone (with jack detection) and
line out (optical combo — the red light is
TOSLINK, harmless). Plug the headphones into the
headphone output and select the
“Headphone” port in the mixer
(KDE/PipeWire) — selecting “Line Out” uses a
different codec path and stays silent. Symptom of the wrong
path: the Headphone DAC (node 0x02)
sits at volume 0x00 with pin 0x10
muted; selecting the right port makes WirePlumber raise the
hardware volume and unmute it. On Bazzite
(PipeWire) the internal speaker also played without a quirk;
on Mint only the rear output works (internal
speaker silent without model= on
snd_hda_intel).
dhclient -1 eth0.qm guest exec. Write a script to
/tmp and run it from the VM's terminal
instead.The GPU passes through without
Code 43 using -cpu host,hidden=1 + the
romfile. The card shows up as “AMD Radeon HD
7800 Series” working in Device Manager, with the
legacy Adrenalin driver (21.5.2 or 22.6.1).
However the physical display
doesn't come up: with vga: none/x-vga
OVMF can't POST the Mac vBIOS (no signal), and with a virtual
display Windows doesn't detect the monitor on the secondary
GPU. Linux works because the KMS driver takes over the
GPU at boot; Windows depends on
firmware POST. Not solved
here.
To return the host to its default state:
remove vfio-pci.ids, intel_iommu, and
video=efifb:off from the cmdline, delete
/etc/modprobe.d/{vfio,iommu_unsafe_interrupts}.conf
and the vfio modules from /etc/modules, remove
hostpci*/usb* from the VM, and switch
back to vga: std. Then:
update-grub && update-initramfs -u -k all && reboot
What this guide validates: a
physical video output, on a Linux VM, with an
AMD FirePro D500 passed through from a
Mac Pro 6,1. Always confirm the device-IDs and
PCI slots of your own hardware with lspci -nn
before reproducing the steps.
Copy-paste summary of the commands
already presented in the sections above, grouped by where each
one runs. The device-IDs and PCI slots are from this guide's
reference hardware — confirm your own with
lspci -nn before copying.
/etc/default/grubGRUB_CMDLINE_LINUX_DEFAULT="... intel_iommu=on iommu=pt vfio-pci.ids=1002:679e,1002:aaa0 video=efifb:off"
/etc/modulesvfio vfio_iommu_type1 vfio_pci
/etc/modprobe.d/# /etc/modprobe.d/iommu_unsafe_interrupts.conf echo "options vfio_iommu_type1 allow_unsafe_interrupts=1" > /etc/modprobe.d/iommu_unsafe_interrupts.conf # /etc/modprobe.d/vfio.conf printf 'softdep amdgpu pre: vfio-pci\nsoftdep radeon pre: vfio-pci\n' > /etc/modprobe.d/vfio.conf
# apply update-grub && update-initramfs -u -k all && reboot # extract vBIOS (before early-bind, with GPU still on amdgpu) cat /sys/kernel/debug/dri/0000:06:00.0/amdgpu_vbios > /usr/share/kvm/d500.rom # validate (after reboot; all should be on vfio-pci) for d in 0000:06:00.0 0000:06:00.1 0000:02:00.0 0000:02:00.1; do echo "$d -> $(basename "$(readlink /sys/bus/pci/devices/$d/driver)")"; done
qm (VM config)# GPU (video) qm set <VMID> -hostpci0 0000:06:00,pcie=1,romfile=d500.rom -vga none # CPU (host passthrough) qm set <VMID> -cpu host # keyboard/mouse (USB) qm set <VMID> -usb0 host=VVVV:PPPP -usb1 host=WWWW:QQQQ # audio (Mac's analog codec) qm set <VMID> -hostpci1 0000:00:1b.0,pcie=1
/etc/default/grubradeon.si_support=0 amdgpu.si_support=1 amdgpu.cik_support=1 update-grub
sudo rpm-ostree kargs --append-if-missing=radeon.si_support=0 --append-if-missing=amdgpu.si_support=1 \ --append-if-missing=amdgpu.cik_support=1 --append-if-missing=amdgpu.runpm=0
cat /sys/bus/pci/devices/0000:01:00.0/uevent | grep DRIVER # expected: DRIVER=amdgpu