#!/bin/sh
# SPDX-License-Identifier: GPL-2.0+
#
# Produce awk statements roughly depicting the system's CPU and cache
# layout. If the required information is not available, produce
# error messages as awk comments. Successful exit regardless.
#
# Usage: kvm-assign-cpus.sh /path/to/sysfs
T="`mktemp -d ${TMPDIR-/tmp}/kvm-assign-cpus.sh.XXXXXX`"
trap 'rm -rf $T' 0 2
sysfsdir=${1-/sys/devices/system/node}
if ! cd "$sysfsdir" > $T/msg 2>&1
then
sed -e 's/^/# /' < $T/msg
exit 0
fi
nodelist="`ls -d node*`"
for i in node*
do
if ! test -d $i/
then
echo "# Not a directory: $sysfsdir/node*"
exit 0
fi
for j in $i/cpu*/cache/index*
do
if ! test -d $j/
then
echo "# Not a directory: $sysfsdir/$j"
exit 0
else
break
fi
done
indexlist="`ls -d $i/cpu* | grep 'cpu[0-9][0-9]*' | head -1 | sed -e 's,^.*$,ls -d &/cache/index*,' | sh | sed -e 's,^.*/,,'`"
break
done
for i in node*/cpu*/cache/index*/shared_cpu_list
do
if ! test -f $i
then
echo "# Not a file: $sysfsdir/$i"
exit 0
else
break
fi
done
firstshared=
for i in $indexlist
do
rm -f $T/cpulist
for n in node*
do
f="$n/cpu*/cache/$i/shared_cpu_list"
if ! cat $f > $T/msg 2>&1
then
sed -e 's/^/# /' < $T/msg
exit 0
fi
cat $f >> $T/cpulist
done
if grep -q '[-,]' $T/cpulist
then
if test -z "$firstshared"
then
firstshared="$i"
fi
fi
done
if test -z "$firstshared"
then
splitindex="`echo $indexlist | sed -e 's/ .*$//'`"
else
splitindex="$firstshared"
fi
nodenum=0
for n in node*
do
cat $n/cpu*/cache/$splitindex/shared_cpu_list | sort -u -k1n |
awk -v nodenum="$nodenum" '
BEGIN {
idx = 0;
}
{
nlists = split($0, cpulists, ",");
for (i = 1; i <= nlists; i++) {
listsize = split(cpulists[i], cpus, "-");
if (listsize == 1)
cpus[2] = cpus[1];
for (j = cpus[1]; j <= cpus[2]; j++) {
print "cpu[" nodenum "][" idx "] = " j ";";
idx++;
}
}
}
END {
print "nodecpus[" nodenum "] = " idx ";";
}'
nodenum=`expr $nodenum + 1`
done
echo "numnodes = $nodenum;"