MS-A2 Minisforum (AMD Ryzen™ 9 9955HX + Radeon™ 610M) – The “I Finally Stopped Crying” Zero-Artifact iGPU Passthrough Thread

futiless

Renowned Member
From absolute hell to running weeks straight with zero green frames, zero Code 43, zero black screens – December 2025


After months of investing essentially all my free time to working the bugs out and getting proper passthrough working to the point I am mostly satisfied for the application. Along the way I was giving a great deal of help from Uzumo. As he commented and built upon here: https://github.com/isc30/ryzen-gpu-passthrough-proxmox/blob/main/README.md, concepts that go on to be expanded into the hookscript method as outlined in Uzumo's dialog here https://github.com/isc30/ryzen-gpu-passthrough-proxmox/issues/131#issue-3266798285.


Now I have been scolded for seeking help regarding roms here on Proxmox but Uzumo was happy to provide the link https://github.com/isc30/ryzen-gpu-passthrough-proxmox. That gave me a great starting point. My novice eyes overlooked the https://github.com/isc30/ryzen-gpu-passthrough-proxmox/tree/main/Tools section. Here you can find what we need to get iGPU roms extracted. I did however end up reaching out to Minisforum and they passed along the shall we call it official vbios. The GopDriver and vbios is critical for this method. Getting the right one is tricky and not designed for the end user obviously. I would like to see companies which boast support for Proxmox get this process along to the consumer in a less convoluted fashion as clearly this is what we are trying to accomplish. Though I digress, I love my finished product.


Presently I am really only using a few vm's:


  • PFSense Community Edition which receives passthrough from the two X710 Intel slots and a back plain bridge to the vm's. This vm automatically boots and acts as a great home lab router/ server.
  • I have installed a Mellanox ConnectX 4 I got for $50 USD on ebay and another for my PC.

It's been a couple months since I started out https://forum.proxmox.com/threads/p...passthrough-a-desperate-plea-for-help.172139/. Since then I have made quite a few changes on the original each one coming with a story I wont bore you with unless you ask.


Instead I was hoping to collect a few other folks who have the same configuration as me that could help me inhance. Heck even just reconsider aspects of it I really don't care but initally I just wanted to help others who have been reaching out inquiring what I am working with.


Granted this is a significantly different setup on the MS-A2 lowered power delidded processor which minisforum wants locked to 45watts if you read the guides on the support section for our product. It becomes evidently clear people with this setup have issues with heat. I did find ways to modify and mitgate with bios settings, custimzed fan stages with aggressive speeds after 65. Also I cleared the original phasechange compound and upgraded to the best rated phase change pad I could find. If you are interested I will find the details. I have an after market fan directed to it at low speed in the "homelab server room". I am now able to have default or higher power settings in the bios and not ever see temperatures exceed 60. Which you need to install Cockpit for Proxmox to give you a Debian alternative frontend to help in various ways and for us its all about the temperature.


I don't want to get to far off topic here as I do want to provide a guide for this hardware but you have to check out https://github.com/filebrowser/filebrowser! This makes the editiing of our server files much easier than any other way I can image. I even allows you to make bookmarks as URL directly to a file. Which in turn brings up an editor! This is a priceless edition to debugging a wildly artifacting system that needs to be restarted hundreds and hunreds of times testing different settings. I also found a cgit project which literally runs automated backups every so many minutes on the tree structure for changes and you as the administrator can review and map out chronologically over time on a sort of giant map. Look I know how pathetic it is telling this to a community like this. But I intend my reader of this post to be almost as novice as me. Hence this is priceless knowledge as having quick access to the files is necessary.


Anyways enough about those seemingly abstract topics here is what I am using at the moment and Yes it is now zero artifacts for weeks. The real problem comes in when you 1) want to tweak to utilize power settings, as this setup essentially turns them off but if you essentially piss around enough you in theory could get them working too. Hence why I am making this thread to see if other wanted to dialouge about these igpu's and passthrough techniques. Not as though that hasn't been done before.. Its just that I have yet to see it done "right" per say, Myself included.


