1#!/usr/bin/env bash 2 3set -e 4 5rootdir=$(readlink -f $(dirname $0))/.. 6 7function linux_iter_pci { 8 # Argument is the class code 9 # TODO: More specifically match against only class codes in the grep 10 # step. 11 lspci -mm -n | grep $1 | tr -d '"' | awk -F " " '{print "0000:"$1}' 12} 13 14function linux_bind_driver() { 15 bdf="$1" 16 driver_name="$2" 17 old_driver_name="no driver" 18 ven_dev_id=$(lspci -n -s $bdf | cut -d' ' -f3 | sed 's/:/ /') 19 20 if [ -e "/sys/bus/pci/devices/$bdf/driver" ]; then 21 old_driver_name=$(basename $(readlink /sys/bus/pci/devices/$bdf/driver)) 22 23 if [ "$driver_name" = "$old_driver_name" ]; then 24 return 0 25 fi 26 27 echo "$ven_dev_id" > "/sys/bus/pci/devices/$bdf/driver/remove_id" 2> /dev/null || true 28 echo "$bdf" > "/sys/bus/pci/devices/$bdf/driver/unbind" 29 fi 30 31 echo "$bdf ($ven_dev_id): $old_driver_name -> $driver_name" 32 33 echo "$ven_dev_id" > "/sys/bus/pci/drivers/$driver_name/new_id" 2> /dev/null || true 34 echo "$bdf" > "/sys/bus/pci/drivers/$driver_name/bind" 2> /dev/null || true 35 36 iommu_group=$(basename $(readlink -f /sys/bus/pci/devices/$bdf/iommu_group)) 37 if [ -e "/dev/vfio/$iommu_group" ]; then 38 chown "$username" "/dev/vfio/$iommu_group" 39 fi 40} 41 42function configure_linux { 43 driver_name=vfio-pci 44 if [ -z "$(ls /sys/kernel/iommu_groups)" ]; then 45 # No IOMMU. Use uio. 46 driver_name=uio_pci_generic 47 fi 48 49 # NVMe 50 modprobe $driver_name || true 51 for bdf in $(linux_iter_pci 0108); do 52 linux_bind_driver "$bdf" "$driver_name" 53 done 54 55 56 # IOAT 57 TMP=`mktemp` 58 #collect all the device_id info of ioat devices. 59 grep "PCI_DEVICE_ID_INTEL_IOAT" $rootdir/lib/ioat/ioat_pci.h \ 60 | awk -F"x" '{print $2}' > $TMP 61 62 for dev_id in `cat $TMP`; do 63 # Abuse linux_iter_pci by giving it a device ID instead of a class code 64 for bdf in $(linux_iter_pci $dev_id); do 65 linux_bind_driver "$bdf" "$driver_name" 66 done 67 done 68 rm $TMP 69 70 echo "1" > "/sys/bus/pci/rescan" 71 72 if ! mount | grep -q hugetlbs; then 73 mkdir -p /mnt/huge 74 mount -t hugetlbfs nodev /mnt/huge 75 fi 76 echo "$NRHUGE" > /proc/sys/vm/nr_hugepages 77 78 if [ "$driver_name" = "vfio-pci" ]; then 79 chown "$username" /dev/hugepages 80 81 MEMLOCK_AMNT=`ulimit -l` 82 if [ "$MEMLOCK_AMNT" != "unlimited" ] ; then 83 MEMLOCK_MB=`expr $MEMLOCK_AMNT / 1024` 84 echo "" 85 echo "Current user memlock limit: ${MEMLOCK_MB} MB" 86 echo "" 87 echo "This is the maximum amount of memory you will be" 88 echo "able to use with DPDK and VFIO if run as current user." 89 echo -n "To change this, please adjust limits.conf memlock " 90 echo "limit for current user." 91 92 if [ $MEMLOCK_AMNT -lt 65536 ] ; then 93 echo "" 94 echo "## WARNING: memlock limit is less than 64MB" 95 echo -n "## DPDK with VFIO may not be able to initialize " 96 echo "if run as current user." 97 fi 98 fi 99 fi 100} 101 102function reset_linux { 103 # NVMe 104 modprobe nvme || true 105 for bdf in $(linux_iter_pci 0108); do 106 linux_bind_driver "$bdf" nvme 107 done 108 109 110 # IOAT 111 TMP=`mktemp` 112 #collect all the device_id info of ioat devices. 113 grep "PCI_DEVICE_ID_INTEL_IOAT" $rootdir/lib/ioat/ioat_pci.h \ 114 | awk -F"x" '{print $2}' > $TMP 115 116 modprobe ioatdma || true 117 for dev_id in `cat $TMP`; do 118 # Abuse linux_iter_pci by giving it a device ID instead of a class code 119 for bdf in $(linux_iter_pci $dev_id); do 120 linux_bind_driver "$bdf" ioatdma 121 done 122 done 123 rm $TMP 124 125 echo "1" > "/sys/bus/pci/rescan" 126} 127 128function configure_freebsd { 129 TMP=`mktemp` 130 AWK_PROG="{if (count > 0) printf \",\"; printf \"%s:%s:%s\",\$2,\$3,\$4; count++}" 131 echo $AWK_PROG > $TMP 132 PCICONF=`pciconf -l | grep 'class=0x010802\|^ioat'` 133 BDFS=`echo $PCICONF | awk -F: -f $TMP` 134 kldunload nic_uio.ko || true 135 kenv hw.nic_uio.bdfs=$BDFS 136 kldload nic_uio.ko 137 rm $TMP 138 139 kldunload contigmem.ko || true 140 kenv hw.contigmem.num_buffers=$((NRHUGE * 2 / 32)) 141 kenv hw.contigmem.buffer_size=$((32 * 1024 * 1024)) 142 kldload contigmem.ko 143} 144 145function reset_freebsd { 146 kldunload contigmem.ko || true 147 kldunload nic_uio.ko || true 148} 149 150NRHUGE=1024 151 152username=$1 153mode=$2 154 155if [ "$username" = "reset" -o "$username" = "config" ]; then 156 mode="$username" 157 username="" 158fi 159 160if [ "$mode" == "" ]; then 161 mode="config" 162fi 163 164if [ "$username" = "" ]; then 165 username=`logname` 166fi 167 168if [ `uname` = Linux ]; then 169 if [ "$mode" == "config" ]; then 170 configure_linux 171 elif [ "$mode" == "reset" ]; then 172 reset_linux 173 fi 174else 175 if [ "$mode" == "config" ]; then 176 configure_freebsd 177 elif [ "$mode" == "reset" ]; then 178 reset_freebsd 179 fi 180fi 181