GPU Passthrough no Mac Pro 6,1 (“lata de lixo”)

FirePro D500 → desktop Linux no monitor físico, via Proxmox

Publicado em 11 de julho de 2026

O objetivo deste guia é passar uma AMD FirePro D500 (GPU Tahiti, arquitetura GCN 1.0, de 2013) de um Mac Pro 6,1 (Late 2013, a “lata de lixo”) rodando Proxmox VE para dentro de uma VM, com a saída de vídeo aparecendo no monitor físico (HDMI/DisplayPort) — não em VNC/SPICE.

O resultado funciona de ponta a ponta em Linux Mint e Bazzite (Fedora Atomic). No Windows a GPU passa para a VM sem o famoso Code 43, mas o display físico não sai — o motivo está detalhado na seção sobre Windows.

É um problema interessante porque combina duas fontes de peculiaridade ao mesmo tempo: é uma GPU de Mac (vBIOS em EFI GOP, não x86 legado) rodando em hardware de 2013 (sem interrupt remapping na IOMMU). Cada uma dessas características, sozinha, já exige um ajuste específico no passthrough; juntas, exigem uma sequência de passos bem definida para funcionar.


Por que é difícil (e o que cada passo resolve)

As FirePro D500 são GPUs Tahiti (GCN 1.0 / Southern Islands) de 2013, com peculiaridades de Mac. A tabela abaixo resume os obstáculos encontrados e a solução aplicada a cada um:

Obstáculo Sintoma Solução
Mac Pro 6,1 não tem interrupt remapping vfio: Failed to set iommu for container: Operation not permitted allow_unsafe_interrupts=1
GPU de Mac não tem vBIOS x86 (usa EFI GOP) Invalid PCI ROM header signature: got 0xffff; GPU não enumera na VM extrair a vBIOS real e passar como romfile
O amdgpu do host pega a GPU no boot e a “suja” console do host na tela; depois reset recovery - restoring BARs ... blocked, host pode travar early-bind (vfio-pci.ids no cmdline) — prende a GPU ao vfio antes do amdgpu
x-vga=1 / POST da vBIOS de Mac no OVMF sem sinal no boot NÃO usar x-vga; usar vga: none (driver da VM assume)
Driver radeon legado não faz scanout na Tahiti tela preta com sinal forçar amdgpu (amdgpu.si_support=1)
HDMI do Mac é HDMI 1.4 (máx 4K@30) preto com sinal em 4K@60 forçar 1080p/1440p (no Xorg); Wayland/KDE negocia sozinho

Pré-requisitos

  • Proxmox VE 8/9 no Mac Pro 6,1; acesso root por SSH.
  • IOMMU/VT-d disponível (o Xeon E5 v2 do Mac Pro suporta).
  • Uma das duas GPUs livre para a VM.

Atenção: descubra qual GPU alimenta a porta física onde o monitor está — plugue o monitor e veja qual card fica 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

Em um Mac Pro 6,1 típico, o HDMI nativo costuma ser alimentado pela GPU no slot PCI 0000:06:00 (a primária/boot_vga); a outra GPU fica em 0000:02:00. Confirme sempre com o comando acima antes de prosseguir.

Como as duas D500 têm o mesmo device-id (1002:679e), o early-bind por id manda as duas GPUs para o vfio e o host fica headless (administrado por SSH/web). Isso é intencional e desejável aqui.

Descubra os IDs do seu hardware:

lspci -nn | grep -iE "VGA|Display|Audio"
# Referência: GPU 1002:679e (Tahiti LE), áudio HDMI 1002:aaa0, áudio analógico do Mac 8086:1d20 (Cirrus CS4208)

Passo 1 — IOMMU + módulos vfio (host)

Em /etc/default/grub, na linha GRUB_CMDLINE_LINUX_DEFAULT, adicione intel_iommu=on iommu=pt. Em /etc/modules, adicione vfio, vfio_iommu_type1 e vfio_pci.

# /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="... intel_iommu=on iommu=pt"

# /etc/modules
vfio
vfio_iommu_type1
vfio_pci

Passo 2 — allow_unsafe_interrupts (obrigatório no Mac Pro 6,1)

echo "options vfio_iommu_type1 allow_unsafe_interrupts=1" > /etc/modprobe.d/iommu_unsafe_interrupts.conf

Sem isso o vfio recusa (Operation not permitted). Implicação de segurança: uma VM maliciosa poderia, em teoria, injetar interrupções no host — aceitável num ambiente single-user/confiável; é o único caminho neste hardware (que não tem interrupt remapping).


Passo 3 — Early-bind: a peça-chave

Prenda as GPUs ao vfio-pci antes do amdgpu carregar, senão o amdgpu inicializa a GPU no boot, ela fica “suja”, e o passthrough falha (ou trava o host).