But heres the kicker I have got this setup to work flawlessly with stresstests of display @ 4k60p ; 4 x 4 ; downscaled in a grid 8k Japan video at 60p. For our system this is a great litmus test. If it is not setup correctly with the settings which essentially worked for others in the Ryzan lineup because in our case we need more tweaking for the buggs to be gone. I have a lot of bandwidth so this was fine for me. Essentially this would NOT work with the original setup with the hookscript and all. But now I can leave the system running for days on weeks. No flaws no jarred blackscreens, display driver crashes, green screens and on and on. All of which corrupt the working environment.


If you are admittedly a novice with OS's and you cant tell the nuance's here the signs are nerve racking and alarming to the point most would quit. However if you consider the way the frame buffer is a total mess when we have problems its wise to have a bootable wintousb. I found an incredible one so that we can boot our server test the hardware and get peace of mind back in order if your server is a mess with graphic artifacts or you need direct access for firmware updates like nvme drives for example. I cant STRESS ENOUGH the importance of never assuming that early artifacts will stay forever. (many times it was actually fixed with the configuration I had. But the drivers and system files had taken a serious beating from the previous attempt. Thus noticing the little signs such as if the screen blanks out even once. 2) The issues are all mendable with a safemode boot and driver wiping tools followed by a fresh installaion of the drivers.


Remaining bugs I haven’t touched because I’m exhausted and it’s Christmas season​


  1. power savings ASPM as I have them all disabled.
  2. After shutdown, switching to Ubuntu and then back to windows is not as clean as a fresh boot. I can't say there are artifacts anymore! So that is a major plus! I am passing though my aftermarket wifi 7 mediatek bluetooth and wifi. Then the same over in Ubuntu. but as you can see in the screenshot – lingering disabled devices that need to be re-enabled each boot. A pain but not the end of the line. Just something to consider and maybe help me overcome. That and the number power settings I had the disfortune of having to ultimately disable. Although I had it working for days like this it was ultimately just not reliable.

The exact files & VBIOS situation – EVERY detail because people keep asking​


Get our Gop Driver I posted here – save yourself the hassle of getting it if you are on 9955HX (others work but this is the type of thing were there is likely a better cleaner extract going around, also the bios version it was pulled from matters). So for us with artifacts and video issues it would be key to have the best foundation. Hence try mine sourced with https://github.com/LongSoft/UEFITool/releases/tag/A72 and posted here https://github.com/qemus/virtiso/releases.


You may notice my vbios has a different label in the following write up but that is because in the last month I heard back from Minisforum with what they said is a better one ?.. It is much larger in size like 128 kb. Whereas the majority of the vios post from the Ryzan like 80 percent had the same size like 43 kb or something .. Now I had 3 128 kb from the manufacturer, 1 I collected from tool which I shared and called it something that didnt fit into the rest nicely FOR THIS EXACT reason. I am not sure if it is correct. Now I am happy with the one I have but this is definitely worth consider.


If you have this exact MS-A2 (Ryzen 9 9955HX + Radeon 610M) and want to team up, share your hookscripts, fight over which 128 KB VBIOS is actually the golden one, get ASPM working reliably, fix the lingering Mediatek BT lingering crap, whatever – reply here.I’m done suffering alone. Let’s make this thing perfect together.




1764927328826.png:

There is lingering disabled devices that need to be re-enabled each boot. A pain but not the end of the line. Just something to consider and maybe help me overcome. That and the number power settings I had the disfortune of having to ultimately disable. Although I had it working for days like this it was ultimately just not reliable.

CONTINUED ON THE NEXT POST L
 
  • Like
Reactions: cedws
Windows conf

