PCIe pass through for Wifi Dev

For the last little while I have been working on porting a WiFi driver. I initially planned to use one of my testbed machines, but the card I had wasn't supported by the original driver and locked up the system.

While waiting for another card I spun up development on the Morefine M6 which had failed complete at its proposed role as a desktop mirrored storage array.

The Morefine M6 has an Intel N200 SoC and supported Intel wifi.

I always set out to try PCIe pass through and the FreeBSD wiki page provided most of what I needed .

On the host you need to exclude the PCIe devices you wish to give to a guest. You need to find the PCIe address for the device to exclude, pciconf -lv is good for this:

# pciconf -lv 
...
none2@pci0:0:20:2:      class=0x050000 rev=0x00 hdr=0x00 vendor=0x8086 device=0x54ef subvendor=0x8086 subdevice=0x7270
    vendor     = 'Intel Corporation'                        
    device     = 'Alder Lake-N PCH Shared SRAM'                 
    class      = memory                                         
    subclass   = RAM                                            
ppt0@pci0:0:20:3:       class=0x028000 rev=0x00 hdr=0x00 vendor=0x8086 device=0x54f0 subvendor=0x8086 subdevice=0x0070
    vendor     = 'Intel Corporation'
    device     = 'CNVi: Wi-Fi'                                  
    class      = network                                        
ig4iic0@pci0:0:21:0:    class=0x0c8000 rev=0x00 hdr=0x00 vendor=0x8086 device=0x54e8 subvendor=0x8086 subdevice=0x7270
    vendor     = 'Intel Corporation'
    class      = serial bus                                     
ig4iic1@pci0:0:21:1:    class=0x0c8000 rev=0x00 hdr=0x00 vendor=0x8086 device=0x54e9 subvendor=0x8086 subdevice=0x7270
    vendor     = 'Intel Corporation'
    class      = serial bus 
...

I have passed PCIe device 0:20:3 to my guests, in the pciconf list you will see the driver assigned to the device followed by the bus and the address. So the ig4 i2c driver has devices ig4iic0@pci0:0:21:0 and ig4iic1@pci0:0:21:1 and the 'Wi-Fi' device has been taken by ppt0.

This is configured by adding the PCIe address to /boot/loader.conf :

pptdevs="0/20/3"                # intel wifi

We need to give our PCIe device to our VM, I am simple person and do all my bhyve through vmrun.sh and wrapper shell scripts. For FreeBSD the script is this:

#!/bin/sh                                                                   

diskimage="not set"                                                         
vmname="not set"                                                            
pcidev="0/20/3"                                                             

diskimage="/home/tj/vms/fbsd-iwx.raw"                                       
vmname=$(basename $diskimage .raw)                                          

if [ $# -ge 1 ]                                                             
then                                                                        
        for x in $@                                                         
        do                                                                  
                interfaces="$interfaces -t $x"                              
        done                                                                
else                                                                        
        echo 'usage: launchfreebsd.sh tapDev [tapDev tapDev ...]'           
        exit                                                                
fi                                                                          

echo starting vm $vmname from image $diskimage with interfaces ${interfaces}

sh /usr/share/examples/bhyve/vmrun.sh \                                     
        -c $(nproc) \                                                       
        -m 8G \                                                             
        -p ${pcidev} \                                                      
        ${interfaces} \                                                     
        -d $diskimage \                                                     
        $vmname

And for OpenBSD:

#!/bin/sh                                                                   

diskimage="not set"                                                         
vmname="not set"                                                            
pcidev="0/20/3"                                                             

diskimage="/home/tj/vms/obsd.raw"                                          
vmname=$(basename $diskimage .raw)                                          

#setup="true"                                                               

if [ $# -ge 1 ]                                                             
then                                                                        
        for x in $@                                                         
        do                                                                  
                interfaces="$interfaces -t $x"                              
        done                                                                
else                                                                        
        echo 'usage: $0 tapDev [tapDev tapDev ...]'                         
        exit                                                                
fi                                                                          

echo starting vm $vmname from image $diskimage with interfaces ${interfaces}

if [ -z $setup ]                                                            
then                                                                        
        bhyve -A -D -H -P -S -u -w -c 4 -m 8G                           \   
                -s 0,amd_hostbridge                                     \   
                -s 3,virtio-blk,${diskimage}                            \   
                -s 5,passthru,${pcidev}                                 \   
                -s 10,virtio-net,tap0                                   \   
                -s 20,virtio-rnd                                        \   
                -s 31,lpc -l com1,stdio                                 \   
                -l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd \   
                $vmname                                                     
else                                                                        

        vmname=openbsd-installer                                            
        echo "Trying to run installer, remember to configure serial"        
        echo "          set tty com0"                                       
        bhyve -A -D -H -P -S -u -w -c 4 -m 8G                           \   
                -s 0,amd_hostbridge                                     \   
                -s 3,virtio-blk,${diskimage}                            \   
                -s 4,ahci-hd,/home/tj/miniroot76.img                    \   
                -s 5,passthru,${pcidev}                                 \   
                -s 10,virtio-net,tap0                                   \   
                -s 20,virtio-rnd                                        \   
                -s 31,lpc -l com1,stdio                                 \   
                -l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd \   
                $vmname                                                     
fi                                                                          

bhyvectl --destroy --vm=$vmname

In the FreeBSD VM I want to override the default driver so I can test my port this is done by adding a block line to /etc/rc.conf :

devmatch_blocklist="if_iwlwifi"

My work on FreeBSD is supported by the FreeBSD Foundation , you can contribute to improving FreeBSD with code, documentation or financially by donating to the FreeBSD Foundation .