No GRUB_CMDLINE_LINUX_DEFAULT adicione (use os IDs do seu hardware):

vfio-pci.ids=1002:679e,1002:aaa0 video=efifb:off

E garanta a ordem dos drivers:

printf 'softdep amdgpu pre: vfio-pci\nsoftdep radeon pre: vfio-pci\n' > /etc/modprobe.d/vfio.conf

Aplique e reinicie o host:

update-grub && update-initramfs -u -k all && reboot

Após o reboot, valide (todas devem estar em vfio-pci, e o amdgpu NÃO deve ter inicializado nenhuma):

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"   # deve ser 0

Passo 4 — Extrair a vBIOS real da GPU

As D500 de Mac não expõem expansion ROM x86, mas a vBIOS (atombios) está acessível pelo host. O jeito mais fácil é capturá-la antes do early-bind (com a GPU ainda no amdgpu):

cat /sys/kernel/debug/dri/0000:06:00.0/amdgpu_vbios > /usr/share/kvm/d500.rom
# valide: ~64KB, header 55aa, contém "ATOMBIOSBK-AMD ... AMD_TAHITI_LE"
od -A x -t x1 -N 4 /usr/share/kvm/d500.rom   # 55 aa ...

Alternativa (sempre disponível, mesmo pós early-bind): a tabela ACPI VFCT (/sys/firmware/acpi/tables/VFCT contém a vBIOS + header). Guarde cópias — é insubstituível.


Passo 5 — Configurar a VM (sem x-vga, com romfile, vga: none)

qm set <VMID> -hostpci0 0000:06:00,pcie=1,romfile=d500.rom -vga none
qm set <VMID> -cpu host        # p/ Windows, usar: -cpu host,hidden=1  (anti Code 43)
  • Não use x-vga=1 (o OVMF não consegue POST da vBIOS de Mac → sem sinal).
  • vga: none faz a GPU física ser o único display. A VM deve ser OVMF/UEFI + q35.

⚠️ Em vga: none o console SPICE/noVNC do Proxmox não conecta (não há display virtual). Para acesso remoto/instalação, use vga: std temporariamente; troque para none só no modo “tela física”.


Passo 6 — Forçar o driver amdgpu dentro da VM

O radeon legado carrega mas não faz scanout na Tahiti → tela preta. Force o amdgpu:

Distro tradicional (ex.: Linux Mint, Ubuntu, Debian) — em /etc/default/grub:

radeon.si_support=0 amdgpu.si_support=1 amdgpu.cik_support=1

Depois update-grub e reiniciar a VM. (Em Mint/Ubuntu o grub.d/50_linuxmint.cfg também é lido; rode update-grub de verdade — só o /etc/default/grub.d/ próprio não basta.)

