Diagnosing the Impossible: How Eight NVIDIA GPUs Lost Their Memory in a Proxmox VM
In the high-stakes world of multi-GPU machine learning deployments, few problems are as disorienting as booting up a freshly configured server and discovering that six out of eight top-tier NVIDIA RTX PRO 6000 GPUs have simply vanished. Not because they are physically absent, not because the drivers are missing, but because the virtual machine's firmware literally ran out of address space to map their memory. This is the crisis addressed in message 339 of a lengthy opencode session, where an AI assistant synthesizes hours of research, kernel log analysis, and QEMU internals into a coherent plan to rescue a stranded GPU inference server.
The message in question—[msg 339]—is the culmination of a multi-round debugging effort that began when the assistant and user migrated a Proxmox VM from the legacy i440FX chipset to the modern Q35 chipset with PCIe passthrough (pcie=1). This migration was itself part of a larger quest to enable Peer-to-Peer (P2P) DMA between GPUs, a critical capability for high-performance distributed inference workloads. But the migration opened a Pandora's box of PCI BAR (Base Address Register) allocation failures that left the system crippled.
The Scene: A Server with Eight GPUs and Two Working
To understand the weight of this message, we must first appreciate what came before it. The conversation's broader context (segments 0–3 of the opencode session) traces a journey from bare-metal Ubuntu installation through driver configuration, flash-attn compilation, SGLang deployment, and an escalating battle with virtualization overhead. By the time we reach message 339, the user and assistant have already:
- Installed NVIDIA drivers and CUDA Toolkit 13.1 on Ubuntu 24.04
- Resolved flash-attn build issues by carefully tuning parallel compilation jobs
- Deployed the GLM-5-NVFP4 model across 8 RTX PRO 6000 Blackwell GPUs
- Discovered that cross-GPU communication was bottlenecked by virtualization-induced PCIe latency
- Attempted to enable P2P DMA by migrating from i440FX to Q35 with
pcie=1 - Found that the migration caused 6 of 8 GPUs to fail with
BAR2 is 0M @ 0x0errors In the immediately preceding message ([msg 332]), the assistant had analyzed dmesg output and identified the BAR allocation failure, proposing several fixes including addingpci=reallocto the guest kernel or increasing the QEMU MMIO window viamch.above_4g_mem_size. The user then executed a command on the host (qm set 128 -args '-global mch.above_4g_mem_size=2T') but immediately expressed uncertainty, asking whether to undo it and whether switching to OVMF (UEFI firmware) might help ([msg 333]). The assistant then spent several rounds researching—fetching a blog post by QEMU maintainer Gerd Hoffmann on physical address space sizing, reading Proxmox forum threads about RTX 5090 passthrough issues, and studying a tutorial on PCI BAR debugging (<msgs id=334–338>). Message 339 is the synthesis: a clear-eyed, well-structured diagnosis that cuts through the complexity and presents a prioritized action plan.
The Root Cause: A 1.5 Terabyte Window for a 1 Terabyte Problem
The assistant's analysis in [msg 339] is notable for its precision. Rather than hand-waving about "driver issues" or "compatibility problems," it drills into the exact mechanics of PCI BAR allocation. Each RTX PRO 6000 GPU exposes three BARs: BAR0 (64MB for control registers), BAR2 (128GB for VRAM mapping), and BAR4 (32MB). With eight GPUs, the total BAR2 space required is 1TB—just for the VRAM mappings.
The guest firmware (SeaBIOS 1.16.3) allocates a 64-bit MMIO aperture spanning from 0x380000000000 to 0x395fffffffff, which is approximately 1.5TB. This should, in theory, accommodate the 1TB of BAR2 space plus the smaller BARs. The assistant carefully enumerates the eight PCIe bridge windows, each 160GB in size, totaling 1.28TB—well within the 1.5TB root window. Yet only two GPUs (at PCI addresses 04:00.0 and 08:00.0) successfully received BAR assignments.
The key insight is that the bridge windows are large enough, and the total address space is sufficient, but the firmware's allocation algorithm fails to place BAR2 within six of the eight bridges. The dmesg error can't claim; no compatible bridge window reveals that the firmware cannot find a suitable placement for the 128GB BAR2 within the bridge's prefetchable window, even though the window is technically large enough. This is a subtle firmware-level resource allocation bug, not a fundamental capacity problem.
The assistant correctly identifies the guest kernel's own suggestion as the most promising lead: pci_bus 0000:00: Some PCI device resources are unassigned, try booting with pci=realloc. This kernel parameter tells Linux's PCI subsystem to attempt a second pass at resource allocation, potentially reassigning BARs that the firmware failed to place.
Three Options, One Recommended Path
The message presents three options in a carefully ordered sequence, reflecting a pragmatic engineering mindset that values minimal invasiveness and reversibility.
Option 1 (undo the mch.above_4g_mem_size arg and use proper approach) is presented first but immediately undermined by the assistant's own reasoning. The assistant realizes that since cpu: host is already set, host-phys-bits=on should already be active, making this option redundant. The inclusion of this option—followed by its partial retraction with "Wait—actually"—is a fascinating window into the assistant's real-time reasoning. It demonstrates an iterative refinement process: the assistant proposes a hypothesis, tests it against known facts, and corrects itself within the same message. This is not a polished final answer but a thinking-in-progress document, and that honesty about the reasoning process is one of the message's strengths.
Option 2 (add pci=realloc to the guest kernel) is the recommended first step. It is minimally invasive—requiring only a GRUB configuration change inside the VM—and directly addresses the error message the kernel itself produced. The assistant provides exact commands, showing awareness that the user needs executable instructions, not just conceptual understanding.
Option 3 (switch to OVMF with a large MMIO aperture) is the fallback if pci=realloc alone fails. This is a more invasive change because it requires converting the boot disk from MBR to GPT and creating an EFI disk. The assistant correctly notes that OVMF previously failed to boot when the VM was on i440FX (which doesn't support OVMF), but should work now that the VM is on Q35. The recommended MMIO aperture size of 1.5TB (expressed as 1,572,864 MB via the X-PciMmio64Mb OVMF fw_cfg option) is carefully calculated to accommodate eight 128GB BARs with headroom.
The recommended sequence is pragmatic: try the simplest fix first, escalate only if needed, and always maintain a path back to a working state.
Assumptions and Their Risks
Every diagnosis rests on assumptions, and this message is no exception. The assistant assumes that SeaBIOS 1.16.3 correctly handles host-phys-bits when QEMU communicates the right value. This assumption is reasonable given the SeaBIOS version and the QEMU version in use, but the fact that BAR allocation is failing suggests either the assumption is wrong or there is an additional constraint not yet identified.
The assistant also assumes that pci=realloc will succeed if the firmware has placed BAR2 somewhere—even if not in the correct bridge window. The kernel's PCI reallocator works by taking whatever resources the firmware assigned and attempting to redistribute them. If the firmware truly failed to assign BAR2 at all (leaving it at 0x0), the reallocator may have nothing to work with. The assistant acknowledges this risk implicitly by presenting Option 3 as a fallback.
Another assumption is that the user's VM was installed with SeaBIOS/MBR boot. The assistant hedges this by noting that OVMF conversion "is doable but more invasive," but does not verify the actual boot configuration before recommending the sequence. In a production environment, one might want to confirm the boot method before suggesting firmware changes.
Perhaps the most significant unstated assumption is that fixing BAR allocation will ultimately enable P2P DMA. The broader context of the session makes clear that the entire Q35 migration was motivated by P2P enablement. But as later chunks in the session reveal, the hardware topology—each GPU on its own PCIe root complex—fundamentally prevents P2P regardless of BAR allocation. The assistant is solving a necessary but not sufficient precondition.
The Thinking Process: A Case Study in Technical Synthesis
What makes [msg 339] particularly interesting as a subject of analysis is the visible thinking process. The message is structured as a synthesis following several rounds of research, and it shows the assistant working through multiple lines of evidence:
- Direct evidence from dmesg: The
BAR2 is 0M @ 0x0errors and thecan't claim; no compatible bridge windowmessages are the primary data points. - Quantitative analysis: The assistant calculates the total BAR space (8 × 128GB = 1TB), the bridge window sizes (8 × 160GB = 1.28TB), and the root window size (1.5TB), demonstrating that the problem is not raw capacity but allocation algorithm behavior.
- Firmware behavior knowledge: The assistant draws on understanding of how SeaBIOS sizes its 64-bit MMIO aperture based on
host-phys-bits, and how QEMU communicates physical address space limits to the guest. - Community knowledge: The research rounds preceding this message (<msgs id=335–338>) included fetching Gerd Hoffmann's blog post on QEMU physical address space, reading Proxmox forum threads about RTX 5090 passthrough, and studying a PCI BAR debugging tutorial. This community-sourced knowledge informs the OVMF MMIO aperture sizing recommendation.
- Self-correction: The most striking feature of the thinking process is the assistant's willingness to correct itself mid-message. When proposing
-cpu host,host-phys-bits=onas a fix, it immediately realizes thatcpu: hostalready implies this, and pivots. This self-correction is not hidden or edited—it is presented as part of the message, giving the reader insight into the assistant's real-time reasoning.
Input Knowledge Required
To fully understand this message, a reader needs familiarity with several domains:
- PCI BAR fundamentals: Understanding that BARs are address windows that map device memory into the CPU's physical address space, and that each GPU needs a large contiguous window for its VRAM.
- QEMU/Proxmox virtualization: Knowledge of the i440FX vs. Q35 chipset difference, the role of SeaBIOS vs. OVMF as firmware, and how PCIe passthrough works in Proxmox.
- Linux kernel PCI subsystem: Understanding what
pci=reallocdoes and why the kernel might need a second pass at resource allocation. - GPU architecture: Awareness that modern NVIDIA GPUs (especially the RTX PRO 6000 with 96GB VRAM) require large BAR mappings—128GB in this case, which is larger than the GPU's actual VRAM because BAR2 maps the entire VRAM address space plus some overhead. The assistant assumes this knowledge implicitly by not explaining these concepts from scratch. The message is written for an audience (the user) who has been deeply engaged in the configuration process and has already demonstrated familiarity with Proxmox administration, GPU passthrough, and kernel parameter tuning.
Output Knowledge Created
This message creates several forms of actionable knowledge:
- A prioritized troubleshooting sequence for large-BAR GPU passthrough failures in Proxmox, which could be extracted and applied to similar configurations (e.g., RTX 5090, A100, H100 passthrough).
- A quantitative model of PCI BAR allocation for multi-GPU VMs, including the specific sizing calculations (128GB per BAR2, 160GB per bridge window, 1.5TB root window) that can be adapted to other GPU counts and VRAM sizes.
- The OVMF MMIO aperture configuration (
-fw_cfg name=opt/ovmf/X-PciMmio64Mb,string=1572864) as a concrete, copy-pasteable solution for Proxmox hosts needing to support multiple large-BAR GPUs. - A diagnostic methodology that combines dmesg analysis, quantitative capacity planning, and firmware behavior knowledge to isolate BAR allocation issues from other classes of GPU passthrough problems.
Conclusion: A Message at the Crossroads
Message 339 stands at a pivotal moment in the broader session. It represents the assistant's best effort to solve a problem that, as later chunks reveal, has a deeper hardware-level cause that no software fix can fully address. The BAR allocation fix is necessary but not sufficient for the ultimate goal of P2P DMA enablement.
But within its scope, the message is a model of technical communication under uncertainty. It presents a clear diagnosis backed by quantitative evidence, offers multiple options with explicit trade-offs, recommends a prioritized sequence, and—most importantly—shows its work. The visible reasoning process, including the mid-message self-correction, transforms what could be a dry technical instruction set into a genuine collaborative investigation. The assistant is not just telling the user what to do; it is showing the user how to think about the problem.
For anyone who has ever stared at a server that should have eight GPUs but only sees two, this message offers both practical guidance and, perhaps more valuable, the reassurance that the path forward is knowable—one kernel parameter, one firmware setting, one careful dmesg reading at a time.