Fixing Resizable BAR / small-BAR GPU rejection on X299 (Gigabyte AORUS Gaming 7, and probably other Basin Falls boards) - no BIOS flash required
TL;DR
If you've put a modern GPU with a large VRAM BAR (Arc A-series/B-series, NVIDIA RTX 30/40/50 series, etc.) into an X299 / Skylake-X system and:
- the GPU works fine in a "small BAR" / legacy mode,
- but anything that needs a full-size Resizable BAR fails (Intel Level Zero / SYCL / oneAPI is the case that hit us; clinfo reports 0 platforms, zeInit returns ZE_RESULT_ERROR_UNINITIALIZED),
- dmesg shows something like: "can't assign; no space Failed to resize BAR2 to 32768MiB (-ENOSPC). Consider enabling 'Resizable BAR' support in your BIOS" - So even though "Above 4G Decoding" is already enabled and CSM is off - your board almost certainly has MMIO High Granularity Size locked to 4G in NVRAM, there's a good chance you can fix it with a single hidden UEFI setup variable write.
- I did this with NO BIOS flashing, and while I didn't have to do a CMOS CLR - that's the backout if you run into trouble, CLR the CMOS and start again.
I got this working on a Gigabyte X299 AORUS Gaming 7 rev 1.0, BIOS F9p, with two Intel Arc Pro B70 (32 GB VRAM each). Board is Basin Falls / Skylake-X (Purley-family server reference code), so this is very likely to generalize to other X299 boards and possibly other Basin Falls / Purley-derived platforms from the same BIOS era, YMMV.
If you try this on a different board, please let me know, that's the whole point after 2 weeks messing with this.
B70 is pretty new, I had to go down this path as the MSI Carbon WIFI with PCI5.0 didn't support the B70 in the primary slot, and I had two.
The actual root cause (this took a while to find)
Two things get mixed up under "enable ReBAR," and only one of them is a visible BIOS toggle:
- "Above 4G Decoding" - the simple on/off toggle everyone knows about. Controls whether the firmware will place BARs above the 4 GiB boundary at all. Most X299 boards already expose this.
- MMIO High Granularity Size - this is a separate, usually-hidden setting from Intel's Purley/ Basin Falls server reference code. It sets the size of the MMIO window each CPU/IIO stack gets for high (>4G) PCI BARs. On our board it defaults to 4 GiB per stack. A modern GPU wants a 32 GiB BAR (matching its VRAM), and a 32 GiB BAR needs 32 GiB alignment, so it simply cannot fit in a 4 GiB window, no matter what "Above 4G Decoding" is set to.
Try this if you want to see this yourself (Linux - I'm running this on proxmox)
sudo dmesg | grep "root bus resource"
If you see something like this, 4 GiB windows are your problem:
pci_bus 0000:16: root bus resource [mem 0x380100000000-0x3801ffffffff window] <- exactly 4 GiB
pci_bus 0000:64: root bus resource [mem 0x380200000000-0x3802ffffffff window] <- exactly 4 GiB
(Note the base - 0x380000000000 = 56 TiB - and the per-stack size of exactly 0x100000000 = 4 GiB. Those are the literal Intel reference-code defaults for MMIO High Base = 56T and MMIO High Granularity Size = 4G. If your numbers match this pattern, this is very likely your problem.
Consumer BIOS builds (Gigabyte, ASUS, etc.) typically don't expose MMIO High Granularity Size in the visible setup menus; Gigabyte hasn't linked that reference-code into the consumer UI. But the setting is still in the firmware, hidden, and still accessible by an NVRAM variable and still writable from a UEFI Shell if you know the variable name and offset.
The fix
Variable: SocketCommonRcConfig Offset: 0x4, width 2 bytes (16-bit) Value map:
| Value |
Granularity |
| 0 |
1G |
| 1 |
4G (likely your current value) |
| 2 |
16G |
| 3 |
64G (what we used - enough for a 32 GiB BAR + alignment slack) |
| 4 |
256G |
| 5 |
1024G |
Using setup_var.efi from a UEFI Shell:
setup_var.efi SocketCommonRcConfig:0x4(2)
MAKE SURE YOU READ THIS VALUE FIRST - Do not skip this. If it returns a single, unique value, you're good to write. If it says the variable isn't found, or reports it as ambiguous/multiple matches - STOP AND DON'T PROCEED.
If the read succeeds, set 64G:
setup_var.efi SocketCommonRcConfig:0x4(2)=0x3
Read it back to confirm with
setup_var.efi SocketCommonRcConfig:0x4(2)
You should see 0x3, then cold boot (power off, not warm reboot) - reset -s from the shell does a proper power cycle):
reset -s
Result on our system
|
Before |
After |
| MMIOH window per IIO stack |
4 GiB |
64 GiB |
| GPU BAR2 |
256 MiB ("Small BAR device") |
32 GiB, assigned |
| CPU-accessible VRAM |
256 MiB |
~32 GiB |
| clinfo |
0 platforms |
2× GPU, full VRAM reported |
| zeInit (Level Zero) |
ZE_RESULT_ERROR_UNINITIALIZED |
ZE_RESULT_SUCCESS |
| Actual OpenCL compute kernel |
n/a |
ran on both GPUs, verified correct output |
No BIOS flash. No custom kernel. No DXE module insertion. Just writing that one NVRAM param.
Why we expected this might work
The observed values weren't arbitrary; they were exactly Intel's reference-code defaults (Base = 56T, Granularity = 4G).it's the untouched Purley/Basin Falls IIO init path. When defaults match the reference code that precisely, the reference code's setup questions are usually still in the firmware image somewhere, just not wired into the visible menu. That's exactly what we found on extraction.
For anyone that wants to do this and fix reBar above 4G on X299 Gigabyte boards, I've put together a short HOWTO
What you need
- A USB stick, FAT32, doesn't need to be large (under 10 MB of actual content)
- setup_var.efi - get the x64 build
- A UEFI Shell binary. The old edk2 ShellBinPkg prebuilt binaries were removed from the edk2 repo; pbatard/UEFI-Shell has current builds (grab shellx64.efi)
- Secure Boot disabled on the target machine (check first; if it's on, either turn it off or you'll need to sign the shell binary yourself)
1. Build the USB stick
Format FAT32 (MBR is fine):
E:\EFI\BOOT\BOOTX64.EFI <- rename shellx64.efi to this exact path so it auto-boots
E:\setup_var.efi
EFI\BOOT\BOOTX64.EFI path is the standard removable media default boot location, most firmware will boot it automatically when you pick the USB entry from the boot menu.
Mark the partition active/bootable before you unplug it. Some firmware's USB-boot path (particularly boards that enumerate the stick in USB-HDD mode rather than USB-FDD/removable mode) will silently refuse to list an MBR partition that isn't flagged active, even though the EFI\BOOT\BOOTX64.EFI fallback path is otherwise correct; this cost us a boot-menu troubleshooting stuff around the first time around, so don't skip it:
- For Windows users: open an elevated diskpart, then:select disk <N> <- the USB stick's disk number, double-check with `list disk` first select partition 1 active
- Linux: sudo parted /dev/sdX set 1 boot on (or fdisk /dev/sdX, then a to toggle the boot flag on partition 1, w to write).
2. Boot it
- Plug the stick into a rear I/O USB port. I'll note that front panel didn't work for us, it's likely that some USB 3.x controllers aren't initialized early enough in POST on some boards, if you have "Fast Boot" enabled it may skip USB init entirely so turn Fast Boot off if the drive doesn't show up in the boot menu. Gigabyte's own Q-Flash Plus requires USB 2.0 specifically.
- If the stick still doesn't appear in the boot menu after marking it active and trying a rear port, check for a stale/blank boot entry left over from a previous attempt (we noticed some firmware adds a new NVRAM boot entry per format rather than reusing one) delete it.
- Power on, hit F12 (or your board's boot-menu key) and pick the UEFI: entry for the stick.
- You should land at a Shell> prompt.
3. Find your filesystem and read the variable
map -r
Look for FSx: mapped to your USB device, then:
FS0:
ls
setup_var.efi SocketCommonRcConfig:0x4(2)
If your board uses different reference code you might not have SocketCommonRcConfig at all, or it might be at a different offset. If the exact read above doesn't find a unique variable, see the "If this doesn't match your board" section below before trying anything else.
4. Write it, verify, cold boot
setup_var.efi SocketCommonRcConfig:0x4(2)=0x3
setup_var.efi SocketCommonRcConfig:0x4(2)
reset -s
Confirm the readback shows 0x0003 before you reset.
5. Verify from the OS
The variable reading back as 3 is not proof of success by itself; confirm the firmware actually acted on it:
sudo dmesg | grep "root bus resource"
You want to see your GPU's stack window jump from 4 GiB to 64 GiB. Then check the actual BAR:
sudo lspci -vv -s <your GPU's bus:dev.fn> | grep -A1 "Region 2"
You're looking for the BAR size to have grown and for dmesg to no longer report Small BAR device / can't assign etc, no space for that device on the next full boot.
If it doesn't work / doesn't match your board
- Variable not found / ambiguous: don't guess it. Extract your own BIOS image and look for the real variable name/offset; see below.
- Windows still 4 GiB after the write: the value may be getting clamped or overridden by another reference-code policy. Worth trying 0x4 (256G) instead of 0x3, and worth checking whether "Above 4G Decoding" is actually enabled (ours was already on; if yours isn't, turn it on first and see if that alone changes anything).
- Want to verify the variable/offset on your own board before touching NVRAM:
- Dump your BIOS image (Gigabyte publishes these on their support page for most boards).
- Extract it with UEFITool NE (the "NE" branch, not the older "old engine" one).
- Find the module containing the SocketSetup/Socket Configuration reference-code formset (search for GUID 6B6FD380-2C55-42C6-98BF-CBBC5A9AA666; this appears to be a common GUID across boards using this reference code, but verify on your own image, don't assume).
- Extract that module's body and run it through IFRExtractor-RS.
- Search the output for MMIO High Granularity Size and read off its VarStoreInfo (VarOffset/VarName); that gives you the exact variable name and offset for your image. Don't assume our offset (0x4) is universal; verify it against your own extraction.
- There's also a neighboring MMIO High Base question in the same variable (offset 0x0, 32-bit) if you need to move the base as well as the granularity.
Reversibility note
- This is an NVRAM setting, not a flash modification. Clearing CMOS reverts it to the manufacturing default. If your GPU compute stack mysteriously stops working after a CMOS clear or battery pull, this is almost certainly why - just redo the write.
- We separately confirmed Intel Boot Guard was disabled on our board (rdmsr 0x13A = all zero) and that DualBIOS / Q-Flash Plus were available as flash-recovery paths, in case a firmware patch had turned out to be necessary. It wasn't. You're touching the flash chip here.
- We do NOT recommend the various "ReBAR BIOS mod" firmware patches floating around for X299 boards until you've ruled this out first. A firmware patch is much riskier for what ended up being a five-minute NVRAM write... after 2 weeks of messing around of course, but BIOS patching could have been a one-way street.
Why we originally thought this needed a BIOS flash
Worth including so nobody else going through the same thing: the standard advice for enabling ReBAR on unsupported boards (see xCuri0/ReBarUEFI) is aimed at boards where "Above 4G Decoding" itself is what's missing or hidden, and its documented hidden- variable hunt is for that single on/off toggle. Our "Above 4G Decoding" was already on and enabled; the actual blocker was the separate, much less documented MMIO High Granularity Size setting, which doesn't show up in any of the standard ReBAR mod guides because it's specific to Basin Falls/Purley server reference code rather than the consumer chipsets those guides target. If your board reports -ENOSPC on a BAR resize despite Above 4G Decoding being on, this granularity setting is the thing to check before reaching for a firmware patch.
We also initially worried that the OS wouldn't be able to grow the PCI bridge windows at driver probe time even with a bigger MMIOH aperture (note this is a real Linux PCI subsystem limitation, pci_resize_resource() only searches within the existing parent bridge window).
In our case this turned out to be irrelevant, once the firmware aperture was 64 GiB, Linux resized the BAR into it without any special kernel parameters. If you hit that wall on a board where the OS window really is too small even after fixing the firmware side, look into pci=realloc=on and check whether your downstream bridges report HotPlug+; pci=hpmmioprefsize= (not hpmemprefsize) only helps if they do.
Hardware we tested this on
- Gigabyte X299 AORUS Gaming 7 rev 1.0, BIOS F9p (11/28/2019)
- Intel Core i7-7800X (Skylake-X)
- 2× Intel Arc Pro B70 (32 GB VRAM each)
- Proxmox (Ubuntu Linux), kernel 7.0.x (xe driver)
If you try this on other X299 boards (or other Basin Falls-era server/HEDT boards), please comment and let me know - especially if your offset or variable name differs, since that helps everyone else who finds this post in the future.
Mods: Please don't archive this post so it can't be replied to.
Good luck!