Fedora Atomic (ex.: 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

Depois reiniciar a VM. (O amdgpu.runpm=0 é a mitigação anti-freeze — ver abaixo.)

⚠️ Kernel 7.0 (Bazzite 44) NÃO dispensa os si_support (corrige uma observação anterior): a impressão de que “dispensava” foi um boot sortudo — há uma race radeon×amdgpu e às vezes nenhum pega a Tahiti (card0 fica sem driver → “sem sinal”). Mantenha os 3 si_support. Upgrades de imagem Atomic resetam os kargs custom → reaplique após um upgrade grande.

⚠️ amdgpu.runpm=0 é praticamente obrigatório no kernel 7.0/-ogc do Bazzite para o passthrough não travar o HOST inteiro: sem ele, o runtime PM (estado BACO) da GPU no guest trava o PCIe do host num deadlock silencioso (sem AER/MCE; só power cycle recupera) — compatível com o CVE-2026-53293 (deadlock no amdgpu, GCN 1.0+, divulgado jun/2026). Com runpm=0 o reset fica limpo (reset done) e o host estável (validado: boot físico + reboot da VM + uso, sem freeze).

Valide na VM: cat /sys/bus/pci/devices/0000:01:00.0/uevent | grep DRIVERDRIVER=amdgpu.


Passo 7 — Resolução, teclado/mouse e áudio

Resolução: o HDMI do Mac Pro é HDMI 1.4não exibe 4K@60 (preto com sinal). No Xorg (Mint), force 1080p ou 1440p (modeline + modesetting). No Wayland/KDE (Bazzite) a resolução é negociada automaticamente — não precisa forçar.

Teclado/mouse: USB passthrough — pegue os IDs com lsusb e passe cada dispositivo:

qm set <VMID> -usb0 host=VVVV:PPPP -usb1 host=WWWW:QQQQ

Funciona a quente (sem reiniciar a VM).

Áudio: se o monitor não tem falantes, o áudio HDMI não serve. Passe o codec analógico do Mac (no Mac Pro 6,1 é um Cirrus CS4208, 0000:00:1b.0) para a VM:

qm set <VMID> -hostpci1 0000:00:1b.0,pcie=1

(vira “CS4208 Analog” dentro da VM). O Mac Pro 6,1 tem duas saídas analógicas traseiras: fone de ouvido (com jack detection) e saída de linha (combo óptico — a luzinha vermelha é o TOSLINK, inofensiva). Ligue o fone na saída de fone e selecione a porta “Fone de ouvido” no mixer (KDE/PipeWire) — selecionar “Saída de linha” usa outro caminho do codec e fica mudo. Sintoma do caminho errado: o Headphone DAC (nó 0x02) fica em volume 0x00 e o pino 0x10 mutado; ao selecionar a porta certa o WirePlumber sobe o volume de hardware e desmuta. No Bazzite (PipeWire) o alto-falante interno também tocou sem quirk; no Mint só a saída traseira sai (speaker interno mudo sem model= no snd_hda_intel).


Armadilhas (aprendidas na marra)

  • ⚠️ Nunca reconecte o cabo do monitor com a VM ligada. O hotplug do display numa GPU AMD passada trava o kernel do host inteiro (freeze vfio/PCIe) — exige power cycle. Desligue a VM antes de mexer no cabo.
  • ⚠️ Se o passthrough travar o host de forma recorrente, faça um power cycle completo (energia cortada ~1 min) — reseta o estado de hardware da GPU, o que um reboot de kernel não desfaz.
  • Após reboots, em redes instáveis o DHCP de containers/VMs pode falhar (sem rede/DNS) → renove com dhclient -1 eth0.
  • O guest agent de distros Atomic (Bazzite) é confinado — não roda binários privilegiados via qm guest exec. Escreva um script em /tmp e rode-o pelo terminal da VM.

Windows 10/11 (parcial)

A GPU passa sem Code 43 usando -cpu host,hidden=1 + o romfile. A placa aparece como “AMD Radeon HD 7800 Series” funcionando no Gerenciador de Dispositivos, com o driver Adrenalin legacy (21.5.2 ou 22.6.1).

Porém o display físico não sai: com vga: none/x-vga o OVMF não consegue fazer POST da vBIOS de Mac (sem sinal), e com display virtual o Windows não detecta o monitor na GPU secundária. O Linux funciona porque o driver KMS assume a GPU no boot; o Windows depende do POST do firmware. Não resolvido aqui.


Reversão

Para voltar o host ao estado padrão: remova vfio-pci.ids, intel_iommu e video=efifb:off do cmdline, apague /etc/modprobe.d/{vfio,iommu_unsafe_interrupts}.conf e os módulos vfio de /etc/modules, remova hostpci*/usb* da VM e volte vga: std. Depois:

update-grub && update-initramfs -u -k all && reboot

O que fica validado com este guia: uma saída de vídeo física, numa VM Linux, com uma AMD FirePro D500 passada de um Mac Pro 6,1. Confirme sempre os device-IDs e slots PCI do seu próprio hardware com lspci -nn antes de reproduzir os passos.


Cheat sheet — comandos por local

Resumo copia-e-cola dos comandos já apresentados nas seções acima, agrupados por onde cada um roda. Os device-IDs e slots PCI são do hardware de referência deste guia — confirme os seus com lspci -nn antes de copiar.

1. Host — /etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULT="... intel_iommu=on iommu=pt vfio-pci.ids=1002:679e,1002:aaa0 video=efifb:off"

2. Host — /etc/modules

vfio
vfio_iommu_type1
vfio_pci

3. Host — /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

4. Host — shell (aplicar + extrair vBIOS + validar)

# aplicar
update-grub && update-initramfs -u -k all && reboot

# extrair vBIOS (antes do early-bind, com a GPU ainda no amdgpu)
cat /sys/kernel/debug/dri/0000:06:00.0/amdgpu_vbios > /usr/share/kvm/d500.rom

# validar (após reboot; todas devem estar em 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

5. Proxmox — qm (config da VM)

# GPU (vídeo)
qm set <VMID> -hostpci0 0000:06:00,pcie=1,romfile=d500.rom -vga none

# CPU (host passthrough)
qm set <VMID> -cpu host

# teclado/mouse (USB)
qm set <VMID> -usb0 host=VVVV:PPPP -usb1 host=WWWW:QQQQ

# áudio (codec analógico do Mac)
qm set <VMID> -hostpci1 0000:00:1b.0,pcie=1

6. VM Linux (distro tradicional) — /etc/default/grub

radeon.si_support=0 amdgpu.si_support=1 amdgpu.cik_support=1

update-grub

7. VM Linux (Fedora Atomic) — 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

8. VM — validação

cat /sys/bus/pci/devices/0000:01:00.0/uevent | grep DRIVER
# esperado: DRIVER=amdgpu