Code:
##args for args -cpu kvm=off,hv_vendor_id=proxmox'
##OCT22args -cpu 'host,hv_passthrough,level=35,-hypervisor,+svm,'
##args -device virtio-iommu-pci,bus=pcie.0,addr=1e.0,ats=on,caching-mode=on, -cpu 'host,hv_passthrough,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time,-hypervisor,+svm,+invtsc'
##args -device virtio-iommu-pci,bus=pcie.0,addr=1e.0,ats=on,caching-mode=on,aw-bits=48 -global virtio-iommu-pci.ats=on -global virtio-iommu-pci.caching-mode=on -global virtio-iommu-pci.aw-bits=48 -cpu 'host,hv_passthrough,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time,-hypervisor,+svm,+invtsc'
##args -cpu host,hv_passthrough,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time,-hypervisor,+svm,+invtsc -device virtio-iommu-pci,bus=pcie.0,addr=1e.0
#args -cpu 'kvm64,hv_passthrough,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time,-hypervisor,+svm,+invtsc'
#THESe are args from nov 07 artifacting args%3A -cpu 'host,hv_passthrough,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time,level=5,-hypervisor,+svm,+invtsc'
#THIS IS UZOMO proofed version args -cpu 'host,hv_passthrough,-hypervisor,level=35,+svm'
#args -cpu 'host,hv_passthrough,-hypervisor,level=35,+svm,'
#args BEST KNOWN NOT SO FOR VFIO LESS SYSTEM? -cpu 'host,hv_passthrough,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time,-hypervisor,+svm,+invtsc'
agent: 1
args: -cpu 'host,hv_passthrough,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time,-hypervisor,+svm,+invtsc,+kvm_pv_unhalt'
balloon: 0
bios: ovmf
boot: order=scsi0
cores: 16
cpu: host,flags=+nested-virt;+md-clear;-pcid;-spec-ctrl;-ssbd;+ibpb;+virt-ssbd;+amd-ssbd;+amd-no-ssb;+pdpe1gb;+hv-tlbflush;-hv-evmcs;+aes
efidisk0: local-zfs:vm-211-disk-0,efitype=4m,size=1M
hookscript: local:snippets/ryzen_igpu_reset.sh
hostpci0: 0000:01:00.0,pcie=1,romfile=9955HX.bin,x-vga=1
hostpci1: 0000:01:00.1,pcie=1,romfile=AMDGopDriver_164E_graniteridge_9955hx.rom
hostpci2: 0000:07:00.0,pcie=1
hugepages: 1024
ide0: local:iso/virtio-win-0.1.285.iso,media=cdrom,size=771138K
machine: pc-q35-10.1,viommu=virtio
memory: 32768
meta: creation-qemu=10.0.2,ctime=1760472552
name: Win11Corp25h2Nov13
net0: virtio=BC:24:11:8D:AF:BB,bridge=vmbr0,firewall=1,mtu=9000,queues=16
numa: 1
ostype: win11
scsi0: local-zfs:vm-211-disk-1,aio=io_uring,cache=writeback,discard=on,size=256G,ssd=1
scsi1: local-zfs:vm-211-disk-2,discard=on,size=432G,ssd=1
scsihw: virtio-scsi-pci
smbios1: uuid=eed56bbb-f7f4-496d-baf6-d7aa232af170
sockets: 1
tags: ssssss;win11
tpmstate0: local-zfs:vm-211-disk-3,size=4M,version=v2.0
usb0: host=1-2
usb1: host=5-1
usb2: host=2-1
usb3: host=3-2.4.4
usb4: host=4-2.1
vcpus: 16
vga: none
vmgenid: 3c2bc4a1-e8e1-4701-a1f1-c0660fa1277d

Ubuntu conf in QEMU-server folder under pve

