test/vhost: Add helper functions for extracting IRQ data
Signed-off-by: Michal Berger <michal.berger@intel.com> Change-Id: If75aeca0c44667ef02b72f2e4a9141da4057d291 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/15459 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Karol Latecki <karol.latecki@intel.com> Reviewed-by: Shuhei Matsumoto <smatsumoto@nvidia.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Kamil Godzwon <kamilx.godzwon@intel.com>
This commit is contained in:
parent
78df9be449
commit
f8a085a2d5
257
test/vhost/irqs.sh
Normal file
257
test/vhost/irqs.sh
Normal file
@ -0,0 +1,257 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (C) 2022 Intel Corporation.
|
||||
# All rights reserved.
|
||||
|
||||
source "$rootdir/test/scheduler/common.sh"
|
||||
|
||||
declare -a irqs_counters=()
|
||||
declare -a irqs_devices=()
|
||||
declare -a irqs_types=()
|
||||
declare -a cpus=()
|
||||
|
||||
_get_cpus() {
|
||||
local state=${1:-online}
|
||||
|
||||
_get_override_cpus || "_get_${state}_cpus"
|
||||
}
|
||||
|
||||
_get_override_cpus() {
|
||||
((${#cpus_override[@]} > 0)) || return 1
|
||||
fold_list_onto_array cpus "${cpus_override[@]}"
|
||||
}
|
||||
|
||||
_get_online_cpus() {
|
||||
fold_list_onto_array cpus $(get_online_cpus)
|
||||
}
|
||||
|
||||
_get_offline_cpus() {
|
||||
fold_list_onto_array cpus $(get_offline_cpus)
|
||||
}
|
||||
|
||||
get_all_irqs() {
|
||||
local irqs=() s_irqs=()
|
||||
|
||||
irqs=(/proc/irq/+([0-9]))
|
||||
irqs=("${irqs[@]##*/}")
|
||||
|
||||
# Sort it
|
||||
fold_list_onto_array s_irqs "${irqs[@]}"
|
||||
|
||||
printf '%u\n' "${s_irqs[@]}"
|
||||
}
|
||||
|
||||
check_this_irq() {
|
||||
local irq=${1:-0}
|
||||
|
||||
((${#irqs_to_lookup[@]} > 0)) || return 0
|
||||
|
||||
[[ -n ${irqs_to_lookup[irq]} ]]
|
||||
}
|
||||
|
||||
update_irqs_sysfs() {
|
||||
local sysroot=${1:-}
|
||||
local input=$sysroot/sys/kernel/irq
|
||||
|
||||
[[ -e $input ]] || return 1
|
||||
|
||||
# per_cpu_count holds a list of all cpus, regardless of their state
|
||||
_get_cpus online
|
||||
_get_cpus offline
|
||||
|
||||
local irq_path
|
||||
for irq_path in "$input/"*; do
|
||||
irq=${irq_path##*/}
|
||||
check_this_irq "$irq" || continue
|
||||
IFS="," read -ra cpu_counters < "$irq_path/per_cpu_count"
|
||||
for cpu in "${cpus[@]}"; do
|
||||
eval "_irq${irq}_cpu${cpu}+=(${cpu_counters[cpu]})"
|
||||
eval "_irq${irq}_counter[cpu]=_irq${irq}_cpu${cpu}[@]"
|
||||
done
|
||||
irqs_counters[irq]="_irq${irq}_counter[@]"
|
||||
irqs_devices[irq]=$(< "$irq_path/actions")
|
||||
irqs_types[irq]="$(< "$irq_path/chip_name") $(< "$irq_path/hwirq")-$(< "$irq_path/name")"
|
||||
done
|
||||
}
|
||||
|
||||
update_irqs_procfs() {
|
||||
local input=${1:-/proc/interrupts}
|
||||
|
||||
[[ -e $input ]] || return 1
|
||||
|
||||
# /proc/interrupts shows only online CPUs. Use get_cpus() to get readings for
|
||||
# proper CPUs rather than parsing the actual header of the file.
|
||||
_get_cpus online
|
||||
|
||||
local counter_idx
|
||||
while read -ra irqs; do
|
||||
irq=${irqs[0]%:*}
|
||||
[[ $irq == +([0-9]) ]] || continue
|
||||
check_this_irq "$irq" || continue
|
||||
cpu_counters=("${irqs[@]:1:${#cpus[@]}}") counter_idx=0
|
||||
for cpu in "${cpus[@]}"; do
|
||||
eval "_irq${irq}_cpu${cpu}+=(${cpu_counters[counter_idx++]})"
|
||||
eval "_irq${irq}_counter[cpu]=_irq${irq}_cpu${cpu}[@]"
|
||||
done
|
||||
irqs_counters[irq]="_irq${irq}_counter[@]"
|
||||
irqs_devices[irq]=${irqs[*]:${#cpus[@]}+1:2}
|
||||
irqs_types[irq]=${irqs[*]:${#cpus[@]}+3}
|
||||
done < "$input"
|
||||
}
|
||||
|
||||
update_irqs() {
|
||||
local irqs irq
|
||||
local cpu cpu_counters=()
|
||||
local irqs_to_lookup=()
|
||||
|
||||
fold_list_onto_array irqs_to_lookup "$@"
|
||||
|
||||
update_irqs_sysfs || update_irqs_procfs
|
||||
}
|
||||
|
||||
get_irqs() {
|
||||
local irqs=("$@") irq cpu
|
||||
local _counters counters counter delta total
|
||||
|
||||
# If cpus[@] are not init, update was not run so nothing to check
|
||||
((${#cpus[@]} > 0)) || return 1
|
||||
|
||||
if ((${#irqs[@]} == 0)); then
|
||||
irqs=($(get_all_irqs))
|
||||
fi
|
||||
|
||||
for irq in "${irqs[@]}"; do
|
||||
for cpu in "${cpus[@]}"; do
|
||||
[[ -v "_irq${irq}_cpu${cpu}[@]" ]] || continue
|
||||
local -n counters="_irq${irq}_cpu${cpu}"
|
||||
# keep a separate copy to not touch the main _irq*[]
|
||||
_counters=("${counters[@]}") total=0
|
||||
|
||||
if ((${#counters[@]} > 1)); then
|
||||
# Enhance output with calculating deltas between each reading
|
||||
for ((counter = 0; counter < ${#counters[@]} - 1; counter++)); do
|
||||
delta=$((counters[counter + 1] - counters[counter]))
|
||||
_counters[counter + 1]="${counters[counter + 1]} (+$delta)"
|
||||
: $((total += delta))
|
||||
done
|
||||
fi
|
||||
_counters+=("==$total")
|
||||
# Ignore idle irqs unless request from the env tells otherwise
|
||||
if [[ -n $SHOW_ALL_IRQS ]] || ((total > 0)); then
|
||||
echo "irq$irq->$(get_irq_type "$irq")->$(get_irq_device "$irq")@cpu$cpu:"
|
||||
printf ' %s\n' "${_counters[@]}"
|
||||
fi
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
get_irq_type() {
|
||||
[[ -n ${irqs_types[$1]} ]] || return 1
|
||||
echo "${irqs_types[$1]}"
|
||||
}
|
||||
|
||||
get_irq_device() {
|
||||
[[ -n ${irqs_devices[$1]} ]] || return 1
|
||||
echo "${irqs_devices[$1]}"
|
||||
}
|
||||
|
||||
reset_irqs() {
|
||||
irqs_counters=() irqs_devices=() irqs_types=() cpus=()
|
||||
|
||||
unset -v "${!_irq@}"
|
||||
}
|
||||
|
||||
read_irq_cpu_mask() {
|
||||
local irq=$1 mask=$2
|
||||
|
||||
[[ -n $irq && -e /proc/irq/$irq || -n $mask ]] || return 1
|
||||
|
||||
# smp_affinity holds a string of comma-separated 32-bit values. Iterate
|
||||
# over each dWORD and extract cpus bit by bit. Iterate from the end of
|
||||
# the array as that's where the first dWORD is located.
|
||||
local smp_affinity
|
||||
local bit dword dword_l=32 dword_idx
|
||||
local cpus=()
|
||||
|
||||
if [[ -n $mask ]]; then
|
||||
IFS="," read -ra smp_affinity <<< "$mask"
|
||||
else
|
||||
IFS="," read -ra smp_affinity < "/proc/irq/$irq/smp_affinity"
|
||||
fi
|
||||
|
||||
smp_affinity=("${smp_affinity[@]/#/0x}")
|
||||
|
||||
for ((dword = ${#smp_affinity[@]} - 1, dword_idx = 0; dword >= 0; dword--, dword_idx++)); do
|
||||
bit=-1
|
||||
while ((++bit < dword_l)); do
|
||||
if ((smp_affinity[dword] & 1 << bit)); then
|
||||
cpus[bit + dword_l * dword_idx]=$bit
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
printf '%u\n' "${!cpus[@]}"
|
||||
}
|
||||
|
||||
read_irq_cpu_list() {
|
||||
local irq=$1 effective=${2:-0}
|
||||
|
||||
[[ -n $irq && -e /proc/irq/$irq ]] || return 1
|
||||
|
||||
if ((effective)); then
|
||||
parse_cpu_list "/proc/irq/$irq/effective_affinity_list"
|
||||
else
|
||||
parse_cpu_list "/proc/irq/$irq/smp_affinity_list"
|
||||
fi
|
||||
}
|
||||
|
||||
build_irq_cpu_mask() {
|
||||
local cpu dword_l=32 dword_idx dword idxs
|
||||
local _mask=() mask=""
|
||||
|
||||
for cpu; do
|
||||
dword_idx=$((cpu / dword_l))
|
||||
((_mask[dword_idx] |= 1 << (cpu - dword_l * dword_idx)))
|
||||
done
|
||||
|
||||
# Store sorted list of dword indexes that we got
|
||||
idxs=("${!_mask[@]}")
|
||||
|
||||
# Fill out all dWORDs starting from the highest (last) dword index
|
||||
for ((dword = idxs[-1]; dword >= 0; dword--)); do
|
||||
_mask[dword]=$(printf '%08x' "${_mask[dword]}")
|
||||
mask=${mask:+$mask,}${_mask[dword]}
|
||||
done
|
||||
|
||||
echo "$mask"
|
||||
}
|
||||
|
||||
squash_irq_cpu_mask() {
|
||||
local mask
|
||||
|
||||
mask=$(build_irq_cpu_mask "$@")
|
||||
# E.g.: 1,32,64,65,77,88,127 -> 0x80000000010020030000000100000002
|
||||
# Valid under DPDK
|
||||
echo "0x${mask//,/}"
|
||||
}
|
||||
|
||||
unsquash_irq_cpu_mask() {
|
||||
# E.g.: 0x80000000010020030000000100000002 -> 80000000,01002003,00000001,00000002
|
||||
# 8 is a max number of chars in a dWORD represented in hex.
|
||||
|
||||
local smask=$1 _smask="" smask_l _smask_l
|
||||
|
||||
smask=${smask/0x/} smask_l=$((${#smask} / 8)) _smask_l=$smask_l
|
||||
|
||||
((smask_l == 0)) && echo "$smask" && return 0
|
||||
|
||||
# Put comma at a right index
|
||||
while ((_smask_l)); do
|
||||
_smask+=,${smask:${#smask}-_smask_l--*8:8}
|
||||
done
|
||||
|
||||
# Add remaining chars if any
|
||||
_smask=${smask::${#smask}-8*smask_l}${_smask}
|
||||
|
||||
# If there were no chars left, drop the ',' from the beginning of the string
|
||||
echo "${_smask#,}"
|
||||
}
|
Loading…
Reference in New Issue
Block a user