xref: /spdk/scripts/setup.sh (revision fa2d95b3fe66e7f5c543eaef89fa00d4eaa0e6e7)
1#!/usr/bin/env bash
2
3set -e
4
5rootdir=$(readlink -f $(dirname $0))/..
6source "$rootdir/scripts/common.sh"
7
8function usage()
9{
10	if [ `uname` = Linux ]; then
11		options="[config|reset|status|cleanup|help]"
12	else
13		options="[config|reset|help]"
14	fi
15
16	[[ ! -z $2 ]] && ( echo "$2"; echo ""; )
17	echo "Helper script for allocating hugepages and binding NVMe, I/OAT and Virtio devices to"
18	echo "a generic VFIO kernel driver. If VFIO is not available on the system, this script will"
19	echo "fall back to UIO. NVMe and Virtio devices with active mountpoints will be ignored."
20	echo "All hugepage operations use default hugepage size on the system (hugepagesz)."
21	echo "Usage: $(basename $1) $options"
22	echo
23	echo "$options - as following:"
24	echo "config            Default mode. Allocate hugepages and bind PCI devices."
25	if [ `uname` = Linux ]; then
26		echo "cleanup            Remove any orphaned files that can be left in the system after SPDK application exit"
27	fi
28	echo "reset             Rebind PCI devices back to their original drivers."
29	echo "                  Also cleanup any leftover spdk files/resources."
30	echo "                  Hugepage memory size will remain unchanged."
31	if [ `uname` = Linux ]; then
32		echo "status            Print status of all SPDK-compatible devices on the system."
33	fi
34	echo "help              Print this help message."
35	echo
36	echo "The following environment variables can be specified."
37	echo "HUGEMEM           Size of hugepage memory to allocate (in MB). 2048 by default."
38	echo "                  For NUMA systems, the hugepages will be evenly distributed"
39	echo "                  between CPU nodes"
40	echo "NRHUGE            Number of hugepages to allocate. This variable overwrites HUGEMEM."
41	echo "HUGENODE          Specific NUMA node to allocate hugepages on. To allocate"
42	echo "                  hugepages on multiple nodes run this script multiple times -"
43	echo "                  once for each node."
44	echo "PCI_WHITELIST"
45	echo "PCI_BLACKLIST     Whitespace separated list of PCI devices (NVMe, I/OAT, Virtio)."
46	echo "                  Each device must be specified as a full PCI address."
47	echo "                  E.g. PCI_WHITELIST=\"0000:01:00.0 0000:02:00.0\""
48	echo "                  To blacklist all PCI devices use a non-valid address."
49	echo "                  E.g. PCI_WHITELIST=\"none\""
50	echo "                  If PCI_WHITELIST and PCI_BLACKLIST are empty or unset, all PCI devices"
51	echo "                  will be bound."
52	echo "                  Each device in PCI_BLACKLIST will be ignored (driver won't be changed)."
53	echo "                  PCI_BLACKLIST has precedence over PCI_WHITELIST."
54	echo "TARGET_USER       User that will own hugepage mountpoint directory and vfio groups."
55	echo "                  By default the current user will be used."
56	echo "DRIVER_OVERRIDE   Disable automatic vfio-pci/uio_pci_generic selection and forcefully"
57	echo "                  bind devices to the given driver."
58	echo "                  E.g. DRIVER_OVERRIDE=uio_pci_generic or DRIVER_OVERRIDE=/home/public/dpdk/build/kmod/igb_uio.ko"
59	exit 0
60}
61
62# In monolithic kernels the lsmod won't work. So
63# back that with a /sys/modules. We also check
64# /sys/bus/pci/drivers/ as neither lsmod nor /sys/modules might
65# contain needed info (like in Fedora-like OS).
66function check_for_driver {
67	if lsmod | grep -q ${1//-/_}; then
68		return 1
69	fi
70
71	if [[ -d /sys/module/${1} || \
72			-d /sys/module/${1//-/_} || \
73			-d /sys/bus/pci/drivers/${1} || \
74			-d /sys/bus/pci/drivers/${1//-/_} ]]; then
75		return 2
76	fi
77	return 0
78}
79
80function pci_dev_echo() {
81	local bdf="$1"
82	local vendor="$(cat /sys/bus/pci/devices/$bdf/vendor)"
83	local device="$(cat /sys/bus/pci/devices/$bdf/device)"
84	shift
85	echo "$bdf (${vendor#0x} ${device#0x}): $@"
86}
87
88function linux_bind_driver() {
89	bdf="$1"
90	driver_name="$2"
91	old_driver_name="no driver"
92	ven_dev_id=$(lspci -n -s $bdf | cut -d' ' -f3 | sed 's/:/ /')
93
94	if [ -e "/sys/bus/pci/devices/$bdf/driver" ]; then
95		old_driver_name=$(basename $(readlink /sys/bus/pci/devices/$bdf/driver))
96
97		if [ "$driver_name" = "$old_driver_name" ]; then
98			pci_dev_echo "$bdf" "Already using the $old_driver_name driver"
99			return 0
100		fi
101
102		echo "$ven_dev_id" > "/sys/bus/pci/devices/$bdf/driver/remove_id" 2> /dev/null || true
103		echo "$bdf" > "/sys/bus/pci/devices/$bdf/driver/unbind"
104	fi
105
106	pci_dev_echo "$bdf" "$old_driver_name -> $driver_name"
107
108	echo "$ven_dev_id" > "/sys/bus/pci/drivers/$driver_name/new_id" 2> /dev/null || true
109	echo "$bdf" > "/sys/bus/pci/drivers/$driver_name/bind" 2> /dev/null || true
110
111	iommu_group=$(basename $(readlink -f /sys/bus/pci/devices/$bdf/iommu_group))
112	if [ -e "/dev/vfio/$iommu_group" ]; then
113		if [ -n "$TARGET_USER" ]; then
114			chown "$TARGET_USER" "/dev/vfio/$iommu_group"
115		fi
116	fi
117}
118
119function linux_unbind_driver() {
120	local bdf="$1"
121	local ven_dev_id=$(lspci -n -s $bdf | cut -d' ' -f3 | sed 's/:/ /')
122	local old_driver_name="no driver"
123
124	if [ -e "/sys/bus/pci/devices/$bdf/driver" ]; then
125		old_driver_name=$(basename $(readlink /sys/bus/pci/devices/$bdf/driver))
126		echo "$ven_dev_id" > "/sys/bus/pci/devices/$bdf/driver/remove_id" 2> /dev/null || true
127		echo "$bdf" > "/sys/bus/pci/devices/$bdf/driver/unbind"
128	fi
129
130	pci_dev_echo "$bdf" "$old_driver_name -> no driver"
131}
132
133function linux_hugetlbfs_mounts() {
134	mount | grep ' type hugetlbfs ' | awk '{ print $3 }'
135}
136
137function get_nvme_name_from_bdf {
138	set +e
139	nvme_devs=`lsblk -d --output NAME | grep "^nvme"`
140	set -e
141	for dev in $nvme_devs; do
142		link_name=$(readlink /sys/block/$dev/device/device) || true
143		if [ -z "$link_name" ]; then
144			link_name=$(readlink /sys/block/$dev/device)
145		fi
146		link_bdf=$(basename "$link_name")
147		if [ "$link_bdf" = "$1" ]; then
148			eval "$2=$dev"
149			return
150		fi
151	done
152}
153
154function get_virtio_names_from_bdf {
155	blk_devs=`lsblk --nodeps --output NAME`
156	virtio_names=''
157
158	for dev in $blk_devs; do
159		if readlink "/sys/block/$dev" | grep -q "$1"; then
160			virtio_names="$virtio_names $dev"
161		fi
162	done
163
164	eval "$2='$virtio_names'"
165}
166
167function configure_linux_pci {
168	local driver_path=""
169	driver_name=""
170	if [[ -n "${DRIVER_OVERRIDE}" ]]; then
171		driver_path="${DRIVER_OVERRIDE%/*}"
172		driver_name="${DRIVER_OVERRIDE##*/}"
173		# path = name -> there is no path
174		if [[ "$driver_path" = "$driver_name" ]]; then
175			driver_path=""
176		fi
177	elif [[ -n "$(ls /sys/kernel/iommu_groups)" || \
178	     (-e /sys/module/vfio/parameters/enable_unsafe_noiommu_mode && \
179	     "$(cat /sys/module/vfio/parameters/enable_unsafe_noiommu_mode)" == "Y") ]]; then
180		driver_name=vfio-pci
181	elif modinfo uio_pci_generic >/dev/null 2>&1; then
182		driver_name=uio_pci_generic
183	elif [[ -r "$rootdir/dpdk/build/kmod/igb_uio.ko" ]]; then
184		driver_path="$rootdir/dpdk/build/kmod/igb_uio.ko"
185		driver_name="igb_uio"
186		modprobe uio
187		echo "WARNING: uio_pci_generic not detected - using $driver_name"
188	else
189		echo "No valid drivers found [vfio-pci, uio_pci_generic, igb_uio]. Please either enable the vfio-pci or uio_pci_generic"
190		echo "kernel modules, or have SPDK build the igb_uio driver by running ./configure --with-igb-uio-driver and recompiling."
191		return 1
192	fi
193
194	# modprobe assumes the directory of the module. If the user passes in a path, we should use insmod
195	if [[ -n "$driver_path" ]]; then
196		insmod $driver_path || true
197	else
198		modprobe $driver_name
199	fi
200
201	# NVMe
202	for bdf in $(iter_all_pci_class_code 01 08 02); do
203		blkname=''
204		get_nvme_name_from_bdf "$bdf" blkname
205		if ! pci_can_use $bdf; then
206			pci_dev_echo "$bdf" "Skipping un-whitelisted NVMe controller $blkname"
207			continue
208		fi
209		if [ "$blkname" != "" ]; then
210			mountpoints=$(lsblk /dev/$blkname --output MOUNTPOINT -n | wc -w)
211		else
212			mountpoints="0"
213		fi
214		if [ "$mountpoints" = "0" ]; then
215			linux_bind_driver "$bdf" "$driver_name"
216		else
217			pci_dev_echo "$bdf" "Active mountpoints on /dev/$blkname, so not binding PCI dev"
218		fi
219	done
220
221	# IOAT
222	TMP=`mktemp`
223	#collect all the device_id info of ioat devices.
224	grep "PCI_DEVICE_ID_INTEL_IOAT" $rootdir/include/spdk/pci_ids.h \
225	| awk -F"x" '{print $2}' > $TMP
226
227	for dev_id in `cat $TMP`; do
228		for bdf in $(iter_all_pci_dev_id 8086 $dev_id); do
229			if ! pci_can_use $bdf; then
230				pci_dev_echo "$bdf" "Skipping un-whitelisted I/OAT device"
231				continue
232			fi
233
234			linux_bind_driver "$bdf" "$driver_name"
235		done
236	done
237	rm $TMP
238
239	# virtio
240	TMP=`mktemp`
241	#collect all the device_id info of virtio devices.
242	grep "PCI_DEVICE_ID_VIRTIO" $rootdir/include/spdk/pci_ids.h \
243	| awk -F"x" '{print $2}' > $TMP
244
245	for dev_id in `cat $TMP`; do
246		for bdf in $(iter_all_pci_dev_id 1af4 $dev_id); do
247			if ! pci_can_use $bdf; then
248				pci_dev_echo "$bdf" "Skipping un-whitelisted Virtio device at $bdf"
249				continue
250			fi
251			blknames=''
252			get_virtio_names_from_bdf "$bdf" blknames
253			for blkname in $blknames; do
254				if [ "$(lsblk /dev/$blkname --output MOUNTPOINT -n | wc -w)" != "0" ]; then
255					pci_dev_echo "$bdf" "Active mountpoints on /dev/$blkname, so not binding"
256					continue 2
257				fi
258			done
259
260			linux_bind_driver "$bdf" "$driver_name"
261		done
262	done
263	rm $TMP
264
265	echo "1" > "/sys/bus/pci/rescan"
266}
267
268function cleanup_linux {
269	shopt -s extglob nullglob
270	dirs_to_clean=""
271	dirs_to_clean="$(echo {/var/run,/tmp}/dpdk/spdk{,_pid}+([0-9])) "
272	if [[ -d $XDG_RUNTIME_DIR && $XDG_RUNTIME_DIR != *" "* ]]; then
273		dirs_to_clean+="$(readlink -e assert_not_empty $XDG_RUNTIME_DIR/dpdk/spdk{,_pid}+([0-9]) || true) "
274	fi
275
276	files_to_clean=""
277	for dir in $dirs_to_clean; do
278		files_to_clean+="$(echo $dir/*) "
279	done
280	shopt -u extglob nullglob
281
282	files_to_clean+="$(ls -1 /dev/shm/* | egrep '(spdk_tgt|iscsi|vhost|nvmf|rocksdb|bdevio|bdevperf)_trace|spdk_iscsi_conns' || true) "
283	files_to_clean="$(readlink -e assert_not_empty $files_to_clean || true)"
284	if [[ -z "$files_to_clean" ]]; then
285		echo "Clean"
286		return 0;
287	fi
288
289	shopt -s extglob
290	for fd_dir in $(echo /proc/+([0-9])); do
291		opened_files+="$(readlink -e assert_not_empty $fd_dir/fd/* || true)"
292	done
293	shopt -u extglob
294
295	if [[ -z "$opened_files" ]]; then
296		echo "Can't get list of opened files!"
297		exit 1
298	fi
299
300	echo 'Cleaning'
301	for f in $files_to_clean; do
302		if ! echo "$opened_files" | egrep -q "^$f\$"; then
303			echo "Removing:    $f"
304			rm $f
305		else
306			echo "Still open: $f"
307		fi
308	done
309
310	for dir in $dirs_to_clean; do
311	if ! echo "$opened_files" | egrep -q "^$dir\$"; then
312		echo "Removing:    $dir"
313		rmdir $dir
314	else
315		echo "Still open: $dir"
316	fi
317	done
318	echo "Clean"
319
320	unset dirs_to_clean files_to_clean opened_files
321}
322
323function configure_linux {
324	configure_linux_pci
325	hugetlbfs_mounts=$(linux_hugetlbfs_mounts)
326
327	if [ -z "$hugetlbfs_mounts" ]; then
328		hugetlbfs_mounts=/mnt/huge
329		echo "Mounting hugetlbfs at $hugetlbfs_mounts"
330		mkdir -p "$hugetlbfs_mounts"
331		mount -t hugetlbfs nodev "$hugetlbfs_mounts"
332	fi
333
334	if [ -z "$HUGENODE" ]; then
335		hugepages_target="/proc/sys/vm/nr_hugepages"
336	else
337		hugepages_target="/sys/devices/system/node/node${HUGENODE}/hugepages/hugepages-${HUGEPGSZ}kB/nr_hugepages"
338	fi
339
340	echo "$NRHUGE" > "$hugepages_target"
341	allocated_hugepages=`cat $hugepages_target`
342	if [ "$allocated_hugepages" -lt "$NRHUGE" ]; then
343		echo ""
344		echo "## ERROR: requested $NRHUGE hugepages but only $allocated_hugepages could be allocated."
345		echo "## Memory might be heavily fragmented. Please try flushing the system cache, or reboot the machine."
346		exit 1
347	fi
348
349	if [ "$driver_name" = "vfio-pci" ]; then
350		if [ -n "$TARGET_USER" ]; then
351			for mount in $hugetlbfs_mounts; do
352				chown "$TARGET_USER" "$mount"
353				chmod g+w "$mount"
354			done
355		fi
356
357		MEMLOCK_AMNT=`ulimit -l`
358		if [ "$MEMLOCK_AMNT" != "unlimited" ] ; then
359			MEMLOCK_MB=$(( $MEMLOCK_AMNT / 1024 ))
360			echo ""
361			echo "Current user memlock limit: ${MEMLOCK_MB} MB"
362			echo ""
363			echo "This is the maximum amount of memory you will be"
364			echo "able to use with DPDK and VFIO if run as current user."
365			echo -n "To change this, please adjust limits.conf memlock "
366			echo "limit for current user."
367
368			if [ $MEMLOCK_AMNT -lt 65536 ] ; then
369				echo ""
370				echo "## WARNING: memlock limit is less than 64MB"
371				echo -n "## DPDK with VFIO may not be able to initialize "
372				echo "if run as current user."
373			fi
374		fi
375	fi
376}
377
378function reset_linux_pci {
379	# NVMe
380	set +e
381	check_for_driver nvme
382	driver_loaded=$?
383	set -e
384	for bdf in $(iter_all_pci_class_code 01 08 02); do
385		if ! pci_can_use $bdf; then
386			pci_dev_echo "$bdf" "Skipping un-whitelisted NVMe controller $blkname"
387			continue
388		fi
389		if [ $driver_loaded -ne 0 ]; then
390			linux_bind_driver "$bdf" nvme
391		else
392			linux_unbind_driver "$bdf"
393		fi
394	done
395
396	# IOAT
397	TMP=`mktemp`
398	#collect all the device_id info of ioat devices.
399	grep "PCI_DEVICE_ID_INTEL_IOAT" $rootdir/include/spdk/pci_ids.h \
400	| awk -F"x" '{print $2}' > $TMP
401
402	set +e
403	check_for_driver ioatdma
404	driver_loaded=$?
405	set -e
406	for dev_id in `cat $TMP`; do
407		for bdf in $(iter_all_pci_dev_id 8086 $dev_id); do
408			if ! pci_can_use $bdf; then
409				pci_dev_echo "$bdf" "Skipping un-whitelisted I/OAT device"
410				continue
411			fi
412			if [ $driver_loaded -ne 0 ]; then
413				linux_bind_driver "$bdf" ioatdma
414			else
415				linux_unbind_driver "$bdf"
416			fi
417		done
418	done
419	rm $TMP
420
421	# virtio
422	TMP=`mktemp`
423	#collect all the device_id info of virtio devices.
424	grep "PCI_DEVICE_ID_VIRTIO" $rootdir/include/spdk/pci_ids.h \
425	| awk -F"x" '{print $2}' > $TMP
426
427	# TODO: check if virtio-pci is loaded first and just unbind if it is not loaded
428	# Requires some more investigation - for example, some kernels do not seem to have
429	#  virtio-pci but just virtio_scsi instead.  Also need to make sure we get the
430	#  underscore vs. dash right in the virtio_scsi name.
431	modprobe virtio-pci || true
432	for dev_id in `cat $TMP`; do
433		for bdf in $(iter_all_pci_dev_id 1af4 $dev_id); do
434			if ! pci_can_use $bdf; then
435				pci_dev_echo "$bdf" "Skipping un-whitelisted Virtio device at"
436				continue
437			fi
438			linux_bind_driver "$bdf" virtio-pci
439		done
440	done
441	rm $TMP
442
443	echo "1" > "/sys/bus/pci/rescan"
444}
445
446function reset_linux {
447	reset_linux_pci
448	for mount in $(linux_hugetlbfs_mounts); do
449		rm -f "$mount"/spdk*map_*
450	done
451	rm -f /run/.spdk*
452}
453
454function status_linux {
455	echo "Hugepages"
456	printf "%-6s %10s %8s / %6s\n" "node" "hugesize"  "free" "total"
457
458	numa_nodes=0
459	shopt -s nullglob
460	for path in /sys/devices/system/node/node?/hugepages/hugepages-*/; do
461		numa_nodes=$((numa_nodes + 1))
462		free_pages=`cat $path/free_hugepages`
463		all_pages=`cat $path/nr_hugepages`
464
465		[[ $path =~ (node[0-9]+)/hugepages/hugepages-([0-9]+kB) ]]
466
467		node=${BASH_REMATCH[1]}
468		huge_size=${BASH_REMATCH[2]}
469
470		printf "%-6s %10s %8s / %6s\n" $node $huge_size $free_pages $all_pages
471	done
472	shopt -u nullglob
473
474	# fall back to system-wide hugepages
475	if [ "$numa_nodes" = "0" ]; then
476		free_pages=`grep HugePages_Free /proc/meminfo | awk '{ print $2 }'`
477		all_pages=`grep HugePages_Total /proc/meminfo | awk '{ print $2 }'`
478		node="-"
479		huge_size="$HUGEPGSZ"
480
481		printf "%-6s %10s %8s / %6s\n" $node $huge_size $free_pages $all_pages
482	fi
483
484	echo ""
485	echo "NVMe devices"
486
487	echo -e "BDF\t\tVendor\tDevice\tNUMA\tDriver\t\tDevice name"
488	for bdf in $(iter_all_pci_class_code 01 08 02); do
489		driver=$(grep DRIVER /sys/bus/pci/devices/$bdf/uevent |awk -F"=" '{print $2}')
490		if [ "$numa_nodes" = "0" ]; then
491			node="-"
492		else
493			node=$(cat /sys/bus/pci/devices/$bdf/numa_node)
494		fi
495		device=$(cat /sys/bus/pci/devices/$bdf/device)
496		vendor=$(cat /sys/bus/pci/devices/$bdf/vendor)
497		if [ "$driver" = "nvme" -a -d /sys/bus/pci/devices/$bdf/nvme ]; then
498			name="\t"`ls /sys/bus/pci/devices/$bdf/nvme`;
499		else
500			name="-";
501		fi
502		echo -e "$bdf\t${vendor#0x}\t${device#0x}\t$node\t${driver:--}\t\t$name";
503	done
504
505	echo ""
506	echo "I/OAT DMA"
507
508	#collect all the device_id info of ioat devices.
509	TMP=`grep "PCI_DEVICE_ID_INTEL_IOAT" $rootdir/include/spdk/pci_ids.h \
510	| awk -F"x" '{print $2}'`
511	echo -e "BDF\t\tVendor\tDevice\tNUMA\tDriver"
512	for dev_id in $TMP; do
513		for bdf in $(iter_all_pci_dev_id 8086 $dev_id); do
514			driver=$(grep DRIVER /sys/bus/pci/devices/$bdf/uevent |awk -F"=" '{print $2}')
515			if [ "$numa_nodes" = "0" ]; then
516				node="-"
517			else
518				node=$(cat /sys/bus/pci/devices/$bdf/numa_node)
519			fi
520			device=$(cat /sys/bus/pci/devices/$bdf/device)
521			vendor=$(cat /sys/bus/pci/devices/$bdf/vendor)
522			echo -e "$bdf\t${vendor#0x}\t${device#0x}\t$node\t${driver:--}"
523		done
524	done
525
526	echo ""
527	echo "virtio"
528
529	#collect all the device_id info of virtio devices.
530	TMP=`grep "PCI_DEVICE_ID_VIRTIO" $rootdir/include/spdk/pci_ids.h \
531	| awk -F"x" '{print $2}'`
532	echo -e "BDF\t\tVendor\tDevice\tNUMA\tDriver\t\tDevice name"
533	for dev_id in $TMP; do
534		for bdf in $(iter_all_pci_dev_id 1af4 $dev_id); do
535			driver=$(grep DRIVER /sys/bus/pci/devices/$bdf/uevent |awk -F"=" '{print $2}')
536			if [ "$numa_nodes" = "0" ]; then
537				node="-"
538			else
539				node=$(cat /sys/bus/pci/devices/$bdf/numa_node)
540			fi
541			device=$(cat /sys/bus/pci/devices/$bdf/device)
542			vendor=$(cat /sys/bus/pci/devices/$bdf/vendor)
543			blknames=''
544			get_virtio_names_from_bdf "$bdf" blknames
545			echo -e "$bdf\t${vendor#0x}\t${device#0x}\t$node\t\t${driver:--}\t\t$blknames"
546		done
547	done
548}
549
550function configure_freebsd_pci {
551	TMP=`mktemp`
552
553	# NVMe
554	GREP_STR="class=0x010802"
555
556	# IOAT
557	grep "PCI_DEVICE_ID_INTEL_IOAT" $rootdir/include/spdk/pci_ids.h \
558	| awk -F"x" '{print $2}' > $TMP
559	for dev_id in `cat $TMP`; do
560		GREP_STR="${GREP_STR}\|chip=0x${dev_id}8086"
561	done
562
563	AWK_PROG="{if (count > 0) printf \",\"; printf \"%s:%s:%s\",\$2,\$3,\$4; count++}"
564	echo $AWK_PROG > $TMP
565
566	BDFS=`pciconf -l | grep "${GREP_STR}" | awk -F: -f $TMP`
567
568	kldunload nic_uio.ko || true
569	kenv hw.nic_uio.bdfs=$BDFS
570	kldload nic_uio.ko
571	rm $TMP
572}
573
574function configure_freebsd {
575	configure_freebsd_pci
576	# If contigmem is already loaded but the HUGEMEM specified doesn't match the
577	#  previous value, unload contigmem so that we can reload with the new value.
578	if kldstat -q -m contigmem; then
579		if [ `kenv hw.contigmem.num_buffers` -ne "$((HUGEMEM / 256))" ]; then
580			kldunload contigmem.ko
581		fi
582	fi
583	if ! kldstat -q -m contigmem; then
584		kenv hw.contigmem.num_buffers=$((HUGEMEM / 256))
585		kenv hw.contigmem.buffer_size=$((256 * 1024 * 1024))
586		kldload contigmem.ko
587	fi
588}
589
590function reset_freebsd {
591	kldunload contigmem.ko || true
592	kldunload nic_uio.ko || true
593}
594
595mode=$1
596
597if [ -z "$mode" ]; then
598	mode="config"
599fi
600
601: ${HUGEMEM:=2048}
602: ${PCI_WHITELIST:=""}
603: ${PCI_BLACKLIST:=""}
604
605if [ -n "$NVME_WHITELIST" ]; then
606	PCI_WHITELIST="$PCI_WHITELIST $NVME_WHITELIST"
607fi
608
609if [ -n "$SKIP_PCI" ]; then
610	PCI_WHITELIST="none"
611fi
612
613if [ -z "$TARGET_USER" ]; then
614	TARGET_USER="$SUDO_USER"
615	if [ -z "$TARGET_USER" ]; then
616		TARGET_USER=`logname 2>/dev/null` || true
617	fi
618fi
619
620if [ `uname` = Linux ]; then
621	HUGEPGSZ=$(( `grep Hugepagesize /proc/meminfo | cut -d : -f 2 | tr -dc '0-9'` ))
622	HUGEPGSZ_MB=$(( $HUGEPGSZ / 1024 ))
623	: ${NRHUGE=$(( (HUGEMEM + HUGEPGSZ_MB - 1) / HUGEPGSZ_MB ))}
624
625	if [ "$mode" == "config" ]; then
626		configure_linux
627	elif [ "$mode" == "cleanup" ]; then
628		cleanup_linux
629	elif [ "$mode" == "reset" ]; then
630		reset_linux
631	elif [ "$mode" == "status" ]; then
632		status_linux
633	elif [ "$mode" == "help" ]; then
634		usage $0
635	else
636		usage $0 "Invalid argument '$mode'"
637	fi
638else
639	if [ "$mode" == "config" ]; then
640		configure_freebsd
641	elif [ "$mode" == "reset" ]; then
642		reset_freebsd
643	elif [ "$mode" == "cleanup" ]; then
644		echo "setup.sh cleanup function not yet supported on $(uname)"
645	elif [ "$mode" == "status" ]; then
646		echo "setup.sh status function not yet supported on $(uname)"
647	elif [ "$mode" == "help" ]; then
648		usage $0
649	else
650		usage $0 "Invalid argument '$mode'"
651	fi
652fi
653