Code:
# GPU Passthrough
#hostpci0%3A 0000%3A01%3A00.0,pcie=1,romfile=AMDGopDriver_9800x3d.rom,x-vga=1
#hostpci0%3A 0000%3A01%3A00.0,pcie=1,x-vga=1
##hostpci0%3A 0000 01 00 0,pcie=1,romfile=9955HX.bin,x-vga=1
#hostpci1%3A 0000%3A01%3A00.1,pcie=1
acpi: 1
agent: 1,fstrim_cloned_disks=1,type=virtio
args: -cpu 'host,kvm=off,hv_vendor_id=proxmox,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time'
balloon: 0
bios: ovmf
boot: order=virtio0
cores: 16
cpu: host,flags=+nested-virt;+md-clear;-pcid;-spec-ctrl;-ssbd;+ibpb;+virt-ssbd;+amd-ssbd;+amd-no-ssb;+pdpe1gb;+hv-tlbflush;-hv-evmcs;+aes
cpuunits: 2048
efidisk0: local-zfs:vm-333-disk-0,efitype=4m,pre-enrolled-keys=1,size=1M
hookscript: local:snippets/ryzen_igpu_reset.sh
hostpci0: 0000:01:00.0,pcie=1,romfile=vbios_SeanPull_164E_graniteridge_9955hx.bin,x-vga=1
hostpci1: 0000:01:00.1,pcie=1,romfile=AMDGopDriver_164E_graniteridge_9955hx.rom
machine: q35
memory: 32768
meta: creation-qemu=10.0.2,ctime=1758159885
name: Ubuntu2504
net0: virtio=BC:24:11:32:C8:DF,bridge=vmbr0,firewall=1,queues=12
numa: 1
ostype: l26
scsihw: virtio-scsi-pci
smbios1: uuid=415ad881-96c6-4ddd-9c4c-3e400745297e
sockets: 1
spice_enhancements: foldersharing=1,videostreaming=all
tags: ubuntu
tpmstate0: local-zfs:vm-333-disk-1,size=4M,version=v2.0
usb0: host=3-2.4.4
usb1: host=1-2
vcpus: 12
vga: none
virtio0: local-zfs:vm-333-disk-2,aio=io_uring,cache=unsafe,discard=on,iothread=1,size=600G
vmgenid: 34005779-aca5-4a5f-b7d5-c998f525cef1

ryzen_igpu_reset.sh
Code:
#!/bin/bash
phase="$2"
VMID="$1"

log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - VM $VMID: $*" >> /var/log/pve/tasks/hookscript.log
}

if [ "$phase" = "pre-start" ]; then
    log "Unbinding GPU + Audio + Bluetooth"
    echo "0000:01:00.0" > /sys/bus/pci/drivers/amdgpu/unbind 2>/dev/null || true
    echo "0000:01:00.1" > /sys/bus/pci/drivers/snd_hda_intel/unbind 2>/dev/null || true
    echo "0000:07:00.0" > /sys/bus/pci/drivers/iwlwifi/unbind 2>/dev/null || true   # change iwlwifi if needed
    sleep 5
fi

if [ "$phase" = "post-stop" ]; then
    log "Rebinding GPU + Audio + Bluetooth"
    sleep 5
    echo "0000:01:00.0" > /sys/bus/pci/drivers/vfio-pci/unbind 2>/dev/null || true
    echo "0000:01:00.1" > /sys/bus/pci/drivers/vfio-pci/unbind 2>/dev/null || true
    echo "0000:07:00.0" > /sys/bus/pci/drivers/vfio-pci/unbind 2>/dev/null || true
    sleep 2
    echo "1" > /sys/bus/pci/devices/0000:01:00.0/reset 2>/dev/null || true
    sleep 3
    echo "0000:01:00.0" > /sys/bus/pci/drivers/amdgpu/bind 2>/dev/null && log "GPU rebound" || log "GPU bind failed"
    echo "0000:01:00.1" > /sys/bus/pci/drivers/snd_hda_intel/bind 2>/dev/null && log "Audio rebound" || log "Audio bind failed"
    echo "0000:07:00.0" > /sys/bus/pci/drivers/iwlwifi/bind 2>/dev/null && log "Bluetooth/WiFi rebound" || log "Bluetooth bind failed"
    sleep 2
    chvt 1 2>/dev/null; chvt 7 2>/dev/null
fi

etc/modprobe.d/vfio.conf

