2016-02-19 21:11:08 +00:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
|
|
set -e
|
|
|
|
|
|
|
|
rootdir=$(readlink -f $(dirname $0))/..
|
|
|
|
|
|
|
|
function linux_iter_pci {
|
|
|
|
# Argument is the class code
|
|
|
|
# TODO: More specifically match against only class codes in the grep
|
|
|
|
# step.
|
2017-04-25 00:15:57 +00:00
|
|
|
lspci -mm -n -D | grep $1 | tr -d '"' | awk -F " " '{print $1}'
|
2016-02-19 21:11:08 +00:00
|
|
|
}
|
|
|
|
|
2016-04-14 19:21:32 +00:00
|
|
|
function linux_bind_driver() {
|
|
|
|
bdf="$1"
|
|
|
|
driver_name="$2"
|
|
|
|
old_driver_name="no driver"
|
|
|
|
ven_dev_id=$(lspci -n -s $bdf | cut -d' ' -f3 | sed 's/:/ /')
|
|
|
|
|
|
|
|
if [ -e "/sys/bus/pci/devices/$bdf/driver" ]; then
|
|
|
|
old_driver_name=$(basename $(readlink /sys/bus/pci/devices/$bdf/driver))
|
|
|
|
|
|
|
|
if [ "$driver_name" = "$old_driver_name" ]; then
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo "$ven_dev_id" > "/sys/bus/pci/devices/$bdf/driver/remove_id" 2> /dev/null || true
|
|
|
|
echo "$bdf" > "/sys/bus/pci/devices/$bdf/driver/unbind"
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo "$bdf ($ven_dev_id): $old_driver_name -> $driver_name"
|
|
|
|
|
|
|
|
echo "$ven_dev_id" > "/sys/bus/pci/drivers/$driver_name/new_id" 2> /dev/null || true
|
|
|
|
echo "$bdf" > "/sys/bus/pci/drivers/$driver_name/bind" 2> /dev/null || true
|
2016-04-06 03:03:28 +00:00
|
|
|
|
|
|
|
iommu_group=$(basename $(readlink -f /sys/bus/pci/devices/$bdf/iommu_group))
|
|
|
|
if [ -e "/dev/vfio/$iommu_group" ]; then
|
2016-11-29 21:26:42 +00:00
|
|
|
if [ "$username" != "" ]; then
|
|
|
|
chown "$username" "/dev/vfio/$iommu_group"
|
|
|
|
fi
|
2016-04-06 03:03:28 +00:00
|
|
|
fi
|
2016-04-14 19:21:32 +00:00
|
|
|
}
|
|
|
|
|
2017-03-28 17:09:31 +00:00
|
|
|
function linux_hugetlbfs_mount() {
|
|
|
|
mount | grep '^hugetlbfs ' | awk '{ print $3 }'
|
|
|
|
}
|
|
|
|
|
2016-02-19 21:11:08 +00:00
|
|
|
function configure_linux {
|
|
|
|
driver_name=vfio-pci
|
|
|
|
if [ -z "$(ls /sys/kernel/iommu_groups)" ]; then
|
|
|
|
# No IOMMU. Use uio.
|
|
|
|
driver_name=uio_pci_generic
|
|
|
|
fi
|
|
|
|
|
|
|
|
# NVMe
|
|
|
|
modprobe $driver_name || true
|
|
|
|
for bdf in $(linux_iter_pci 0108); do
|
2016-04-14 19:21:32 +00:00
|
|
|
linux_bind_driver "$bdf" "$driver_name"
|
2016-02-19 21:11:08 +00:00
|
|
|
done
|
|
|
|
|
|
|
|
|
|
|
|
# IOAT
|
|
|
|
TMP=`mktemp`
|
|
|
|
#collect all the device_id info of ioat devices.
|
2016-08-08 22:57:49 +00:00
|
|
|
grep "PCI_DEVICE_ID_INTEL_IOAT" $rootdir/include/spdk/pci_ids.h \
|
2016-02-19 21:11:08 +00:00
|
|
|
| awk -F"x" '{print $2}' > $TMP
|
|
|
|
|
|
|
|
for dev_id in `cat $TMP`; do
|
|
|
|
# Abuse linux_iter_pci by giving it a device ID instead of a class code
|
|
|
|
for bdf in $(linux_iter_pci $dev_id); do
|
2016-04-14 19:21:32 +00:00
|
|
|
linux_bind_driver "$bdf" "$driver_name"
|
2016-02-19 21:11:08 +00:00
|
|
|
done
|
|
|
|
done
|
|
|
|
rm $TMP
|
|
|
|
|
|
|
|
echo "1" > "/sys/bus/pci/rescan"
|
2016-04-14 20:22:11 +00:00
|
|
|
|
2017-03-28 17:09:31 +00:00
|
|
|
hugetlbfs_mount=$(linux_hugetlbfs_mount)
|
|
|
|
|
|
|
|
if [ -z "$hugetlbfs_mount" ]; then
|
|
|
|
hugetlbfs_mount=/mnt/huge
|
|
|
|
echo "Mounting hugetlbfs at $hugetlbfs_mount"
|
|
|
|
mkdir -p "$hugetlbfs_mount"
|
|
|
|
mount -t hugetlbfs nodev "$hugetlbfs_mount"
|
2016-04-14 20:22:11 +00:00
|
|
|
fi
|
|
|
|
echo "$NRHUGE" > /proc/sys/vm/nr_hugepages
|
2016-04-06 03:03:28 +00:00
|
|
|
|
|
|
|
if [ "$driver_name" = "vfio-pci" ]; then
|
2016-11-29 21:26:42 +00:00
|
|
|
if [ "$username" != "" ]; then
|
2017-03-28 17:09:31 +00:00
|
|
|
chown "$username" "$hugetlbfs_mount"
|
2016-11-29 21:26:42 +00:00
|
|
|
fi
|
2016-04-06 03:03:28 +00:00
|
|
|
|
|
|
|
MEMLOCK_AMNT=`ulimit -l`
|
|
|
|
if [ "$MEMLOCK_AMNT" != "unlimited" ] ; then
|
2016-11-08 14:21:15 +00:00
|
|
|
MEMLOCK_MB=$(( $MEMLOCK_AMNT / 1024 ))
|
2016-04-06 03:03:28 +00:00
|
|
|
echo ""
|
|
|
|
echo "Current user memlock limit: ${MEMLOCK_MB} MB"
|
|
|
|
echo ""
|
|
|
|
echo "This is the maximum amount of memory you will be"
|
|
|
|
echo "able to use with DPDK and VFIO if run as current user."
|
|
|
|
echo -n "To change this, please adjust limits.conf memlock "
|
|
|
|
echo "limit for current user."
|
|
|
|
|
|
|
|
if [ $MEMLOCK_AMNT -lt 65536 ] ; then
|
|
|
|
echo ""
|
|
|
|
echo "## WARNING: memlock limit is less than 64MB"
|
|
|
|
echo -n "## DPDK with VFIO may not be able to initialize "
|
|
|
|
echo "if run as current user."
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
fi
|
2016-02-19 21:11:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function reset_linux {
|
|
|
|
# NVMe
|
|
|
|
modprobe nvme || true
|
|
|
|
for bdf in $(linux_iter_pci 0108); do
|
2016-04-14 19:21:32 +00:00
|
|
|
linux_bind_driver "$bdf" nvme
|
2016-02-19 21:11:08 +00:00
|
|
|
done
|
|
|
|
|
|
|
|
|
|
|
|
# IOAT
|
|
|
|
TMP=`mktemp`
|
|
|
|
#collect all the device_id info of ioat devices.
|
2016-08-08 22:57:49 +00:00
|
|
|
grep "PCI_DEVICE_ID_INTEL_IOAT" $rootdir/include/spdk/pci_ids.h \
|
2016-02-19 21:11:08 +00:00
|
|
|
| awk -F"x" '{print $2}' > $TMP
|
|
|
|
|
|
|
|
modprobe ioatdma || true
|
|
|
|
for dev_id in `cat $TMP`; do
|
|
|
|
# Abuse linux_iter_pci by giving it a device ID instead of a class code
|
|
|
|
for bdf in $(linux_iter_pci $dev_id); do
|
2016-04-14 19:21:32 +00:00
|
|
|
linux_bind_driver "$bdf" ioatdma
|
2016-02-19 21:11:08 +00:00
|
|
|
done
|
|
|
|
done
|
|
|
|
rm $TMP
|
|
|
|
|
|
|
|
echo "1" > "/sys/bus/pci/rescan"
|
2017-03-28 17:11:35 +00:00
|
|
|
|
|
|
|
hugetlbfs_mount=$(linux_hugetlbfs_mount)
|
2017-03-28 21:16:10 +00:00
|
|
|
rm -f "$hugetlbfs_mount"/spdk*map_*
|
2016-02-19 21:11:08 +00:00
|
|
|
}
|
|
|
|
|
2017-01-30 13:38:44 +00:00
|
|
|
function status_linux {
|
|
|
|
echo "NVMe devices"
|
|
|
|
|
|
|
|
echo -e "BDF\t\tNuma Node\tDriver name\t\tDevice name"
|
|
|
|
for bdf in $(linux_iter_pci 0108); do
|
|
|
|
driver=`grep DRIVER /sys/bus/pci/devices/$bdf/uevent |awk -F"=" '{print $2}'`
|
|
|
|
node=`cat /sys/bus/pci/devices/$bdf/numa_node`;
|
|
|
|
if [ "$driver" = "nvme" ]; then
|
|
|
|
name="\t"`ls /sys/bus/pci/devices/$bdf/nvme`;
|
|
|
|
else
|
|
|
|
name="-";
|
|
|
|
fi
|
|
|
|
echo -e "$bdf\t$node\t\t$driver\t\t$name";
|
|
|
|
done
|
|
|
|
|
|
|
|
echo "I/OAT DMA"
|
|
|
|
|
|
|
|
#collect all the device_id info of ioat devices.
|
|
|
|
TMP=`grep "PCI_DEVICE_ID_INTEL_IOAT" $rootdir/include/spdk/pci_ids.h \
|
|
|
|
| awk -F"x" '{print $2}'`
|
|
|
|
echo -e "BDF\t\tNuma Node\tDriver Name"
|
|
|
|
for dev_id in $TMP; do
|
|
|
|
# Abuse linux_iter_pci by giving it a device ID instead of a class code
|
|
|
|
for bdf in $(linux_iter_pci $dev_id); do
|
|
|
|
driver=`grep DRIVER /sys/bus/pci/devices/$bdf/uevent |awk -F"=" '{print $2}'`
|
|
|
|
node=`cat /sys/bus/pci/devices/$bdf/numa_node`;
|
|
|
|
echo -e "$bdf\t$node\t\t$driver"
|
|
|
|
done
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2016-02-19 21:11:08 +00:00
|
|
|
function configure_freebsd {
|
|
|
|
TMP=`mktemp`
|
2016-08-08 22:57:49 +00:00
|
|
|
|
|
|
|
# NVMe
|
|
|
|
GREP_STR="class=0x010802"
|
|
|
|
|
|
|
|
# IOAT
|
|
|
|
grep "PCI_DEVICE_ID_INTEL_IOAT" $rootdir/include/spdk/pci_ids.h \
|
|
|
|
| awk -F"x" '{print $2}' > $TMP
|
|
|
|
for dev_id in `cat $TMP`; do
|
|
|
|
GREP_STR="${GREP_STR}\|chip=0x${dev_id}8086"
|
|
|
|
done
|
|
|
|
|
2016-02-19 21:11:08 +00:00
|
|
|
AWK_PROG="{if (count > 0) printf \",\"; printf \"%s:%s:%s\",\$2,\$3,\$4; count++}"
|
|
|
|
echo $AWK_PROG > $TMP
|
2016-08-08 22:57:49 +00:00
|
|
|
|
|
|
|
BDFS=`pciconf -l | grep "${GREP_STR}" | awk -F: -f $TMP`
|
|
|
|
|
2016-02-19 21:11:08 +00:00
|
|
|
kldunload nic_uio.ko || true
|
|
|
|
kenv hw.nic_uio.bdfs=$BDFS
|
|
|
|
kldload nic_uio.ko
|
|
|
|
rm $TMP
|
2016-04-14 20:22:11 +00:00
|
|
|
|
|
|
|
kldunload contigmem.ko || true
|
2016-07-21 16:55:32 +00:00
|
|
|
kenv hw.contigmem.num_buffers=$((NRHUGE * 2 / 256))
|
|
|
|
kenv hw.contigmem.buffer_size=$((256 * 1024 * 1024))
|
2016-04-14 20:22:11 +00:00
|
|
|
kldload contigmem.ko
|
2016-02-19 21:11:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function reset_freebsd {
|
|
|
|
kldunload contigmem.ko || true
|
|
|
|
kldunload nic_uio.ko || true
|
|
|
|
}
|
|
|
|
|
2016-12-14 15:10:12 +00:00
|
|
|
: ${NRHUGE:=1024}
|
2016-04-14 20:22:11 +00:00
|
|
|
|
2016-04-06 03:03:28 +00:00
|
|
|
username=$1
|
|
|
|
mode=$2
|
|
|
|
|
2017-01-30 13:38:44 +00:00
|
|
|
if [ "$username" = "reset" -o "$username" = "config" -o "$username" = "status" ]; then
|
2016-04-06 03:03:28 +00:00
|
|
|
mode="$username"
|
|
|
|
username=""
|
|
|
|
fi
|
|
|
|
|
2016-02-19 21:11:08 +00:00
|
|
|
if [ "$mode" == "" ]; then
|
|
|
|
mode="config"
|
|
|
|
fi
|
|
|
|
|
2016-04-06 03:03:28 +00:00
|
|
|
if [ "$username" = "" ]; then
|
2016-11-29 21:26:42 +00:00
|
|
|
username="$SUDO_USER"
|
|
|
|
if [ "$username" = "" ]; then
|
|
|
|
username=`logname 2>/dev/null` || true
|
|
|
|
fi
|
2016-04-06 03:03:28 +00:00
|
|
|
fi
|
|
|
|
|
2016-02-19 21:11:08 +00:00
|
|
|
if [ `uname` = Linux ]; then
|
|
|
|
if [ "$mode" == "config" ]; then
|
|
|
|
configure_linux
|
|
|
|
elif [ "$mode" == "reset" ]; then
|
|
|
|
reset_linux
|
2017-01-30 13:38:44 +00:00
|
|
|
elif [ "$mode" == "status" ]; then
|
|
|
|
status_linux
|
2016-02-19 21:11:08 +00:00
|
|
|
fi
|
|
|
|
else
|
|
|
|
if [ "$mode" == "config" ]; then
|
|
|
|
configure_freebsd
|
|
|
|
elif [ "$mode" == "reset" ]; then
|
|
|
|
reset_freebsd
|
|
|
|
fi
|
|
|
|
fi
|