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 [[ -n $2 ]] && ( echo "$2"; echo ""; ) 17 echo "Helper script for allocating hugepages and binding NVMe, I/OAT, VMD and Virtio devices" 18 echo "to a generic VFIO kernel driver. If VFIO is not available on the system, this script" 19 echo "will 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, VMD, 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 local blknames=() 139 140 set +e 141 nvme_devs=$(lsblk -d --output NAME | grep "^nvme") 142 set -e 143 for dev in $nvme_devs; do 144 link_name=$(readlink /sys/block/$dev/device/device) || true 145 if [ -z "$link_name" ]; then 146 link_name=$(readlink /sys/block/$dev/device) 147 fi 148 link_bdf=$(basename "$link_name") 149 if [ "$link_bdf" = "$1" ]; then 150 blknames+=($dev) 151 fi 152 done 153 154 printf '%s\n' "${blknames[@]}" 155} 156 157function get_virtio_names_from_bdf { 158 blk_devs=$(lsblk --nodeps --output NAME) 159 virtio_names='' 160 161 for dev in $blk_devs; do 162 if readlink "/sys/block/$dev" | grep -q "$1"; then 163 virtio_names="$virtio_names $dev" 164 fi 165 done 166 167 eval "$2='$virtio_names'" 168} 169 170function configure_linux_pci { 171 local driver_path="" 172 driver_name="" 173 if [[ -n "${DRIVER_OVERRIDE}" ]]; then 174 driver_path="${DRIVER_OVERRIDE%/*}" 175 driver_name="${DRIVER_OVERRIDE##*/}" 176 # path = name -> there is no path 177 if [[ "$driver_path" = "$driver_name" ]]; then 178 driver_path="" 179 fi 180 elif [[ -n "$(ls /sys/kernel/iommu_groups)" || \ 181 (-e /sys/module/vfio/parameters/enable_unsafe_noiommu_mode && \ 182 "$(cat /sys/module/vfio/parameters/enable_unsafe_noiommu_mode)" == "Y") ]]; then 183 driver_name=vfio-pci 184 elif modinfo uio_pci_generic >/dev/null 2>&1; then 185 driver_name=uio_pci_generic 186 elif [[ -r "$rootdir/dpdk/build/kmod/igb_uio.ko" ]]; then 187 driver_path="$rootdir/dpdk/build/kmod/igb_uio.ko" 188 driver_name="igb_uio" 189 modprobe uio 190 echo "WARNING: uio_pci_generic not detected - using $driver_name" 191 else 192 echo "No valid drivers found [vfio-pci, uio_pci_generic, igb_uio]. Please either enable the vfio-pci or uio_pci_generic" 193 echo "kernel modules, or have SPDK build the igb_uio driver by running ./configure --with-igb-uio-driver and recompiling." 194 return 1 195 fi 196 197 # modprobe assumes the directory of the module. If the user passes in a path, we should use insmod 198 if [[ -n "$driver_path" ]]; then 199 insmod $driver_path || true 200 else 201 modprobe $driver_name 202 fi 203 204 # NVMe 205 for bdf in $(iter_all_pci_class_code 01 08 02); do 206 blknames=() 207 if ! pci_can_use $bdf; then 208 pci_dev_echo "$bdf" "Skipping un-whitelisted NVMe controller at $bdf" 209 continue 210 fi 211 212 mount=false 213 for blkname in $(get_nvme_name_from_bdf $bdf); do 214 mountpoints=$(lsblk /dev/$blkname --output MOUNTPOINT -n | wc -w) 215 if [ "$mountpoints" != "0" ]; then 216 mount=true 217 blknames+=($blkname) 218 fi 219 done 220 221 if ! $mount; then 222 linux_bind_driver "$bdf" "$driver_name" 223 else 224 for name in ${blknames[@]}; do 225 pci_dev_echo "$bdf" "Active mountpoints on /dev/$name, so not binding PCI dev" 226 done 227 fi 228 done 229 230 # IOAT 231 TMP=$(mktemp) 232 #collect all the device_id info of ioat devices. 233 grep "PCI_DEVICE_ID_INTEL_IOAT" $rootdir/include/spdk/pci_ids.h \ 234 | awk -F"x" '{print $2}' > $TMP 235 236 for dev_id in $(cat $TMP); do 237 for bdf in $(iter_all_pci_dev_id 8086 $dev_id); do 238 if ! pci_can_use $bdf; then 239 pci_dev_echo "$bdf" "Skipping un-whitelisted I/OAT device" 240 continue 241 fi 242 243 linux_bind_driver "$bdf" "$driver_name" 244 done 245 done 246 rm $TMP 247 248 # virtio 249 TMP=$(mktemp) 250 #collect all the device_id info of virtio devices. 251 grep "PCI_DEVICE_ID_VIRTIO" $rootdir/include/spdk/pci_ids.h \ 252 | awk -F"x" '{print $2}' > $TMP 253 254 for dev_id in $(cat $TMP); do 255 for bdf in $(iter_all_pci_dev_id 1af4 $dev_id); do 256 if ! pci_can_use $bdf; then 257 pci_dev_echo "$bdf" "Skipping un-whitelisted Virtio device at $bdf" 258 continue 259 fi 260 blknames='' 261 get_virtio_names_from_bdf "$bdf" blknames 262 for blkname in $blknames; do 263 if [ "$(lsblk /dev/$blkname --output MOUNTPOINT -n | wc -w)" != "0" ]; then 264 pci_dev_echo "$bdf" "Active mountpoints on /dev/$blkname, so not binding" 265 continue 2 266 fi 267 done 268 269 linux_bind_driver "$bdf" "$driver_name" 270 done 271 done 272 rm $TMP 273 274 # VMD 275 TMP=$(mktemp) 276 #collect all the device_id info of vmd devices. 277 grep "PCI_DEVICE_ID_INTEL_VMD" $rootdir/include/spdk/pci_ids.h \ 278 | awk -F"x" '{print $2}' > $TMP 279 280 for dev_id in $(cat $TMP); do 281 for bdf in $(iter_pci_dev_id 8086 $dev_id); do 282 if [[ -z "$PCI_WHITELIST" ]] || ! pci_can_use $bdf; then 283 echo "Skipping un-whitelisted VMD device at $bdf" 284 continue 285 fi 286 287 linux_bind_driver "$bdf" "$driver_name" 288 echo " VMD generic kdrv: " "$bdf" "$driver_name" 289 done 290 done 291 rm $TMP 292 293 echo "1" > "/sys/bus/pci/rescan" 294} 295 296function cleanup_linux { 297 shopt -s extglob nullglob 298 dirs_to_clean="" 299 dirs_to_clean="$(echo {/var/run,/tmp}/dpdk/spdk{,_pid}+([0-9])) " 300 if [[ -d $XDG_RUNTIME_DIR && $XDG_RUNTIME_DIR != *" "* ]]; then 301 dirs_to_clean+="$(readlink -e assert_not_empty $XDG_RUNTIME_DIR/dpdk/spdk{,_pid}+([0-9]) || true) " 302 fi 303 304 files_to_clean="" 305 for dir in $dirs_to_clean; do 306 files_to_clean+="$(echo $dir/*) " 307 done 308 shopt -u extglob nullglob 309 310 files_to_clean+="$(ls -1 /dev/shm/* | \ 311 grep -E '(spdk_tgt|iscsi|vhost|nvmf|rocksdb|bdevio|bdevperf|vhost_fuzz|nvme_fuzz)_trace|spdk_iscsi_conns' || true) " 312 files_to_clean="$(readlink -e assert_not_empty $files_to_clean || true)" 313 if [[ -z "$files_to_clean" ]]; then 314 echo "Clean" 315 return 0; 316 fi 317 318 shopt -s extglob 319 for fd_dir in $(echo /proc/+([0-9])); do 320 opened_files+="$(readlink -e assert_not_empty $fd_dir/fd/* || true)" 321 done 322 shopt -u extglob 323 324 if [[ -z "$opened_files" ]]; then 325 echo "Can't get list of opened files!" 326 exit 1 327 fi 328 329 echo 'Cleaning' 330 for f in $files_to_clean; do 331 if ! echo "$opened_files" | grep -E -q "^$f\$"; then 332 echo "Removing: $f" 333 rm $f 334 else 335 echo "Still open: $f" 336 fi 337 done 338 339 for dir in $dirs_to_clean; do 340 if ! echo "$opened_files" | grep -E -q "^$dir\$"; then 341 echo "Removing: $dir" 342 rmdir $dir 343 else 344 echo "Still open: $dir" 345 fi 346 done 347 echo "Clean" 348 349 unset dirs_to_clean files_to_clean opened_files 350} 351 352function configure_linux { 353 configure_linux_pci 354 hugetlbfs_mounts=$(linux_hugetlbfs_mounts) 355 356 if [ -z "$hugetlbfs_mounts" ]; then 357 hugetlbfs_mounts=/mnt/huge 358 echo "Mounting hugetlbfs at $hugetlbfs_mounts" 359 mkdir -p "$hugetlbfs_mounts" 360 mount -t hugetlbfs nodev "$hugetlbfs_mounts" 361 fi 362 363 if [ -z "$HUGENODE" ]; then 364 hugepages_target="/proc/sys/vm/nr_hugepages" 365 else 366 hugepages_target="/sys/devices/system/node/node${HUGENODE}/hugepages/hugepages-${HUGEPGSZ}kB/nr_hugepages" 367 fi 368 369 echo "$NRHUGE" > "$hugepages_target" 370 allocated_hugepages=$(cat $hugepages_target) 371 if [ "$allocated_hugepages" -lt "$NRHUGE" ]; then 372 echo "" 373 echo "## ERROR: requested $NRHUGE hugepages but only $allocated_hugepages could be allocated." 374 echo "## Memory might be heavily fragmented. Please try flushing the system cache, or reboot the machine." 375 exit 1 376 fi 377 378 if [ "$driver_name" = "vfio-pci" ]; then 379 if [ -n "$TARGET_USER" ]; then 380 for mount in $hugetlbfs_mounts; do 381 chown "$TARGET_USER" "$mount" 382 chmod g+w "$mount" 383 done 384 fi 385 386 MEMLOCK_AMNT=$(ulimit -l) 387 if [ "$MEMLOCK_AMNT" != "unlimited" ] ; then 388 MEMLOCK_MB=$(( $MEMLOCK_AMNT / 1024 )) 389 echo "" 390 echo "Current user memlock limit: ${MEMLOCK_MB} MB" 391 echo "" 392 echo "This is the maximum amount of memory you will be" 393 echo "able to use with DPDK and VFIO if run as current user." 394 echo -n "To change this, please adjust limits.conf memlock " 395 echo "limit for current user." 396 397 if [ $MEMLOCK_AMNT -lt 65536 ] ; then 398 echo "" 399 echo "## WARNING: memlock limit is less than 64MB" 400 echo -n "## DPDK with VFIO may not be able to initialize " 401 echo "if run as current user." 402 fi 403 fi 404 fi 405 406 if [ ! -f /dev/cpu/0/msr ]; then 407 # Some distros build msr as a module. Make sure it's loaded to ensure 408 # DPDK can easily figure out the TSC rate rather than relying on 100ms 409 # sleeps. 410 modprobe msr || true 411 fi 412} 413 414function reset_linux_pci { 415 # NVMe 416 set +e 417 check_for_driver nvme 418 driver_loaded=$? 419 set -e 420 for bdf in $(iter_all_pci_class_code 01 08 02); do 421 if ! pci_can_use $bdf; then 422 pci_dev_echo "$bdf" "Skipping un-whitelisted NVMe controller $blkname" 423 continue 424 fi 425 if [ $driver_loaded -ne 0 ]; then 426 linux_bind_driver "$bdf" nvme 427 else 428 linux_unbind_driver "$bdf" 429 fi 430 done 431 432 # IOAT 433 TMP=$(mktemp) 434 #collect all the device_id info of ioat devices. 435 grep "PCI_DEVICE_ID_INTEL_IOAT" $rootdir/include/spdk/pci_ids.h \ 436 | awk -F"x" '{print $2}' > $TMP 437 438 set +e 439 check_for_driver ioatdma 440 driver_loaded=$? 441 set -e 442 for dev_id in $(cat $TMP); do 443 for bdf in $(iter_all_pci_dev_id 8086 $dev_id); do 444 if ! pci_can_use $bdf; then 445 pci_dev_echo "$bdf" "Skipping un-whitelisted I/OAT device" 446 continue 447 fi 448 if [ $driver_loaded -ne 0 ]; then 449 linux_bind_driver "$bdf" ioatdma 450 else 451 linux_unbind_driver "$bdf" 452 fi 453 done 454 done 455 rm $TMP 456 457 # virtio 458 TMP=$(mktemp) 459 #collect all the device_id info of virtio devices. 460 grep "PCI_DEVICE_ID_VIRTIO" $rootdir/include/spdk/pci_ids.h \ 461 | awk -F"x" '{print $2}' > $TMP 462 463 # TODO: check if virtio-pci is loaded first and just unbind if it is not loaded 464 # Requires some more investigation - for example, some kernels do not seem to have 465 # virtio-pci but just virtio_scsi instead. Also need to make sure we get the 466 # underscore vs. dash right in the virtio_scsi name. 467 modprobe virtio-pci || true 468 for dev_id in $(cat $TMP); do 469 for bdf in $(iter_all_pci_dev_id 1af4 $dev_id); do 470 if ! pci_can_use $bdf; then 471 pci_dev_echo "$bdf" "Skipping un-whitelisted Virtio device at" 472 continue 473 fi 474 linux_bind_driver "$bdf" virtio-pci 475 done 476 done 477 rm $TMP 478 479 # VMD 480 TMP=$(mktemp) 481 #collect all the device_id info of vmd devices. 482 grep "PCI_DEVICE_ID_INTEL_VMD" $rootdir/include/spdk/pci_ids.h \ 483 | awk -F"x" '{print $2}' > $TMP 484 485 set +e 486 check_for_driver vmd 487 driver_loaded=$? 488 set -e 489 for dev_id in $(cat $TMP); do 490 for bdf in $(iter_pci_dev_id 8086 $dev_id); do 491 if ! pci_can_use $bdf; then 492 echo "Skipping un-whitelisted VMD device at $bdf" 493 continue 494 fi 495 if [ $driver_loaded -ne 0 ]; then 496 linux_bind_driver "$bdf" vmd 497 else 498 linux_unbind_driver "$bdf" 499 fi 500 done 501 done 502 rm $TMP 503 504 echo "1" > "/sys/bus/pci/rescan" 505} 506 507function reset_linux { 508 reset_linux_pci 509 for mount in $(linux_hugetlbfs_mounts); do 510 rm -f "$mount"/spdk*map_* 511 done 512 rm -f /run/.spdk* 513} 514 515function status_linux { 516 echo "Hugepages" 517 printf "%-6s %10s %8s / %6s\n" "node" "hugesize" "free" "total" 518 519 numa_nodes=0 520 shopt -s nullglob 521 for path in /sys/devices/system/node/node?/hugepages/hugepages-*/; do 522 numa_nodes=$((numa_nodes + 1)) 523 free_pages=$(cat $path/free_hugepages) 524 all_pages=$(cat $path/nr_hugepages) 525 526 [[ $path =~ (node[0-9]+)/hugepages/hugepages-([0-9]+kB) ]] 527 528 node=${BASH_REMATCH[1]} 529 huge_size=${BASH_REMATCH[2]} 530 531 printf "%-6s %10s %8s / %6s\n" $node $huge_size $free_pages $all_pages 532 done 533 shopt -u nullglob 534 535 # fall back to system-wide hugepages 536 if [ "$numa_nodes" = "0" ]; then 537 free_pages=$(grep HugePages_Free /proc/meminfo | awk '{ print $2 }') 538 all_pages=$(grep HugePages_Total /proc/meminfo | awk '{ print $2 }') 539 node="-" 540 huge_size="$HUGEPGSZ" 541 542 printf "%-6s %10s %8s / %6s\n" $node $huge_size $free_pages $all_pages 543 fi 544 545 echo "" 546 echo "NVMe devices" 547 548 echo -e "BDF\t\tVendor\tDevice\tNUMA\tDriver\t\tDevice name" 549 for bdf in $(iter_all_pci_class_code 01 08 02); do 550 driver=$(grep DRIVER /sys/bus/pci/devices/$bdf/uevent |awk -F"=" '{print $2}') 551 if [ "$numa_nodes" = "0" ]; then 552 node="-" 553 else 554 node=$(cat /sys/bus/pci/devices/$bdf/numa_node) 555 fi 556 device=$(cat /sys/bus/pci/devices/$bdf/device) 557 vendor=$(cat /sys/bus/pci/devices/$bdf/vendor) 558 if [ "$driver" = "nvme" -a -d /sys/bus/pci/devices/$bdf/nvme ]; then 559 name="\t"$(ls /sys/bus/pci/devices/$bdf/nvme); 560 else 561 name="-"; 562 fi 563 echo -e "$bdf\t${vendor#0x}\t${device#0x}\t$node\t${driver:--}\t\t$name"; 564 done 565 566 echo "" 567 echo "I/OAT DMA" 568 569 #collect all the device_id info of ioat devices. 570 TMP=$(grep "PCI_DEVICE_ID_INTEL_IOAT" $rootdir/include/spdk/pci_ids.h \ 571 | awk -F"x" '{print $2}') 572 echo -e "BDF\t\tVendor\tDevice\tNUMA\tDriver" 573 for dev_id in $TMP; do 574 for bdf in $(iter_all_pci_dev_id 8086 $dev_id); do 575 driver=$(grep DRIVER /sys/bus/pci/devices/$bdf/uevent |awk -F"=" '{print $2}') 576 if [ "$numa_nodes" = "0" ]; then 577 node="-" 578 else 579 node=$(cat /sys/bus/pci/devices/$bdf/numa_node) 580 fi 581 device=$(cat /sys/bus/pci/devices/$bdf/device) 582 vendor=$(cat /sys/bus/pci/devices/$bdf/vendor) 583 echo -e "$bdf\t${vendor#0x}\t${device#0x}\t$node\t${driver:--}" 584 done 585 done 586 587 echo "" 588 echo "virtio" 589 590 #collect all the device_id info of virtio devices. 591 TMP=$(grep "PCI_DEVICE_ID_VIRTIO" $rootdir/include/spdk/pci_ids.h \ 592 | awk -F"x" '{print $2}') 593 echo -e "BDF\t\tVendor\tDevice\tNUMA\tDriver\t\tDevice name" 594 for dev_id in $TMP; do 595 for bdf in $(iter_all_pci_dev_id 1af4 $dev_id); do 596 driver=$(grep DRIVER /sys/bus/pci/devices/$bdf/uevent |awk -F"=" '{print $2}') 597 if [ "$numa_nodes" = "0" ]; then 598 node="-" 599 else 600 node=$(cat /sys/bus/pci/devices/$bdf/numa_node) 601 fi 602 device=$(cat /sys/bus/pci/devices/$bdf/device) 603 vendor=$(cat /sys/bus/pci/devices/$bdf/vendor) 604 blknames='' 605 get_virtio_names_from_bdf "$bdf" blknames 606 echo -e "$bdf\t${vendor#0x}\t${device#0x}\t$node\t\t${driver:--}\t\t$blknames" 607 done 608 done 609 610 echo "VMD" 611 612 #collect all the device_id info of vmd devices. 613 TMP=$(grep "PCI_DEVICE_ID_INTEL_VMD" $rootdir/include/spdk/pci_ids.h \ 614 | awk -F"x" '{print $2}') 615 echo -e "BDF\t\tNuma Node\tDriver Name" 616 for dev_id in $TMP; do 617 for bdf in $(iter_pci_dev_id 8086 $dev_id); do 618 driver=$(grep DRIVER /sys/bus/pci/devices/$bdf/uevent |awk -F"=" '{print $2}') 619 node=$(cat /sys/bus/pci/devices/$bdf/numa_node); 620 echo -e "$bdf\t$node\t\t$driver" 621 done 622 done 623} 624 625function configure_freebsd_pci { 626 TMP=$(mktemp) 627 628 # NVMe 629 GREP_STR="class=0x010802" 630 631 # IOAT 632 grep "PCI_DEVICE_ID_INTEL_IOAT" $rootdir/include/spdk/pci_ids.h \ 633 | awk -F"x" '{print $2}' > $TMP 634 for dev_id in $(cat $TMP); do 635 GREP_STR="${GREP_STR}\|chip=0x${dev_id}8086" 636 done 637 638 # VMD 639 grep "PCI_DEVICE_ID_INTEL_VMD" $rootdir/include/spdk/pci_ids.h \ 640 | awk -F"x" '{print $2}' > $TMP 641 for dev_id in $(cat $TMP); do 642 GREP_STR="${GREP_STR}\|chip=0x${dev_id}8086" 643 done 644 645 AWK_PROG="{if (count > 0) printf \",\"; printf \"%s:%s:%s\",\$2,\$3,\$4; count++}" 646 echo $AWK_PROG > $TMP 647 648 BDFS=$(pciconf -l | grep "${GREP_STR}" | awk -F: -f $TMP) 649 650 kldunload nic_uio.ko || true 651 kenv hw.nic_uio.bdfs=$BDFS 652 kldload nic_uio.ko 653 rm $TMP 654} 655 656function configure_freebsd { 657 configure_freebsd_pci 658 # If contigmem is already loaded but the HUGEMEM specified doesn't match the 659 # previous value, unload contigmem so that we can reload with the new value. 660 if kldstat -q -m contigmem; then 661 if [ $(kenv hw.contigmem.num_buffers) -ne "$((HUGEMEM / 256))" ]; then 662 kldunload contigmem.ko 663 fi 664 fi 665 if ! kldstat -q -m contigmem; then 666 kenv hw.contigmem.num_buffers=$((HUGEMEM / 256)) 667 kenv hw.contigmem.buffer_size=$((256 * 1024 * 1024)) 668 kldload contigmem.ko 669 fi 670} 671 672function reset_freebsd { 673 kldunload contigmem.ko || true 674 kldunload nic_uio.ko || true 675} 676 677mode=$1 678 679if [ -z "$mode" ]; then 680 mode="config" 681fi 682 683: ${HUGEMEM:=2048} 684: ${PCI_WHITELIST:=""} 685: ${PCI_BLACKLIST:=""} 686 687if [ -n "$NVME_WHITELIST" ]; then 688 PCI_WHITELIST="$PCI_WHITELIST $NVME_WHITELIST" 689fi 690 691if [ -n "$SKIP_PCI" ]; then 692 PCI_WHITELIST="none" 693fi 694 695if [ -z "$TARGET_USER" ]; then 696 TARGET_USER="$SUDO_USER" 697 if [ -z "$TARGET_USER" ]; then 698 TARGET_USER=$(logname 2>/dev/null) || true 699 fi 700fi 701 702if [ $(uname) = Linux ]; then 703 HUGEPGSZ=$(( $(grep Hugepagesize /proc/meminfo | cut -d : -f 2 | tr -dc '0-9') )) 704 HUGEPGSZ_MB=$(( $HUGEPGSZ / 1024 )) 705 : ${NRHUGE=$(( (HUGEMEM + HUGEPGSZ_MB - 1) / HUGEPGSZ_MB ))} 706 707 if [ "$mode" == "config" ]; then 708 configure_linux 709 elif [ "$mode" == "cleanup" ]; then 710 cleanup_linux 711 elif [ "$mode" == "reset" ]; then 712 reset_linux 713 elif [ "$mode" == "status" ]; then 714 status_linux 715 elif [ "$mode" == "help" ]; then 716 usage $0 717 else 718 usage $0 "Invalid argument '$mode'" 719 fi 720else 721 if [ "$mode" == "config" ]; then 722 configure_freebsd 723 elif [ "$mode" == "reset" ]; then 724 reset_freebsd 725 elif [ "$mode" == "cleanup" ]; then 726 echo "setup.sh cleanup function not yet supported on $(uname)" 727 elif [ "$mode" == "status" ]; then 728 echo "setup.sh status function not yet supported on $(uname)" 729 elif [ "$mode" == "help" ]; then 730 usage $0 731 else 732 usage $0 "Invalid argument '$mode'" 733 fi 734fi 735