MS-A2 BIOS 1.03 breaks PCIe passthrough ("1:1 IOMMU mapping"): root cause + working fix without downgrading
TL;DR: Every BIOS 1.03 build I know of,
including the latest 04/01/2026 re-release, ships an ACPI IVRS table that marks every PCI device on buses 00-0F as needing a forced 1:1 IOMMU mapping. VFIO then refuses to pass through
any device: GPU, NIC, NVMe, SR-IOV VFs, all of them. No BIOS setting or kernel version fixes it. You can downgrade to 1.02, or stay on 1.03 and load a corrected IVRS table from the initrd. I did the second; details below.
Setup
- MS-A2 (9955HX), BIOS 1.03, dated 04/01/2026 per dmidecode (the re-release that was reported as "works fine")
- Proxmox VE 9, kernel 7.0.14-20-pve, ZFS root, GRUB through proxmox-boot-tool
- Intel E810-XXV dual-port. The host keeps the PFs on the ice driver (for DDP); one SR-IOV VF per port goes to an OPNsense/Linux router VM
- Passthrough worked on 1.02. After flashing 1.03 it broke completely.
Symptoms
The VM fails to start. QEMU says:
Code:
kvm: -device vfio-pci,host=0000:07:01.0,...: vfio 0000:07:01.0: failed to setup container for group 28: Failed to set group container: Invalid argument
and dmesg has the real reason:
Code:
vfio-pci 0000:07:01.0: Firmware has requested this device have a 1:1 IOMMU mapping, rejecting configuring the device without a 1:1 mapping. Contact your platform vendor.
It happens for whole devices (PFs) and for VFs alike.
Quick check: are you affected?
Code:
cat /sys/kernel/iommu_groups/*/reserved_regions | grep -c direct
On 1.03 I got a "direct" entry in
every IOMMU group (28 of 28):
Code:
0x00000000b2da4000 0x00000000b2da4fff direct
0x00000000b5e45000 0x00000000b5e46fff direct
0x00000000fee00000 0x00000000feefffff msi
0x000000fd00000000 0x000000ffffffffff reserved
Any number above 0 means passthrough of those devices is blocked.
Root cause
1.03 added three IVMD (memory definition) entries to the IVRS table:
Code:
Subtable Type : 22 [Memory Definition Block (IVMD)] <- type 0x22 = device range
Flags : 08 -> Unity 0, Readable 0, Writeable 0, Exclusion Range 1
DeviceId : 0000
Auxiliary Data: 0FFF <- end of range: devices 00:00.0 .. 0F:1F.7 = everything
Start Address : 00000000B5E46000 Length 0x1000
(same again for B5E45000 and B2DA4000)
Linux treats exclusion ranges as read/write unity maps, so each device in the range gets a non-relaxable IOMMU_RESV_DIRECT region. Since kernel 6.x, VFIO refuses to attach any device that has a "require direct" region. The range 0x0000-0x0FFF covers every bus, so nothing can be passed through.
A 1.02 table doesn't have these entries. Removing them restores 1.02 behaviour.
What I/others tried that does NOT help: other kernels (6.17, 7.0.x), removing iommu=pt, toggling Above 4G / ReBAR / ACS in the BIOS, pcie_acs_override, legacy VFIO vs iommufd. "amd_iommu=relax_unity" has been mentioned but isn't in any PVE kernel.
Option A: downgrade to 1.02
F1WSA_FRG_1.02_250616a. Per Minisforum support (see earlier posts in this thread), reflash 1.03 over 1.03 first, then flash 1.02. Going straight from 1.03 to 1.02 reportedly bricked at least one unit.
Option B: stay on 1.03 and override the IVRS table (what I did)
The PVE kernel has CONFIG_ACPI_TABLE_UPGRADE=y, so it can load a replacement ACPI table from an uncompressed cpio at the front of the initrd. No kernel recompile.
1. Build the corrected table
Install acpica-tools. If the host has no internet, download the .deb elsewhere and copy it over; it only depends on libc6:
Code:
# trixie / PVE 9:
# http://deb.debian.org/debian/pool/main/a/acpica-unix/acpica-tools_20250404-1_amd64.deb
dpkg -i acpica-tools_20250404-1_amd64.deb
mkdir -p /root/ivrs && cd /root/ivrs
cp /sys/firmware/acpi/tables/IVRS IVRS.orig.dat
iasl -d IVRS.orig.dat # -> IVRS.orig.dsl
grep -n "Subtable Type" IVRS.orig.dsl # the three type-22 IVMD entries are the LAST subtables
Keep everything before the first IVMD and bump the OEM revision. The kernel only replaces a table if the new one has a higher revision:
Code:
n=$(grep -n "Subtable Type : 22" IVRS.orig.dsl | head -1 | cut -d: -f1)
head -n $((n-1)) IVRS.orig.dsl | sed 's/\(Oem Revision : \)00000001/\100000002/' > IVRS.dsl
iasl IVRS.dsl # -> IVRS.aml, 200 bytes (was 296)
Sanity checks: disassemble IVRS.aml again and diff it against the original. The only differences should be table length (0x128 -> 0xC8), checksum, OEM revision and compiler ID, plus the three missing IVMD blocks. I also byte-compared the IVHD part, and it's identical:
Code:
cmp -l <(head -c 200 IVRS.orig.dat) IVRS.aml # only header bytes 5,6,10,25,29-36 differ
2. Load it from the initrd with an initramfs-tools hook
The Proxmox forum guide uses GRUB_EARLY_INITRD_LINUX_CUSTOM with a cpio in /boot. On proxmox-boot-tool systems (ZFS root, kernels/initrds copied to the ESPs) I didn't want to rely on that. A hook that calls prepend_earlyinitramfs (the same mechanism microcode uses) puts the table inside every initrd. That works for GRUB and systemd-boot, and every future kernel upgrade picks it up automatically.
Code:
mkdir -p /etc/initramfs-tools/acpi
cp /root/ivrs/IVRS.aml /etc/initramfs-tools/acpi/ivrs.aml
cat > /etc/initramfs-tools/hooks/acpi-ivrs-override <<'EOF'
#!/bin/sh
# Prepend patched ACPI IVRS (MS-A2 BIOS 1.03: IVMD 0000-0FFF entries removed).
# Remove this hook + run update-initramfs -u -k all once the BIOS is fixed.
PREREQ=""
prereqs() { echo "$PREREQ"; }
case "$1" in prereqs) prereqs; exit 0 ;; esac
. /usr/share/initramfs-tools/hook-functions
AML=/etc/initramfs-tools/acpi/ivrs.aml
[ -f "$AML" ] || exit 0
TMP=$(mktemp -d)
mkdir -p "$TMP/kernel/firmware/acpi"
cp "$AML" "$TMP/kernel/firmware/acpi/ivrs.aml"
(cd "$TMP" && find kernel | cpio -H newc -o --quiet) > "$TMP.cpio"
prepend_earlyinitramfs "$TMP.cpio"
rm -rf "$TMP" "$TMP.cpio"
EOF
chmod +x /etc/initramfs-tools/hooks/acpi-ivrs-override
# rebuild ONLY the current kernel's initrd first; older kernels stay untouched as a fallback
update-initramfs -u -k $(uname -r)
lsinitramfs /boot/initrd.img-$(uname -r) | grep ivrs # kernel/firmware/acpi/ivrs.aml
3. (Optional) Test boot with automatic rollback (GRUB)
The MS-A2 has no remote console, so I wanted a boot that rolls itself back if it hangs. Note: on GRUB,
proxmox-boot-tool kernel pin <ver> --next-boot is NOT a real one-shot. It writes a fixed "set default=" into the ESP grub.cfg and only proxmox-boot-cleanup.service clears it, after a successful boot, so a hang would boot the same kernel again. GRUB's own next_entry is a real one-shot (GRUB clears it before it boots):
Code:
proxmox-boot-tool kernel pin <older-known-good-kernel> # persistent default = old initrd, no override
proxmox-boot-tool refresh
E="gnulinux-advanced-<id>>gnulinux-<new-kernel>-advanced-<id>" # IDs: grep menuentry_id_option /boot/grub/grub.cfg
for u in $(cat /etc/kernel/proxmox-boot-uuids); do
m=$(mktemp -d); mount /dev/disk/by-uuid/$u $m
grub-editenv $m/grub/grubenv set next_entry="$E"
umount $m; rmdir $m
done
reboot
# hang -> power cycle -> boots the pinned old kernel without the override
# OK -> proxmox-boot-tool kernel unpin && proxmox-boot-tool refresh
# (and grub-editenv <esp>/grub/grubenv unset next_entry on the ESP that didn't boot)
4. Verify
Code:
# dmesg | grep -i "table upgrade\|ACPI: IVRS"
ACPI: IVRS ACPI table found in initrd [kernel/firmware/acpi/ivrs.aml][0xc8]
ACPI: Table Upgrade: override [IVRS- AMD -AmdTable]
ACPI: IVRS 0x00000000B9ED6000 0000C8 (v02 AMD AmdTable 00000002 INTL 20250404)
# cat /sys/kernel/iommu_groups/*/reserved_regions | grep -c direct
0
No AMD-Vi errors or IO_PAGE_FAULTs, and the VM with both E810 VFs started on boot again. Once it works, rebuild the other kernels too with
update-initramfs -u -k all if you want them as fallbacks with passthrough working.
Undo / when a fixed BIOS ships
Code:
rm /etc/initramfs-tools/hooks/acpi-ivrs-override /etc/initramfs-tools/acpi/ivrs.aml
update-initramfs -u -k all
reboot
Do this before or right after flashing a new BIOS. Otherwise the old patched copy of the 1.03 table keeps replacing whatever the new BIOS provides. If a future BIOS is still broken, rebuild the .aml from
that BIOS's table; don't reuse the 1.03 one.
Caveats
- The firmware presumably wanted those three 4K pages excluded for some reason (they sit in or near BIOS-reserved memory). Ignoring them has been fine for me and others so far, and 1.02 didn't have them, but Minisforum hasn't said what they're for.
- A malformed override table is simply ignored by the kernel (you just get the 1:1 error again), so the risk to booting is low. Still keep a fallback kernel, as above.
- Unrelated gotcha: after flashing, the BIOS turned the WiFi card back on, which shifted my E810 from bus 07 to 08 and broke the hostpci/VF addresses. Re-check your PCIe devices after any BIOS flash.
Hopefully Minisforum fixes the IVMD entries in 1.04. Until then this lets you stay on 1.03 without the risky downgrade.