Code:
#options vfio-pci ids=1002:13c0,1002:1640 !!Artifacts  ASPM Project
options vfio-pci ids=1002:13c0,1002:1640 disable_vga=1
softdep amdgpu pre: vfio-pci
softdep snd_hda_intel pre: vfio-pci

etc/modprobe.d/zfs.conf might not work I have 3 x nvme an 96 gigs of RAM

Code:
options zfs zfs_arc_max=51539607552

/etc/default/grub *IMPORTANT: consider the 3 hugepages entries as they pertain to 96gigs of memory and moving larger blocks instand of many tiny. Read about this you may need to turn this down and adjust your vm's .conf.

Code:
# If you change this file or any /etc/default/grub.d/*.cfg file,
# run 'update-grub' afterwards to update /boot/grub/grub.cfg.
# For full documentation of the options in these files, see:
#   info -f grub -n 'Simple configuration'

GRUB_DEFAULT="0"
GRUB_TIMEOUT=2
GRUB_DISTRIBUTOR=`( . /etc/os-release && echo ${NAME} )`
#GRUB_CMDLINE_LINUX_DEFAULT="quiet splash amd_iommu=on iommu=pt default_hugepagesz=1G hugepagesz=1G hugepages=48"
GRUB_CMDLINE_LINUX_DEFAULT="quiet iommu=pt amd_iommu=on default_hugepagesz=1G hugepagesz=1G hugepages=32"
GRUB_CMDLINE_LINUX=""

# If your computer has multiple operating systems installed, then you
# probably want to run os-prober. However, if your computer is a host
# for guest OSes installed via LVM or raw disk devices, running
# os-prober can cause damage to those guest OSes as it mounts
# filesystems to look for things.
#GRUB_DISABLE_OS_PROBER=false

# Uncomment to enable BadRAM filtering, modify to suit your needs
# This works with Linux (no patch required) and with any kernel that obtains
# the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...)
#GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef"

# Uncomment to disable graphical terminal
#GRUB_TERMINAL=console

# The resolution used on graphical terminal
# note that you can use only modes which your graphic card supports via VBE/GOP/UGA
# you can see them in real GRUB with the command `videoinfo'
#GRUB_GFXMODE=640x480

# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
#GRUB_DISABLE_LINUX_UUID=true

# Uncomment to disable generation of recovery mode menu entries
#GRUB_DISABLE_RECOVERY="true"

# Uncomment to get a beep at grub start
#GRUB_INIT_TUNE="480 440 1"

etc/kernel/cmdline

Code:
root=ZFS=rpool/ROOT/pve-1 boot=zfs quiet iommu=pt amd_iommu=on pcie_aspm=off
# removing pcie_aspm=off ubuntu wont boot

THE FOLLOWING 2 ARE ON THE WINDOWS HOST COMPUTER HOOKSCRIPT read about setting up the hookscript method in windows and eliminating your first error 43 and getting the display set to none in the Uzumo guides/my privous posts, etc..

1) file:///C:/Windows/System32/GroupPolicy/Machine/Scripts/Startup/RadeonStartupFix.bat

Code:
@echo off
setlocal enabledelayedexpansion

set LOGFILE=C:\Scripts\enable.log
echo [%date% %time%] Starting enable script >> %LOGFILE%

echo Enabling Display devices...
for /f "tokens=*" %%a in ('pnputil /enum-devices /class Display ^| findstr /c:"Instance ID"') do (
    set "id=%%a"
    set "id=!id:Instance ID: =!"
    set "id=!id: =!"
    if not "!id!"=="" (
        pnputil /enable-device "!id!" >nul 2>&1
        if errorlevel 0 (
            echo [%date% %time%] Enabled: !id! >> %LOGFILE%
        ) else (
            echo [%date% %time%] Failed to enable: !id! (errorlevel: %errorlevel%) >> %LOGFILE%
        )
    )
)

