xref: /spdk/scripts/setup.sh (revision 04c48172b9879a8824de83c842087d871c433d12)
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/include/spdk/pci_ids.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 hugetlbfs; 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=$(( $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/include/spdk/pci_ids.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
131	# NVMe
132	GREP_STR="class=0x010802"
133
134	# IOAT
135	grep "PCI_DEVICE_ID_INTEL_IOAT" $rootdir/include/spdk/pci_ids.h \
136	| awk -F"x" '{print $2}' > $TMP
137	for dev_id in `cat $TMP`; do
138		GREP_STR="${GREP_STR}\|chip=0x${dev_id}8086"
139	done
140
141	AWK_PROG="{if (count > 0) printf \",\"; printf \"%s:%s:%s\",\$2,\$3,\$4; count++}"
142	echo $AWK_PROG > $TMP
143
144	BDFS=`pciconf -l | grep "${GREP_STR}" | awk -F: -f $TMP`
145
146	kldunload nic_uio.ko || true
147	kenv hw.nic_uio.bdfs=$BDFS
148	kldload nic_uio.ko
149	rm $TMP
150
151	kldunload contigmem.ko || true
152	kenv hw.contigmem.num_buffers=$((NRHUGE * 2 / 256))
153	kenv hw.contigmem.buffer_size=$((256 * 1024 * 1024))
154	kldload contigmem.ko
155}
156
157function reset_freebsd {
158	kldunload contigmem.ko || true
159	kldunload nic_uio.ko || true
160}
161
162NRHUGE=1024
163
164username=$1
165mode=$2
166
167if [ "$username" = "reset" -o "$username" = "config" ]; then
168	mode="$username"
169	username=""
170fi
171
172if [ "$mode" == "" ]; then
173	mode="config"
174fi
175
176if [ "$username" = "" ]; then
177	username=`logname`
178fi
179
180if [ `uname` = Linux ]; then
181	if [ "$mode" == "config" ]; then
182		configure_linux
183	elif [ "$mode" == "reset" ]; then
184		reset_linux
185	fi
186else
187	if [ "$mode" == "config" ]; then
188		configure_freebsd
189	elif [ "$mode" == "reset" ]; then
190		reset_freebsd
191	fi
192fi
193