Raptor Lake iGPU SR-IOV

A madman embarks on a quest

The first line of this post was originally going to be “Last week I posted about getting my wacky new server working.”

It is no longer last week, but rather last year. Yes, I started writing this in June 2024 and it is now July 2025.

This server originally had two discrete GPUs for VMs to use, but I also wanted to leverage the i9’s iGPU to handle video transcoding for my media host.

Even before this post was delayed by a year, I had decided that this would not be a guide, but rather a rant.

Will this be easy?

My original goal was to just load a driver, create a VirGL device, and use it for stuff. It wasn’t that easy. During boot, I got this cool message:

[   21.856166] xe 0000:00:02.0: Your graphics device a780 is not officially supported
               by xe driver in this kernel version. To force Xe probe,
               use xe.force_probe='a780' and i915.force_probe='!a780'
               module parameters or CONFIG_DRM_XE_FORCE_PROBE='a780' and
               CONFIG_DRM_I915_FORCE_PROBE='!a780' configuration options.

Alright, sounds easy. Let’s just try this out: modprobe xe force_probe='a780'.

Nice, a device appears in /dev/dri. Time to attach a VirGL device to a VM and boot it up.

Spoiler alert: it didn’t work

The tl;dr is that this afforded me no VA-API capabilities. I did some googling, but have now lost the links I found. If I recall correctly, I think the conclusion was that the xe driver can’t do what I want when paravirtualized. I tried using i915 too, but it won’t even load – even with the force_probe stuff.

This iGPU supports SR-IOV: some magic to make it look like multiple GPUs so each can be passed through into its own VM. Perfect, then I don’t have to worry about this paravirtualization nonsense.

The kernel doesn’t support this by default, but there’s a DKMS module. Let’s go ahead and build it!

Compromises

When I first started trying to get SR-IOV working, I was upset that the aforementioned DKMS package didn’t support the 6.8 kernel. I followed instructions in the repo to pin to an earlier one. I figured I could live with 6.5. I rebooted the system and turned on SR-IOV in the bios.

I cloned the repo and followed the steps in the readme, adjusting for my kernel version.

root@kagrenac:~# cd i915-sriov-dkms
root@kagrenac:~/i915-sriov-dkms# uname -a
Linux kagrenac 6.5.13-5-pve #1 SMP PREEMPT_DYNAMIC PMX 6.5.13-5 (2024-04-05T11:03Z) x86_64 GNU/Linux
root@kagrenac:~/i915-sriov-dkms# vi dkms.conf # change the package name and version
root@kagrenac:~/i915-sriov-dkms# cd ..
root@kagrenac:~# mv i915-sriov-dkms /usr/src/i915-sriov-dkms-6.5.13-5-pve
root@kagrenac:~# apt install proxmox-headers-6.5.13-5-pve
...
root@kagrenac:~# dkms install -m i915-sriov-dkms -v 6.5.13-5-pve
Sign command: /lib/modules/6.5.13-5-pve/build/scripts/sign-file
Signing key: /var/lib/dkms/mok.key
Public certificate (MOK): /var/lib/dkms/mok.pub
Creating symlink /var/lib/dkms/i915-sriov-dkms/6.5.13-5-pve/source -> /usr/src/i915-sriov-dkms-6.5.13-5-pve

Building module:
Cleaning build area...
Building module(s)......(bad exit status: 2)
Failed command:
make -j32 KERNELRELEASE=6.5.13-5-pve -C /lib/modules/6.5.13-5-pve/build M=/var/lib/dkms/i915-sriov-dkms/6.5.13-5-pve/build KVER=6.5.13-5-pve
Error! Bad return status for module build on kernel: 6.5.13-5-pve (x86_64)
Consult /var/lib/dkms/i915-sriov-dkms/6.5.13-5-pve/build/make.log for more information

Uncharted territory

I checked out the log and found the error:

/var/lib/dkms/i915-sriov-dkms/6.5.13-5-pve/build/drivers/gpu/drm/i915/display/intel_dp_mst.c: In function ‘intel_dp_mst_find_vcpi_slots_for_bpp’:
/var/lib/dkms/i915-sriov-dkms/6.5.13-5-pve/build/drivers/gpu/drm/i915/display/intel_dp_mst.c:86:43: error: too many arguments to function ‘drm_dp_calc_pbn_mode’
   86 |                         crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
      |                                           ^~~~~~~~~~~~~~~~~~~~

I tried to brush off the “kernel module dev” hat that I hadn’t worn since probably 2015.