echo Enabling MEDIA devices...
for /f "tokens=*" %%a in ('pnputil /enum-devices /class MEDIA ^| findstr /c:"Instance ID"') do (
    set "id=%%a"
    set "id=!id:Instance ID: =!"
    set "id=!id: =!"
    if not "!id!"=="" (
        pnputil /enable-device "!id!" >nul 2>&1
        if errorlevel 0 (
            echo [%date% %time%] Enabled: !id! >> %LOGFILE%
        ) else (
            echo [%date% %time%] Failed to enable: !id! (errorlevel: %errorlevel%) >> %LOGFILE%
        )
    )
)

echo Enabling Bluetooth devices...
for /f "tokens=*" %%a in ('pnputil /enum-devices /class Bluetooth ^| findstr /c:"Instance ID"') do (
    set "id=%%a"
    set "id=!id:Instance ID: =!"
    set "id=!id: =!"
    if not "!id!"=="" (
        pnputil /enable-device "!id!" >nul 2>&1
        if errorlevel 0 (
            echo [%date% %time%] Enabled: !id! >> %LOGFILE%
        ) else (
            echo [%date% %time%] Failed to enable: !id! (errorlevel: %errorlevel%) >> %LOGFILE%
        )
    )
)

echo [%date% %time%] Enable script complete >> %LOGFILE%
endlocal

file:///C:/Windows/System32/GroupPolicy/Machine/Scripts/Shutdown/RadeonShutdownFix.bat

Code:
@echo off
setlocal enabledelayedexpansion

set LOGFILE=C:\Scripts\disable.log
echo [%date% %time%] Starting disable script >> %LOGFILE%

echo Disabling Display devices...
for /f "tokens=*" %%a in ('pnputil /enum-devices /class Display ^| findstr /c:"Instance ID"') do (
    set "id=%%a"
    set "id=!id:Instance ID: =!"
    set "id=!id: =!"
    if not "!id!"=="" (
        pnputil /disable-device "!id!" >nul 2>&1
        if errorlevel 0 (
            echo [%date% %time%] Disabled: !id! >> %LOGFILE%
        ) else (
            echo [%date% %time%] Failed to disable: !id! (errorlevel: %errorlevel%) >> %LOGFILE%
        )
    )
)

echo Disabling MEDIA devices...
for /f "tokens=*" %%a in ('pnputil /enum-devices /class MEDIA ^| findstr /c:"Instance ID"') do (
    set "id=%%a"
    set "id=!id:Instance ID: =!"
    set "id=!id: =!"
    if not "!id!"=="" (
        pnputil /disable-device "!id!" >nul 2>&1
        if errorlevel 0 (
            echo [%date% %time%] Disabled: !id! >> %LOGFILE%
        ) else (
            echo [%date% %time%] Failed to disable: !id! (errorlevel: %errorlevel%) >> %LOGFILE%
        )
    )
)

echo Disabling Bluetooth devices...
for /f "tokens=*" %%a in ('pnputil /enum-devices /class Bluetooth ^| findstr /c:"Instance ID"') do (
    set "id=%%a"
    set "id=!id:Instance ID: =!"
    set "id=!id: =!"
    if not "!id!"=="" (
        pnputil /disable-device "!id!" >nul 2>&1
        if errorlevel 0 (
            echo [%date% %time%] Disabled: !id! >> %LOGFILE%
        ) else (
            echo [%date% %time%] Failed to disable: !id! (errorlevel: %errorlevel%) >> %LOGFILE%
        )
    )
)

echo [%date% %time%] Disable script complete >> %LOGFILE%
endlocal

That’s literally everything I’m running right now Feel free to steal, improve, or roast – just don’t send me back to the green-screen dimension

PS : Merry Christmas ; if you need this and I helped like this post and commit to at least a reply or two regarding what you use and what might help. Thank you No comment is stupid everything is welcome.

PPS: IF YOU WANT the VBIOS from Minisforum I cant post it here so you will have to contact me. :) Cheers
 
  • Like
Reactions: cedws and uzumo