384 lines
12 KiB
Bash
384 lines
12 KiB
Bash
#!/bin/bash
|
|
################################################################################
|
|
# Copyright (c) 2013-2015 Wind River Systems, Inc.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
################################################################################
|
|
|
|
source /etc/platform/platform.conf
|
|
|
|
################################################################################
|
|
# Utility function to expand a sequence of numbers (e.g., 0-7,16-23)
|
|
################################################################################
|
|
function expand_sequence {
|
|
SEQUENCE=(${1//,/ })
|
|
DELIMITER=${2:-","}
|
|
|
|
LIST=
|
|
for entry in ${SEQUENCE[@]}; do
|
|
range=(${entry/-/ })
|
|
a=${range[0]}
|
|
b=${range[1]:-${range[0]}}
|
|
|
|
for i in $(seq $a $b); do
|
|
LIST="${LIST}${DELIMITER}${i}"
|
|
done
|
|
done
|
|
echo ${LIST:1}
|
|
}
|
|
|
|
################################################################################
|
|
# Append a string to comma separated list string
|
|
################################################################################
|
|
function append_list {
|
|
local PUSH=$1
|
|
local LIST=$2
|
|
if [ -z "${LIST}" ]; then
|
|
LIST=${PUSH}
|
|
else
|
|
LIST="${LIST},${PUSH}"
|
|
fi
|
|
echo ${LIST}
|
|
return 0
|
|
}
|
|
|
|
################################################################################
|
|
# Condense a sequence of numbers to a list of ranges (e.g, 7-12,15-16)
|
|
################################################################################
|
|
function condense_sequence {
|
|
local arr=( $(printf '%s\n' "$@" | sort -n) )
|
|
local first
|
|
local last
|
|
local cpulist=""
|
|
for ((i=0; i < ${#arr[@]}; i++)); do
|
|
num=${arr[$i]}
|
|
if [[ -z $first ]]; then
|
|
first=$num
|
|
last=$num
|
|
continue
|
|
fi
|
|
if [[ num -ne $((last + 1)) ]]; then
|
|
if [[ first -eq last ]]; then
|
|
cpulist=$(append_list ${first} ${cpulist})
|
|
else
|
|
cpulist=$(append_list "${first}-${last}" ${cpulist})
|
|
fi
|
|
first=$num
|
|
last=$num
|
|
else
|
|
: $((last++))
|
|
fi
|
|
done
|
|
if [[ first -eq last ]]; then
|
|
cpulist=$(append_list ${first} ${cpulist})
|
|
else
|
|
cpulist=$(append_list "${first}-${last}" ${cpulist})
|
|
fi
|
|
echo "$cpulist"
|
|
}
|
|
|
|
################################################################################
|
|
# Converts a CPULIST (e.g., 0-7,16-23) to a CPUMAP (e.g., 0x00FF00FF). The
|
|
# CPU map is returned as a string representation of a large hexidecimal
|
|
# number but without the leading "0x" characters.
|
|
#
|
|
################################################################################
|
|
function cpulist_to_cpumap {
|
|
local CPULIST=$1
|
|
local NR_CPUS=$2
|
|
local CPUMAP=0
|
|
local CPUID=0
|
|
if [ -z "${NR_CPUS}" ] || [ ${NR_CPUS} -eq 0 ]; then
|
|
echo 0
|
|
return 0
|
|
fi
|
|
for CPUID in $(expand_sequence $CPULIST " "); do
|
|
if [ "${CPUID}" -lt "${NR_CPUS}" ]; then
|
|
CPUMAP=$(echo "${CPUMAP} + (2^${CPUID})" | bc -l)
|
|
fi
|
|
done
|
|
|
|
echo "obase=16;ibase=10;${CPUMAP}" | bc -l
|
|
return 0
|
|
}
|
|
|
|
################################################################################
|
|
# Converts a CPUMAP (e.g., 0x00FF00FF) to a CPULIST (e.g., 0-7,16-23). The
|
|
# CPUMAP is expected in hexidecimal (base=10) form without the leading "0x"
|
|
# characters.
|
|
#
|
|
################################################################################
|
|
function cpumap_to_cpulist {
|
|
local CPUMAP
|
|
CPUMAP=$(echo "obase=10;ibase=16;$1" | bc -l)
|
|
local NR_CPUS=$2
|
|
local list=()
|
|
local cpulist=""
|
|
for((i=0; i < NR_CPUS; i++))
|
|
do
|
|
## Since 'bc' does not support any bitwise operators this expression:
|
|
## if (CPUMAP & (1 << CPUID))
|
|
## has to be rewritten like this:
|
|
## if (CPUMAP % (2**(CPUID+1)) > ((2**(CPUID)) - 1))
|
|
##
|
|
ISSET=$(echo "scale=0; (${CPUMAP} % 2^(${i}+1)) > (2^${i})-1" | bc -l)
|
|
if [ "${ISSET}" -ne 0 ]; then
|
|
list+=($i)
|
|
fi
|
|
done
|
|
cpulist=$(condense_sequence ${list[@]} )
|
|
echo "$cpulist"
|
|
return 0
|
|
}
|
|
|
|
################################################################################
|
|
# Bitwise NOT of a hexidecimal representation of a CPULIST. The value is
|
|
# returned as a hexidecimal value but without the leading "0x" characters
|
|
#
|
|
################################################################################
|
|
function invert_cpumap {
|
|
local CPUMAP
|
|
CPUMAP=$(echo "obase=10;ibase=16;$1" | bc -l)
|
|
local NR_CPUS=$2
|
|
local INVERSE_CPUMAP=0
|
|
|
|
for CPUID in $(seq 0 $((NR_CPUS - 1))); do
|
|
## See comment in previous function
|
|
ISSET=$(echo "scale=0; (${CPUMAP} % 2^(${CPUID}+1)) > (2^${CPUID})-1" | bc -l)
|
|
if [ "${ISSET}" -eq 1 ]; then
|
|
continue
|
|
fi
|
|
|
|
INVERSE_CPUMAP=$(echo "${INVERSE_CPUMAP} + (2^${CPUID})" | bc -l)
|
|
done
|
|
|
|
echo "obase=16;ibase=10;${INVERSE_CPUMAP}" | bc -l
|
|
return 0
|
|
}
|
|
|
|
################################################################################
|
|
# Builds the complement representation of a CPULIST
|
|
#
|
|
################################################################################
|
|
function invert_cpulist {
|
|
local CPULIST=$1
|
|
local NR_CPUS=$2
|
|
local CPUMAP
|
|
CPUMAP=$(cpulist_to_cpumap ${CPULIST} ${NR_CPUS})
|
|
cpumap_to_cpulist $(invert_cpumap ${CPUMAP} ${NR_CPUS}) ${NR_CPUS}
|
|
return 0
|
|
}
|
|
|
|
################################################################################
|
|
# in_list() - check whether item is contained in list
|
|
# param: item
|
|
# param: list (i.e. 0-3,8-11)
|
|
# returns: 0 - item is contained in list;
|
|
# 1 - item is not contained in list
|
|
#
|
|
################################################################################
|
|
function in_list {
|
|
local item="$1"
|
|
local list="$2"
|
|
|
|
# expand list format 0-3,8-11 to a full sequence {0..3} {8..11}
|
|
local exp_list
|
|
exp_list=$(echo ${list} | \
|
|
sed -e 's#,# #g' -e 's#\([0-9]*\)-\([0-9]*\)#{\1\.\.\2}#g')
|
|
|
|
local e
|
|
for e in $(eval echo ${exp_list}); do
|
|
[[ "$e" == "$item" ]] && return 0
|
|
done
|
|
return 1
|
|
}
|
|
|
|
################################################################################
|
|
# any_in_list() - check if any item of sublist is contained in list
|
|
# param: sublist
|
|
# param: list
|
|
# returns: 0 - an item of sublist is contained in list;
|
|
# 1 - no sublist items contained in list
|
|
#
|
|
################################################################################
|
|
function any_in_list {
|
|
local sublist="$1"
|
|
local list="$2"
|
|
local e
|
|
local exp_list
|
|
|
|
# expand list format 0-3,8-11 to a full sequence {0..3} {8..11}
|
|
exp_list=$(echo ${list} | \
|
|
sed -e 's#,# #g' -e 's#\([0-9]*\)-\([0-9]*\)#{\1\.\.\2}#g')
|
|
declare -A a_list
|
|
for e in $(eval echo ${exp_list}); do
|
|
a_list[$e]=1
|
|
done
|
|
|
|
# expand list format 0-3,8-11 to a full sequence {0..3} {8..11}
|
|
exp_list=$(echo ${sublist} | \
|
|
sed -e 's#,# #g' -e 's#\([0-9]*\)-\([0-9]*\)#{\1\.\.\2}#g')
|
|
declare -A a_sublist
|
|
for e in $(eval echo ${exp_list}); do
|
|
a_sublist[$e]=1
|
|
done
|
|
|
|
# Check if any element of sublist is in list
|
|
for e in "${!a_sublist[@]}"; do
|
|
if [[ "${a_list[$e]}" == 1 ]]; then
|
|
return 0 # matches
|
|
fi
|
|
done
|
|
return 1 # no match
|
|
}
|
|
|
|
################################################################################
|
|
# Return list of CPUs reserved for platform
|
|
################################################################################
|
|
function get_platform_cpu_list {
|
|
## Define platform cpulist based on engineering a number of cores and
|
|
## whether this is a combo or not, and include SMT siblings.
|
|
if [[ $subfunction = *compute* ]]; then
|
|
RESERVE_CONF="/etc/nova/compute_reserved.conf"
|
|
[[ -e ${RESERVE_CONF} ]] && source ${RESERVE_CONF}
|
|
if [ -n "$PLATFORM_CPU_LIST" ];then
|
|
echo "$PLATFORM_CPU_LIST"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
local PLATFORM_SOCKET=0
|
|
local PLATFORM_START=0
|
|
local PLATFORM_CORES=1
|
|
if [ "$nodetype" = "controller" ]; then
|
|
PLATFORM_CORES=$(($PLATFORM_CORES+1))
|
|
fi
|
|
local PLATFORM_CPULIST
|
|
PLATFORM_CPULIST=$(topology_to_cpulist ${PLATFORM_SOCKET} ${PLATFORM_START} ${PLATFORM_CORES})
|
|
echo ${PLATFORM_CPULIST}
|
|
}
|
|
|
|
################################################################################
|
|
# Return list of CPUs reserved for vswitch
|
|
################################################################################
|
|
function get_vswitch_cpu_list {
|
|
## Define default avp cpulist based on engineered number of platform cores,
|
|
## engineered avp cores, and include SMT siblings.
|
|
if [[ $subfunction = *compute* ]]; then
|
|
VSWITCH_CONF="/etc/vswitch/vswitch.conf"
|
|
[[ -e ${VSWITCH_CONF} ]] && source ${VSWITCH_CONF}
|
|
if [ -n "$VSWITCH_CPU_LIST" ];then
|
|
echo "$VSWITCH_CPU_LIST"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
local N_CORES_IN_PKG
|
|
N_CORES_IN_PKG=$(cat /proc/cpuinfo 2>/dev/null | \
|
|
awk '/^cpu cores/ {n = $4} END { print (n>0) ? n : 1 }')
|
|
# engineer platform cores
|
|
local PLATFORM_CORES=1
|
|
if [ "$nodetype" = "controller" ]; then
|
|
PLATFORM_CORES=$(($PLATFORM_CORES+1))
|
|
fi
|
|
|
|
# engineer AVP cores
|
|
local AVP_SOCKET=0
|
|
local AVP_START=${PLATFORM_CORES}
|
|
local AVP_CORES=1
|
|
if [ ${N_CORES_IN_PKG} -gt 4 ]; then
|
|
AVP_CORES=$(($AVP_CORES+1))
|
|
fi
|
|
local AVP_CPULIST
|
|
AVP_CPULIST=$(topology_to_cpulist ${AVP_SOCKET} ${AVP_START} ${AVP_CORES})
|
|
echo ${AVP_CPULIST}
|
|
}
|
|
|
|
################################################################################
|
|
# vswitch_expanded_cpu_list() - compute the vswitch cpu list, including it's siblings
|
|
################################################################################
|
|
function vswitch_expanded_cpu_list {
|
|
list=$(get_vswitch_cpu_list)
|
|
|
|
# Expand vswitch cpulist
|
|
vswitch_cpulist=$(expand_sequence ${list} " ")
|
|
|
|
cpulist=""
|
|
for e in $vswitch_cpulist; do
|
|
# claim hyperthread siblings if SMT enabled
|
|
SIBLINGS_CPULIST=$(cat /sys/devices/system/cpu/cpu${e}/topology/thread_siblings_list 2>/dev/null)
|
|
siblings_cpulist=$(expand_sequence ${SIBLINGS_CPULIST} " ")
|
|
for s in $siblings_cpulist; do
|
|
in_list ${s} ${cpulist}
|
|
if [ $? -eq 1 ]; then
|
|
cpulist=$(append_list ${s} ${cpulist})
|
|
fi
|
|
done
|
|
done
|
|
|
|
echo "$cpulist"
|
|
return 0
|
|
}
|
|
|
|
################################################################################
|
|
# platform_expanded_cpu_list() - compute the platform cpu list, including it's siblings
|
|
################################################################################
|
|
function platform_expanded_cpu_list {
|
|
list=$(get_platform_cpu_list)
|
|
|
|
# Expand platform cpulist
|
|
platform_cpulist=$(expand_sequence ${list} " ")
|
|
|
|
cpulist=""
|
|
for e in $platform_cpulist; do
|
|
# claim hyperthread siblings if SMT enabled
|
|
SIBLINGS_CPULIST=$(cat /sys/devices/system/cpu/cpu${e}/topology/thread_siblings_list 2>/dev/null)
|
|
siblings_cpulist=$(expand_sequence ${SIBLINGS_CPULIST} " ")
|
|
for s in $siblings_cpulist; do
|
|
in_list ${s} ${cpulist}
|
|
if [ $? -eq 1 ]; then
|
|
cpulist=$(append_list ${s} ${cpulist})
|
|
fi
|
|
done
|
|
done
|
|
|
|
echo "$cpulist"
|
|
return 0
|
|
}
|
|
|
|
################################################################################
|
|
# Return list of CPUs based on cpu topology. Select the socket, starting core
|
|
# within the socket, select number of cores, and SMT siblings.
|
|
################################################################################
|
|
function topology_to_cpulist {
|
|
local SOCKET=$1
|
|
local CORE_START=$2
|
|
local NUM_CORES=$3
|
|
local CPULIST
|
|
CPULIST=$(cat /proc/cpuinfo 2>/dev/null | perl -sne \
|
|
'BEGIN { %T = {}; %H = {}; $L = $P = $C = $S = 0; }
|
|
{
|
|
if (/processor\s+:\s+(\d+)/) { $L = $1; }
|
|
if (/physical id\s+:\s+(\d+)/) { $P = $1; }
|
|
if (/core id\s+:\s+(\d+)/) {
|
|
$C = $1;
|
|
$T{$P}{$C}++;
|
|
$S = $T{$P}{$C};
|
|
$H{$P}{$C}{$S} = $L;
|
|
}
|
|
}
|
|
END {
|
|
@cores = sort { $a <=> $b } keys $T{$socket};
|
|
@sel_cores = splice @cores, $core_start, $num_cores;
|
|
@lcpus = ();
|
|
for $C (@sel_cores) {
|
|
for $S (sort {$a <=> $b } keys %{ $H{$socket}{$C} }) {
|
|
push @lcpus, $H{$socket}{$C}{$S};
|
|
}
|
|
}
|
|
printf "%s\n", join(",", @lcpus);
|
|
}' -- -socket=${SOCKET} -core_start=${CORE_START} -num_cores=${NUM_CORES})
|
|
echo ${CPULIST}
|
|
}
|