root@kagrenac:/usr/src/i915-sriov-dkms-6.5.13-5-pve# git grep drm_dp_calc_pbn_mode
drivers/gpu/drm/i915/display/intel_dp_mst.c:                    crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
drivers/gpu/drm/i915/display/intel_dp_mst.c:                            crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
drivers/gpu/drm/i915/display/intel_dp_mst.c:            drm_dp_calc_pbn_mode(mode->clock, min_bpp, false) > port->full_pbn) {
drivers/gpu/drm/i915/display/intel_dp_mst.c:            drm_dp_calc_pbn_mode(mode->clock, min_bpp) > port->full_pbn) {
root@kagrenac:/usr/src/i915-sriov-dkms-6.5.13-5-pve# grep -R drm_dp_calc_pbn_mode /usr/src/linux-headers-6.5.13-5-pve/
/usr/src/linux-headers-6.5.13-5-pve/Module.symvers:0xa47826e4   drm_dp_calc_pbn_mode    drivers/gpu/drm/display/drm_display_helper      EXPORT_SYMBOL
/usr/src/linux-headers-6.5.13-5-pve/include/drm/display/drm_dp_mst_helper.h:int drm_dp_calc_pbn_mode(int clock, int bpp);

It looks like there are a few uses of drm_dp_calc_pbn_mode. Some of them have this extra third argument which is apparently not real.

Let’s take a look at the file and see wh-

#if LINUX_VERSION_CODE < KERNEL_VERSION(6,6,14)
        crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
                                        dsc ? bpp << 4 : bpp,
                                        dsc);
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,6,14)
        crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
                                        dsc ? bpp << 4 : bpp);
#endif

Alright, so these guards are wrong. It might be a PVE thing where a patch was backported or something. I’ll just nuke the first chunk and unconditionally use the >= 6.6.14 stuff.

I got it to build now.

Prayer

I added i915.enable_guc=3 i915.max_vfs=7 to my kernel cmdline, called update-grub, rebuilt my initramfs, and rebooted with my fingers crossed.

It booted, but I realized I forgot to do the thing from the Readme to enable the VFs. Rebooted again.

The kernel module loaded, but no VFs were created. Manually writing to sriov_numvfs just fails.

Fortunately, somebody else also wrote some instructions on how to get this thing working.

There are only some slight modifications to the configuration and build process here. I was totally out of my depth but it seemed like this apt install sysfsutils step might also be important to get the VFs actually created on boot.

I rebuilt the module and did the initramfs thing again.

The kernel logs now presented this error:

[   17.593755] pci 0000:00:02.0: no driver bound to device; cannot configure SR-IOV

From lspci -k we can confirm that i915 is not in use on the device, though it did load.

If I rmmod and modprobe it again, nothing really happened except it logged the same stuff it did on boot:

[  187.619871] Setting dangerous option enable_guc - tainting kernel

However, it still wasn’t bound to the device. Trying force_probe again had no effect.

I found yet another post about setting it up, and still I could find nothing different.

Deep in the weeds

I did some more googling, and landed on something different. I unloaded the custom i915, uninstalled it from dkms, and tried building this Intel backport thing instead.

It failed with the same drm_dp_calc_pbn_mode stuff again, so I went back in and made basically those same changes as before. The module eventually built successfully, then…. it loaded but did not probe the device, same as before.

Some sources say kernel 6.11 might do the stuff I want it to do. I considered just waiting until it was released.

A year later, I tried again

At first, I had no idea why I had such a hard time with this, since it seems like success came easy for others with 13th gen chips.

One day, I had a spare couple of hours and decided to update my BIOS. I figured that maybe this would fix SR-IOV too. Support for 6.8 was available in the DKMS repo now, and I didn’t have to do anything weird to get it to build. It still didn’t work.

My motherboard manufacturer suggested to update the Intel ME along with the BIOS update. This was a nightmare, requiring me to build WinPE boot media in order to run the tool, since there was absolutely no Linux support. However, after doing so, suddenly SR-IOV was working.

Bask in the glory of my really funny looking fetch due to the quantity of VFs.

Why?

I have no idea what other firmware lives in the ME image but it seems like it was necessary to enable SR-IOV on my chip.

I had never considered updating ME before, and nobody on the Internet had advised that it might be necessary for this.

After this, I followed the other common guidance online to set everything else up and it just worked.

I guess the moral of this story is to always keep ME up to date? I hate it.