1eb53c232Spaul luse# SPDX-License-Identifier: BSD-3-Clause 2eb53c232Spaul luse# Copyright (C) 2018 Intel Corporation 3eb53c232Spaul luse# All rights reserved. 4eb53c232Spaul luse# 5eb53c232Spaul luse 6f0c20934SDaniel Verkamp# Common shell utility functions 7f0c20934SDaniel Verkamp 8a1280c98SJim Harris# Check if PCI device is in PCI_ALLOWED and not in PCI_BLOCKED 95de43a75SPawel Wodkowski# Env: 10a1280c98SJim Harris# if PCI_ALLOWED is empty assume device is allowed 11a1280c98SJim Harris# if PCI_BLOCKED is empty assume device is NOT blocked 125de43a75SPawel Wodkowski# Params: 135de43a75SPawel Wodkowski# $1 - PCI BDF 14*cb7af50cSMichal Berger 15*cb7af50cSMichal Bergershopt -s extglob 16*cb7af50cSMichal Berger 17ad32c7b8SPawel Wodkowskifunction pci_can_use() { 185de43a75SPawel Wodkowski local i 195de43a75SPawel Wodkowski 205de43a75SPawel Wodkowski # The '\ ' part is important 21a1280c98SJim Harris if [[ " $PCI_BLOCKED " =~ \ $1\ ]]; then 225de43a75SPawel Wodkowski return 1 235de43a75SPawel Wodkowski fi 245de43a75SPawel Wodkowski 25a1280c98SJim Harris if [[ -z "$PCI_ALLOWED" ]]; then 26a1280c98SJim Harris #no allow list specified, bind all devices 275de43a75SPawel Wodkowski return 0 285de43a75SPawel Wodkowski fi 295de43a75SPawel Wodkowski 30a1280c98SJim Harris for i in $PCI_ALLOWED; do 315de43a75SPawel Wodkowski if [ "$i" == "$1" ]; then 325de43a75SPawel Wodkowski return 0 335de43a75SPawel Wodkowski fi 345de43a75SPawel Wodkowski done 355de43a75SPawel Wodkowski 365de43a75SPawel Wodkowski return 1 375de43a75SPawel Wodkowski} 385de43a75SPawel Wodkowski 399b3773dbSMichal Bergerresolve_mod() { 409b3773dbSMichal Berger local mod=$1 aliases=() 419b3773dbSMichal Berger 429b3773dbSMichal Berger if aliases=($(modprobe -R "$mod")); then 439b3773dbSMichal Berger echo "${aliases[0]}" 449b3773dbSMichal Berger else 459b3773dbSMichal Berger echo "unknown" 469b3773dbSMichal Berger fi 2> /dev/null 479b3773dbSMichal Berger} 489b3773dbSMichal Berger 4936e573fcSMichal Bergercache_pci_init() { 5036e573fcSMichal Berger local -gA pci_bus_cache 515a436f0cSMichal Berger local -gA pci_ids_vendor 525a436f0cSMichal Berger local -gA pci_ids_device 535f61a0c9SMichal Berger local -gA pci_bus_driver 549b3773dbSMichal Berger local -gA pci_mod_driver 559b3773dbSMichal Berger local -gA pci_mod_resolved 56c5c065e9SMichal Berger local -gA pci_iommu_groups 57c5c065e9SMichal Berger local -ga iommu_groups 5836e573fcSMichal Berger 5936e573fcSMichal Berger [[ -z ${pci_bus_cache[*]} || $CMD == reset ]] || return 1 6036e573fcSMichal Berger 6136e573fcSMichal Berger pci_bus_cache=() 625a436f0cSMichal Berger pci_bus_ids_vendor=() 635a436f0cSMichal Berger pci_bus_ids_device=() 645f61a0c9SMichal Berger pci_bus_driver=() 659b3773dbSMichal Berger pci_mod_driver=() 669b3773dbSMichal Berger pci_mod_resolved=() 67c5c065e9SMichal Berger pci_iommu_groups=() 68c5c065e9SMichal Berger iommu_groups=() 6936e573fcSMichal Berger} 7036e573fcSMichal Berger 7136e573fcSMichal Bergercache_pci() { 729b3773dbSMichal Berger local pci=$1 class=$2 vendor=$3 device=$4 driver=$5 mod=$6 7336e573fcSMichal Berger 7436e573fcSMichal Berger if [[ -n $class ]]; then 75844c8ec3SMichal Berger class=0x${class/0x/} 7636e573fcSMichal Berger pci_bus_cache["$class"]="${pci_bus_cache["$class"]:+${pci_bus_cache["$class"]} }$pci" 7736e573fcSMichal Berger fi 7836e573fcSMichal Berger if [[ -n $vendor && -n $device ]]; then 79844c8ec3SMichal Berger vendor=0x${vendor/0x/} device=0x${device/0x/} 8036e573fcSMichal Berger pci_bus_cache["$vendor:$device"]="${pci_bus_cache["$vendor:$device"]:+${pci_bus_cache["$vendor:$device"]} }$pci" 815a436f0cSMichal Berger 825a436f0cSMichal Berger pci_ids_vendor["$pci"]=$vendor 835a436f0cSMichal Berger pci_ids_device["$pci"]=$device 8436e573fcSMichal Berger fi 855f61a0c9SMichal Berger if [[ -n $driver ]]; then 865f61a0c9SMichal Berger pci_bus_driver["$pci"]=$driver 875f61a0c9SMichal Berger fi 889b3773dbSMichal Berger if [[ -n $mod ]]; then 899b3773dbSMichal Berger pci_mod_driver["$pci"]=$mod 909b3773dbSMichal Berger pci_mod_resolved["$pci"]=$(resolve_mod "$mod") 919b3773dbSMichal Berger fi 92c5c065e9SMichal Berger 93c5c065e9SMichal Berger cache_pci_iommu_group "$pci" 94c5c065e9SMichal Berger} 95c5c065e9SMichal Berger 96c5c065e9SMichal Bergercache_iommu_group() { 97c5c065e9SMichal Berger local iommu_group=$1 pcis=() pci 98c5c065e9SMichal Berger 99c5c065e9SMichal Berger [[ -e /sys/kernel/iommu_groups/$iommu_group/type ]] || return 0 100c5c065e9SMichal Berger 101c5c065e9SMichal Berger local -n _iommu_group_ref=_iommu_group_$iommu_group 102c5c065e9SMichal Berger 103c5c065e9SMichal Berger iommu_groups[iommu_group]="_iommu_group_${iommu_group}[@]" 104c5c065e9SMichal Berger 105c5c065e9SMichal Berger for pci in "/sys/kernel/iommu_groups/$iommu_group/devices/"*; do 106c5c065e9SMichal Berger pci=${pci##*/} 107c5c065e9SMichal Berger [[ -n ${pci_iommu_groups["$pci"]} ]] && continue 108c5c065e9SMichal Berger pci_iommu_groups["$pci"]=$iommu_group 109c5c065e9SMichal Berger _iommu_group_ref+=("$pci") 110c5c065e9SMichal Berger done 111c5c065e9SMichal Berger 112c5c065e9SMichal Berger} 113c5c065e9SMichal Berger 114c5c065e9SMichal Bergercache_pci_iommu_group() { 115c5c065e9SMichal Berger local pci=$1 iommu_group 116c5c065e9SMichal Berger 117c5c065e9SMichal Berger [[ -e /sys/bus/pci/devices/$pci/iommu_group ]] || return 0 118c5c065e9SMichal Berger 119c5c065e9SMichal Berger iommu_group=$(readlink -f "/sys/bus/pci/devices/$pci/iommu_group") 120c5c065e9SMichal Berger iommu_group=${iommu_group##*/} 121c5c065e9SMichal Berger 122c5c065e9SMichal Berger cache_iommu_group "$iommu_group" 12336e573fcSMichal Berger} 12436e573fcSMichal Berger 1253ac0a6edSMichal Bergeris_iommu_enabled() { 1263ac0a6edSMichal Berger [[ -e /sys/kernel/iommu_groups/0 ]] && return 0 1273ac0a6edSMichal Berger [[ -e /sys/module/vfio/parameters/enable_unsafe_noiommu_mode ]] || return 1 1283ac0a6edSMichal Berger [[ $(< /sys/module/vfio/parameters/enable_unsafe_noiommu_mode) == Y ]] 1293ac0a6edSMichal Berger} 1303ac0a6edSMichal Berger 13136e573fcSMichal Bergercache_pci_bus_sysfs() { 13236e573fcSMichal Berger [[ -e /sys/bus/pci/devices ]] || return 1 13336e573fcSMichal Berger 13436e573fcSMichal Berger cache_pci_init || return 0 13536e573fcSMichal Berger 13636e573fcSMichal Berger local pci 1379b3773dbSMichal Berger local class vendor device driver mod 13836e573fcSMichal Berger 13936e573fcSMichal Berger for pci in /sys/bus/pci/devices/*; do 1409b3773dbSMichal Berger class=$(< "$pci/class") vendor=$(< "$pci/vendor") device=$(< "$pci/device") driver="" mod="" 1419ad576c6SMichal Berger driver=$(get_pci_driver_sysfs "${pci##*/}") 1429b3773dbSMichal Berger if [[ -e $pci/modalias ]]; then 1439b3773dbSMichal Berger mod=$(< "$pci/modalias") 1449b3773dbSMichal Berger fi 1459b3773dbSMichal Berger cache_pci "${pci##*/}" "$class" "$vendor" "$device" "$driver" "$mod" 14636e573fcSMichal Berger done 14736e573fcSMichal Berger} 14836e573fcSMichal Berger 14936e573fcSMichal Bergercache_pci_bus_lspci() { 15036e573fcSMichal Berger hash lspci 2> /dev/null || return 1 15136e573fcSMichal Berger 15236e573fcSMichal Berger cache_pci_init || return 0 15336e573fcSMichal Berger 15436e573fcSMichal Berger local dev 15536e573fcSMichal Berger while read -ra dev; do 15636e573fcSMichal Berger dev=("${dev[@]//\"/}") 15736e573fcSMichal Berger # lspci splits ls byte of the class (prog. interface) into a separate 15836e573fcSMichal Berger # field if it's != 0. Look for it and normalize the value to fit with 15936e573fcSMichal Berger # what kernel exposes under sysfs. 16036e573fcSMichal Berger if [[ ${dev[*]} =~ -p([0-9]+) ]]; then 16136e573fcSMichal Berger dev[1]+=${BASH_REMATCH[1]} 16236e573fcSMichal Berger else 16336e573fcSMichal Berger dev[1]+=00 16436e573fcSMichal Berger fi 1659ad576c6SMichal Berger # pci class vendor device driver 1669ad576c6SMichal Berger # lspci supports driver listing only under Linux, however, it's not 1679ad576c6SMichal Berger # included when specific display mode (i.e. -mm) is in use, even if 1689ad576c6SMichal Berger # extra -k is slapped on the cmdline. So with that in mind, just 1699ad576c6SMichal Berger # get that info from sysfs. 1709ad576c6SMichal Berger cache_pci "${dev[@]::4}" "$(get_pci_driver_sysfs "${dev[0]}")" 17136e573fcSMichal Berger done < <(lspci -Dnmm) 17236e573fcSMichal Berger} 17336e573fcSMichal Berger 17436e573fcSMichal Bergercache_pci_bus_pciconf() { 17536e573fcSMichal Berger hash pciconf 2> /dev/null || return 1 17636e573fcSMichal Berger 17736e573fcSMichal Berger cache_pci_init || return 0 17836e573fcSMichal Berger 1797201d0e6SMichal Berger local class vendor device 1807201d0e6SMichal Berger local pci pci_info 1817201d0e6SMichal Berger local chip driver 18236e573fcSMichal Berger 1837201d0e6SMichal Berger while read -r pci pci_info; do 1847201d0e6SMichal Berger driver=${pci%@*} 1852635e73dSMichal Berger pci=${pci#*:} pci=${pci%:} # E.g.: nvme0@pci0:0:16:0: -> 0:16:0 1867201d0e6SMichal Berger source <(echo "$pci_info") 1877201d0e6SMichal Berger # pciconf under FreeBSD 13.1 provides vendor and device IDs in its 1887201d0e6SMichal Berger # output under separate, dedicated fields. For 12.x they need to 1897201d0e6SMichal Berger # be extracted from the chip field. 1907201d0e6SMichal Berger if [[ -n $chip ]]; then 1917201d0e6SMichal Berger vendor=$(printf '0x%04x' $((chip & 0xffff))) 1927201d0e6SMichal Berger device=$(printf '0x%04x' $(((chip >> 16) & 0xffff))) 1937201d0e6SMichal Berger fi 1947201d0e6SMichal Berger cache_pci "$pci" "$class" "$vendor" "$device" "$driver" 19536e573fcSMichal Berger done < <(pciconf -l) 19636e573fcSMichal Berger} 19736e573fcSMichal Berger 1989ad576c6SMichal Bergerget_pci_driver_sysfs() { 1999ad576c6SMichal Berger local pci=/sys/bus/pci/devices/$1 driver 2009ad576c6SMichal Berger 2019ad576c6SMichal Berger if [[ -e $pci/driver ]]; then 2029ad576c6SMichal Berger driver=$(readlink -f "$pci/driver") driver=${driver##*/} 2039ad576c6SMichal Berger fi 2049ad576c6SMichal Berger echo "$driver" 2059ad576c6SMichal Berger} 2069ad576c6SMichal Berger 20736e573fcSMichal Bergercache_pci_bus() { 20836e573fcSMichal Berger case "$(uname -s)" in 20936e573fcSMichal Berger Linux) cache_pci_bus_lspci || cache_pci_bus_sysfs ;; 21036e573fcSMichal Berger FreeBSD) cache_pci_bus_pciconf ;; 21136e573fcSMichal Berger esac 21236e573fcSMichal Berger} 21336e573fcSMichal Berger 21436e573fcSMichal Bergeriter_all_pci_sysfs() { 21536e573fcSMichal Berger cache_pci_bus_sysfs || return 1 21636e573fcSMichal Berger 21736e573fcSMichal Berger # default to class of the nvme devices 21836e573fcSMichal Berger local find=${1:-0x010802} findx=$2 21936e573fcSMichal Berger local pci pcis 22036e573fcSMichal Berger 22136e573fcSMichal Berger [[ -n ${pci_bus_cache["$find"]} ]] || return 0 22236e573fcSMichal Berger read -ra pcis <<< "${pci_bus_cache["$find"]}" 22336e573fcSMichal Berger 22436e573fcSMichal Berger if ((findx)); then 22536e573fcSMichal Berger printf '%s\n' "${pcis[@]::findx}" 22636e573fcSMichal Berger else 22736e573fcSMichal Berger printf '%s\n' "${pcis[@]}" 22836e573fcSMichal Berger fi 22936e573fcSMichal Berger} 23036e573fcSMichal Berger 231a1280c98SJim Harris# This function will ignore PCI PCI_ALLOWED and PCI_BLOCKED 232ad32c7b8SPawel Wodkowskifunction iter_all_pci_class_code() { 233074df1d8SPawel Kaminski local class 234074df1d8SPawel Kaminski local subclass 235074df1d8SPawel Kaminski local progif 236074df1d8SPawel Kaminski class="$(printf %02x $((0x$1)))" 237074df1d8SPawel Kaminski subclass="$(printf %02x $((0x$2)))" 238074df1d8SPawel Kaminski progif="$(printf %02x $((0x$3)))" 239f0c20934SDaniel Verkamp 240f0c20934SDaniel Verkamp if hash lspci &> /dev/null; then 241f0c20934SDaniel Verkamp if [ "$progif" != "00" ]; then 242844c8ec3SMichal Berger lspci -mm -n -D \ 243844c8ec3SMichal Berger | grep -i -- "-p${progif}" \ 244844c8ec3SMichal Berger | awk -v cc="\"${class}${subclass}\"" -F " " \ 245f0c20934SDaniel Verkamp '{if (cc ~ $2) print $1}' | tr -d '"' 246f0c20934SDaniel Verkamp else 247844c8ec3SMichal Berger lspci -mm -n -D \ 248844c8ec3SMichal Berger | awk -v cc="\"${class}${subclass}\"" -F " " \ 249f0c20934SDaniel Verkamp '{if (cc ~ $2) print $1}' | tr -d '"' 250f0c20934SDaniel Verkamp fi 251f0c20934SDaniel Verkamp elif hash pciconf &> /dev/null; then 252844c8ec3SMichal Berger local addr=($(pciconf -l | grep -i "class=0x${class}${subclass}${progif}" \ 253844c8ec3SMichal Berger | cut -d$'\t' -f1 | sed -e 's/^[a-zA-Z0-9_]*@pci//g' | tr ':' ' ')) 2547201d0e6SMichal Berger echo "${addr[0]}:${addr[1]}:${addr[2]}:${addr[3]}" 25536e573fcSMichal Berger elif iter_all_pci_sysfs "$(printf '0x%06x' $((0x$progif | 0x$subclass << 8 | 0x$class << 16)))"; then 25636e573fcSMichal Berger : 257ad32c7b8SPawel Wodkowski else 258f2bfad59SLiu Xiaodong echo "Missing PCI enumeration utility" >&2 259ad32c7b8SPawel Wodkowski exit 1 260ad32c7b8SPawel Wodkowski fi 261ad32c7b8SPawel Wodkowski} 262ad32c7b8SPawel Wodkowski 263a1280c98SJim Harris# This function will ignore PCI PCI_ALLOWED and PCI_BLOCKED 264ad32c7b8SPawel Wodkowskifunction iter_all_pci_dev_id() { 265074df1d8SPawel Kaminski local ven_id 266074df1d8SPawel Kaminski local dev_id 267074df1d8SPawel Kaminski ven_id="$(printf %04x $((0x$1)))" 268074df1d8SPawel Kaminski dev_id="$(printf %04x $((0x$2)))" 269ad32c7b8SPawel Wodkowski 270ad32c7b8SPawel Wodkowski if hash lspci &> /dev/null; then 271ad32c7b8SPawel Wodkowski lspci -mm -n -D | awk -v ven="\"$ven_id\"" -v dev="\"${dev_id}\"" -F " " \ 272ad32c7b8SPawel Wodkowski '{if (ven ~ $3 && dev ~ $4) print $1}' | tr -d '"' 273ad32c7b8SPawel Wodkowski elif hash pciconf &> /dev/null; then 2747201d0e6SMichal Berger local addr=($(pciconf -l | grep -iE "chip=0x${dev_id}${ven_id}|vendor=0x$ven_id device=0x$dev_id" \ 275844c8ec3SMichal Berger | cut -d$'\t' -f1 | sed -e 's/^[a-zA-Z0-9_]*@pci//g' | tr ':' ' ')) 2767201d0e6SMichal Berger echo "${addr[0]}:${addr[1]}:${addr[2]}:${addr[3]}" 27736e573fcSMichal Berger elif iter_all_pci_sysfs "0x$ven_id:0x$dev_id"; then 27836e573fcSMichal Berger : 279f0c20934SDaniel Verkamp else 280f2bfad59SLiu Xiaodong echo "Missing PCI enumeration utility" >&2 281f0c20934SDaniel Verkamp exit 1 282f0c20934SDaniel Verkamp fi 283f0c20934SDaniel Verkamp} 284f0c20934SDaniel Verkamp 285f0c20934SDaniel Verkampfunction iter_pci_dev_id() { 286ad32c7b8SPawel Wodkowski local bdf="" 287f0c20934SDaniel Verkamp 288ad32c7b8SPawel Wodkowski for bdf in $(iter_all_pci_dev_id "$@"); do 289ad32c7b8SPawel Wodkowski if pci_can_use "$bdf"; then 290ad32c7b8SPawel Wodkowski echo "$bdf" 291f0c20934SDaniel Verkamp fi 292ad32c7b8SPawel Wodkowski done 293ad32c7b8SPawel Wodkowski} 294ad32c7b8SPawel Wodkowski 295a1280c98SJim Harris# This function will filter out PCI devices using PCI_ALLOWED and PCI_BLOCKED 296ad32c7b8SPawel Wodkowski# See function pci_can_use() 297ad32c7b8SPawel Wodkowskifunction iter_pci_class_code() { 298ad32c7b8SPawel Wodkowski local bdf="" 299ad32c7b8SPawel Wodkowski 300ad32c7b8SPawel Wodkowski for bdf in $(iter_all_pci_class_code "$@"); do 301ad32c7b8SPawel Wodkowski if pci_can_use "$bdf"; then 302ad32c7b8SPawel Wodkowski echo "$bdf" 303ad32c7b8SPawel Wodkowski fi 304ad32c7b8SPawel Wodkowski done 305f0c20934SDaniel Verkamp} 30635babadeSMichal Berger 30735babadeSMichal Bergerfunction nvme_in_userspace() { 30835babadeSMichal Berger # Check used drivers. If it's not vfio-pci or uio-pci-generic 309a1280c98SJim Harris # then most likely PCI_ALLOWED option was used for setup.sh 31035babadeSMichal Berger # and we do not want to use that disk. 31135babadeSMichal Berger 31235babadeSMichal Berger local bdf bdfs 31335babadeSMichal Berger local nvmes 31435babadeSMichal Berger 31535babadeSMichal Berger if [[ -n ${pci_bus_cache["0x010802"]} ]]; then 31635babadeSMichal Berger nvmes=(${pci_bus_cache["0x010802"]}) 31735babadeSMichal Berger else 31835babadeSMichal Berger nvmes=($(iter_pci_class_code 01 08 02)) 31935babadeSMichal Berger fi 32035babadeSMichal Berger 32135babadeSMichal Berger for bdf in "${nvmes[@]}"; do 32235babadeSMichal Berger if [[ -e /sys/bus/pci/drivers/nvme/$bdf ]] \ 32313d01bedSMichal Berger || [[ $(uname -s) == FreeBSD && $(pciconf -l "pci${bdf/./:}") == nvme* ]]; then 32435babadeSMichal Berger continue 32535babadeSMichal Berger fi 32635babadeSMichal Berger bdfs+=("$bdf") 32735babadeSMichal Berger done 32835babadeSMichal Berger ((${#bdfs[@]})) || return 1 32935babadeSMichal Berger printf '%s\n' "${bdfs[@]}" 33035babadeSMichal Berger} 33177c4d0f6SMichal Berger 33286eadb4dSMichal Bergercmp_versions() { 33377c4d0f6SMichal Berger local ver1 ver1_l 33477c4d0f6SMichal Berger local ver2 ver2_l 33577c4d0f6SMichal Berger 33677c4d0f6SMichal Berger IFS=".-:" read -ra ver1 <<< "$1" 33777c4d0f6SMichal Berger IFS=".-:" read -ra ver2 <<< "$3" 33877c4d0f6SMichal Berger local op=$2 33977c4d0f6SMichal Berger 34077c4d0f6SMichal Berger ver1_l=${#ver1[@]} 34177c4d0f6SMichal Berger ver2_l=${#ver2[@]} 34277c4d0f6SMichal Berger 34377c4d0f6SMichal Berger local lt=0 gt=0 eq=0 v 34477c4d0f6SMichal Berger case "$op" in 34577c4d0f6SMichal Berger "<") : $((eq = gt = 1)) ;; 34677c4d0f6SMichal Berger ">") : $((eq = lt = 1)) ;; 34777c4d0f6SMichal Berger "<=") : $((gt = 1)) ;; 34877c4d0f6SMichal Berger ">=") : $((lt = 1)) ;; 34977c4d0f6SMichal Berger "==") : $((lt = gt = 1)) ;; 35077c4d0f6SMichal Berger esac 35177c4d0f6SMichal Berger 35277c4d0f6SMichal Berger decimal() ( 35377c4d0f6SMichal Berger local d=${1,,} 35477c4d0f6SMichal Berger if [[ $d =~ ^[0-9]+$ ]]; then 35577c4d0f6SMichal Berger echo $((10#$d)) 35677c4d0f6SMichal Berger elif [[ $d =~ ^0x || $d =~ ^[a-f0-9]+$ ]]; then 35777c4d0f6SMichal Berger d=${d/0x/} 35877c4d0f6SMichal Berger echo $((0x$d)) 35977c4d0f6SMichal Berger else 36077c4d0f6SMichal Berger echo 0 36177c4d0f6SMichal Berger fi 36277c4d0f6SMichal Berger ) 36377c4d0f6SMichal Berger 36477c4d0f6SMichal Berger for ((v = 0; v < (ver1_l > ver2_l ? ver1_l : ver2_l); v++)); do 36577c4d0f6SMichal Berger ver1[v]=$(decimal "${ver1[v]}") 36677c4d0f6SMichal Berger ver2[v]=$(decimal "${ver2[v]}") 36777c4d0f6SMichal Berger ((ver1[v] > ver2[v])) && return "$gt" 36877c4d0f6SMichal Berger ((ver1[v] < ver2[v])) && return "$lt" 36977c4d0f6SMichal Berger done 37077c4d0f6SMichal Berger [[ ${ver1[*]} == "${ver2[*]}" ]] && return "$eq" 37177c4d0f6SMichal Berger} 37277c4d0f6SMichal Berger 37386eadb4dSMichal Bergerlt() { cmp_versions "$1" "<" "$2"; } 37486eadb4dSMichal Bergergt() { cmp_versions "$1" ">" "$2"; } 37586eadb4dSMichal Bergerle() { cmp_versions "$1" "<=" "$2"; } 37686eadb4dSMichal Bergerge() { cmp_versions "$1" ">=" "$2"; } 37786eadb4dSMichal Bergereq() { cmp_versions "$1" "==" "$2"; } 37877c4d0f6SMichal Bergerneq() { ! eq "$1" "$2"; } 3795a21edf4SNick Connolly 38076f840c0SMichal Bergerblock_in_use() { 38173517575SMichal Berger local block=$1 pt 38276f840c0SMichal Berger # Skip devices that are in use - simple blkid it to see if 38376f840c0SMichal Berger # there's any metadata (pt, fs, etc.) present on the drive. 38476f840c0SMichal Berger # FIXME: Special case to ignore atari as a potential false 38576f840c0SMichal Berger # positive: 38676f840c0SMichal Berger # https://github.com/spdk/spdk/issues/2079 38776f840c0SMichal Berger # Devices with SPDK's GPT part type are not considered to 38876f840c0SMichal Berger # be in use. 38976f840c0SMichal Berger 39076f840c0SMichal Berger if "$rootdir/scripts/spdk-gpt.py" "$block"; then 39176f840c0SMichal Berger return 1 39276f840c0SMichal Berger fi 39376f840c0SMichal Berger 39473517575SMichal Berger if ! pt=$(blkid -s PTTYPE -o value "/dev/${block##*/}"); then 39576f840c0SMichal Berger return 1 39673517575SMichal Berger elif [[ $pt == atari ]]; then 39776f840c0SMichal Berger return 1 39876f840c0SMichal Berger fi 39976f840c0SMichal Berger 400c733cd68STomasz Zawadzki # Devices used in SPDK tests always create GPT partitions 401c733cd68STomasz Zawadzki # with label containing SPDK_TEST string. Such devices were 402c733cd68STomasz Zawadzki # part of the tests before, so are not considered in use. 403c733cd68STomasz Zawadzki if [[ $pt == gpt ]] && parted "/dev/${block##*/}" -ms print | grep -q "SPDK_TEST"; then 404c733cd68STomasz Zawadzki return 1 405c733cd68STomasz Zawadzki fi 406c733cd68STomasz Zawadzki 40776f840c0SMichal Berger return 0 40876f840c0SMichal Berger} 40976f840c0SMichal Berger 4103a39d90bSJim Harrisget_spdk_gpt_old() { 4113a39d90bSJim Harris local spdk_guid 4123a39d90bSJim Harris 4133a39d90bSJim Harris [[ -e $rootdir/module/bdev/gpt/gpt.h ]] || return 1 4143a39d90bSJim Harris 4153a39d90bSJim Harris GPT_H="$rootdir/module/bdev/gpt/gpt.h" 4163a39d90bSJim Harris IFS="()" read -r _ spdk_guid _ < <(grep -w SPDK_GPT_PART_TYPE_GUID_OLD "$GPT_H") 4173a39d90bSJim Harris spdk_guid=${spdk_guid//, /-} spdk_guid=${spdk_guid//0x/} 4183a39d90bSJim Harris 4193a39d90bSJim Harris echo "$spdk_guid" 4203a39d90bSJim Harris} 4213a39d90bSJim Harris 422b7947268SMichal Bergerget_spdk_gpt() { 423b7947268SMichal Berger local spdk_guid 424b7947268SMichal Berger 425b7947268SMichal Berger [[ -e $rootdir/module/bdev/gpt/gpt.h ]] || return 1 426b7947268SMichal Berger 4273a39d90bSJim Harris GPT_H="$rootdir/module/bdev/gpt/gpt.h" 4283a39d90bSJim Harris IFS="()" read -r _ spdk_guid _ < <(grep -w SPDK_GPT_PART_TYPE_GUID "$GPT_H") 429b7947268SMichal Berger spdk_guid=${spdk_guid//, /-} spdk_guid=${spdk_guid//0x/} 430b7947268SMichal Berger 431b7947268SMichal Berger echo "$spdk_guid" 432b7947268SMichal Berger} 433b7947268SMichal Berger 4344f8177b5SMichal Bergermap_supported_devices() { 4357014f640SMichal Berger local type=${1^^} 4364f8177b5SMichal Berger local ids dev_types dev_type dev_id bdf bdfs vmd _vmd 4374f8177b5SMichal Berger 4384f8177b5SMichal Berger local -gA nvme_d 4394f8177b5SMichal Berger local -gA ioat_d dsa_d iaa_d 4404f8177b5SMichal Berger local -gA virtio_d 4414f8177b5SMichal Berger local -gA vmd_d nvme_vmd_d vmd_nvme_d vmd_nvme_count 4424f8177b5SMichal Berger local -gA all_devices_d types_d all_devices_type_d 4434f8177b5SMichal Berger 4444f8177b5SMichal Berger ids+="PCI_DEVICE_ID_INTEL_IOAT" dev_types+="IOAT" 4454f8177b5SMichal Berger ids+="|PCI_DEVICE_ID_INTEL_DSA" dev_types+="|DSA" 4464f8177b5SMichal Berger ids+="|PCI_DEVICE_ID_INTEL_IAA" dev_types+="|IAA" 4474f8177b5SMichal Berger ids+="|PCI_DEVICE_ID_VIRTIO" dev_types+="|VIRTIO" 4484f8177b5SMichal Berger ids+="|PCI_DEVICE_ID_INTEL_VMD" dev_types+="|VMD" 4494f8177b5SMichal Berger ids+="|SPDK_PCI_CLASS_NVME" dev_types+="|NVME" 4504f8177b5SMichal Berger 4514f8177b5SMichal Berger [[ -e $rootdir/include/spdk/pci_ids.h ]] || return 1 4524f8177b5SMichal Berger 4534f8177b5SMichal Berger ((${#pci_bus_cache[@]} == 0)) && cache_pci_bus 4544f8177b5SMichal Berger 4554f8177b5SMichal Berger while read -r _ dev_type dev_id; do 4567014f640SMichal Berger [[ $dev_type == *$type* ]] || continue 4574f8177b5SMichal Berger bdfs=(${pci_bus_cache["0x8086:$dev_id"]}) 4584f8177b5SMichal Berger [[ $dev_type == *NVME* ]] && bdfs=(${pci_bus_cache["$dev_id"]}) 4594f8177b5SMichal Berger [[ $dev_type == *VIRT* ]] && bdfs=(${pci_bus_cache["0x1af4:$dev_id"]}) 4604f8177b5SMichal Berger [[ $dev_type =~ ($dev_types) ]] && dev_type=${BASH_REMATCH[1],,} 4614f8177b5SMichal Berger types_d["$dev_type"]=1 4624f8177b5SMichal Berger for bdf in "${bdfs[@]}"; do 4634f8177b5SMichal Berger eval "${dev_type}_d[$bdf]=0" 4644f8177b5SMichal Berger all_devices_d["$bdf"]=0 4654f8177b5SMichal Berger all_devices_type_d["$bdf"]=$dev_type 4664f8177b5SMichal Berger done 4674f8177b5SMichal Berger done < <(grep -E "$ids" "$rootdir/include/spdk/pci_ids.h") 4684f8177b5SMichal Berger 4694f8177b5SMichal Berger # Rebuild vmd refs from the very cratch to not have duplicates in case we were called 4704f8177b5SMichal Berger # multiple times. 4714f8177b5SMichal Berger unset -v "${!_vmd_@}" 4724f8177b5SMichal Berger 4734f8177b5SMichal Berger for bdf in "${!nvme_d[@]}"; do 4744f8177b5SMichal Berger vmd=$(is_nvme_behind_vmd "$bdf") && _vmd=${vmd//[:.]/_} || continue 4754f8177b5SMichal Berger nvme_vmd_d["$bdf"]=$vmd 4764f8177b5SMichal Berger vmd_nvme_d["$vmd"]="_vmd_${_vmd}_nvmes[@]" 4774f8177b5SMichal Berger ((++vmd_nvme_count["$vmd"])) 4784f8177b5SMichal Berger eval "_vmd_${_vmd}_nvmes+=($bdf)" 4794f8177b5SMichal Berger done 4804f8177b5SMichal Berger} 4814f8177b5SMichal Berger 4824f8177b5SMichal Bergeris_nvme_behind_vmd() { 4834f8177b5SMichal Berger local nvme_bdf=$1 dev_path 4844f8177b5SMichal Berger 4854f8177b5SMichal Berger IFS="/" read -ra dev_path < <(readlink -f "/sys/bus/pci/devices/$nvme_bdf") 4864f8177b5SMichal Berger 4874f8177b5SMichal Berger for dev in "${dev_path[@]}"; do 4884f8177b5SMichal Berger [[ -n $dev && -n ${vmd_d["$dev"]} ]] && echo $dev && return 0 4894f8177b5SMichal Berger done 4904f8177b5SMichal Berger return 1 4914f8177b5SMichal Berger} 4924f8177b5SMichal Berger 4934f8177b5SMichal Bergeris_nvme_iommu_shared_with_vmd() { 4944f8177b5SMichal Berger local nvme_bdf=$1 vmd 4954f8177b5SMichal Berger 4964f8177b5SMichal Berger # This use-case is quite specific to vfio-pci|iommu setup 4974f8177b5SMichal Berger is_iommu_enabled || return 1 4984f8177b5SMichal Berger 4994f8177b5SMichal Berger [[ -n ${nvme_vmd_d["$nvme_bdf"]} ]] || return 1 5004f8177b5SMichal Berger # nvme is behind VMD ... 5014f8177b5SMichal Berger ((pci_iommu_groups["$nvme_bdf"] == pci_iommu_groups["${nvme_vmd_d["$nvme_bdf"]}"])) || return 1 5024f8177b5SMichal Berger # ... and it shares iommu_group with it 5034f8177b5SMichal Berger} 5044f8177b5SMichal Berger 505443e1ea3SJim Harriskmsg() { 506443e1ea3SJim Harris ((UID == 0)) || return 0 507443e1ea3SJim Harris [[ -w /dev/kmsg && $(< /proc/sys/kernel/printk_devkmsg) == on ]] || return 0 508443e1ea3SJim Harris echo "$*" > /dev/kmsg 509443e1ea3SJim Harris} 510443e1ea3SJim Harris 511*cb7af50cSMichal Bergerfunction get_block_dev_from_bdf() { 512*cb7af50cSMichal Berger local bdf=$1 513*cb7af50cSMichal Berger local block blocks=() ctrl sub 514*cb7af50cSMichal Berger 515*cb7af50cSMichal Berger for block in /sys/block/!(nvme*); do 516*cb7af50cSMichal Berger if [[ $(readlink -f "$block/device") == *"/$bdf/"* ]]; then 517*cb7af50cSMichal Berger blocks+=("${block##*/}") 518*cb7af50cSMichal Berger fi 519*cb7af50cSMichal Berger done 520*cb7af50cSMichal Berger 521*cb7af50cSMichal Berger blocks+=($(get_block_dev_from_nvme "$bdf")) 522*cb7af50cSMichal Berger 523*cb7af50cSMichal Berger printf '%s\n' "${blocks[@]}" 524*cb7af50cSMichal Berger} 525*cb7af50cSMichal Berger 526*cb7af50cSMichal Bergerfunction get_block_dev_from_nvme() { 527*cb7af50cSMichal Berger local bdf=$1 block ctrl sub 528*cb7af50cSMichal Berger 529*cb7af50cSMichal Berger for ctrl in /sys/class/nvme/nvme*; do 530*cb7af50cSMichal Berger [[ -e $ctrl/address && $(< "$ctrl/address") == "$bdf" ]] || continue 531*cb7af50cSMichal Berger sub=$(< "$ctrl/subsysnqn") && break 532*cb7af50cSMichal Berger done 533*cb7af50cSMichal Berger 534*cb7af50cSMichal Berger [[ -n $sub ]] || return 0 535*cb7af50cSMichal Berger 536*cb7af50cSMichal Berger for block in /sys/block/nvme*; do 537*cb7af50cSMichal Berger [[ -e $block/hidden && $(< "$block/hidden") == 1 ]] && continue 538*cb7af50cSMichal Berger if [[ -e $block/device/subsysnqn && $(< "$block/device/subsysnqn") == "$sub" ]]; then 539*cb7af50cSMichal Berger echo "${block##*/}" 540*cb7af50cSMichal Berger fi 541*cb7af50cSMichal Berger done 542*cb7af50cSMichal Berger} 543*cb7af50cSMichal Berger 5445a21edf4SNick Connollyif [[ -e "$CONFIG_WPDK_DIR/bin/wpdk_common.sh" ]]; then 5455a21edf4SNick Connolly # Adjust uname to report the operating system as WSL, Msys or Cygwin 5465a21edf4SNick Connolly # and the kernel name as Windows. Define kill() to invoke the SIGTERM 5475a21edf4SNick Connolly # handler before causing a hard stop with TerminateProcess. 5485a21edf4SNick Connolly source "$CONFIG_WPDK_DIR/bin/wpdk_common.sh" 5495a21edf4SNick Connollyfi 5501e46e023SMaciej Mis 5511e46e023SMaciej Mis# Make sure we have access to proper binaries installed in pkgdep/common.sh 5521e46e023SMaciej Misif [[ -e /etc/opt/spdk-pkgdep/paths/export.sh ]]; then 5531e46e023SMaciej Mis source /etc/opt/spdk-pkgdep/paths/export.sh 5541e46e023SMaciej Misfi > /dev/null 555