1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0+
3#
4# Produce awk statements roughly depicting the system's CPU and cache
5# layout.  If the required information is not available, produce
6# error messages as awk comments.  Successful exit regardless.
7#
8# Usage: kvm-assign-cpus.sh /path/to/sysfs
9
10T="`mktemp -d ${TMPDIR-/tmp}/kvm-assign-cpus.sh.XXXXXX`"
11trap 'rm -rf $T' 0 2
12
13sysfsdir=${1-/sys/devices/system/node}
14if ! cd "$sysfsdir" > $T/msg 2>&1
15then
16	sed -e 's/^/# /' < $T/msg
17	exit 0
18fi
19nodelist="`ls -d node*`"
20for i in node*
21do
22	if ! test -d $i/
23	then
24		echo "# Not a directory: $sysfsdir/node*"
25		exit 0
26	fi
27	for j in $i/cpu*/cache/index*
28	do
29		if ! test -d $j/
30		then
31			echo "# Not a directory: $sysfsdir/$j"
32			exit 0
33		else
34			break
35		fi
36	done
37	indexlist="`ls -d $i/cpu* | grep 'cpu[0-9][0-9]*' | head -1 | sed -e 's,^.*$,ls -d &/cache/index*,' | sh | sed -e 's,^.*/,,'`"
38	break
39done
40for i in node*/cpu*/cache/index*/shared_cpu_list
41do
42	if ! test -f $i
43	then
44		echo "# Not a file: $sysfsdir/$i"
45		exit 0
46	else
47		break
48	fi
49done
50firstshared=
51for i in $indexlist
52do
53	rm -f $T/cpulist
54	for n in node*
55	do
56		f="$n/cpu*/cache/$i/shared_cpu_list"
57		if ! cat $f > $T/msg 2>&1
58		then
59			sed -e 's/^/# /' < $T/msg
60			exit 0
61		fi
62		cat $f >> $T/cpulist
63	done
64	if grep -q '[-,]' $T/cpulist
65	then
66		if test -z "$firstshared"
67		then
68			firstshared="$i"
69		fi
70	fi
71done
72if test -z "$firstshared"
73then
74	splitindex="`echo $indexlist | sed -e 's/ .*$//'`"
75else
76	splitindex="$firstshared"
77fi
78nodenum=0
79for n in node*
80do
81	cat $n/cpu*/cache/$splitindex/shared_cpu_list | sort -u -k1n |
82	awk -v nodenum="$nodenum" '
83	BEGIN {
84		idx = 0;
85	}
86
87	{
88		nlists = split($0, cpulists, ",");
89		for (i = 1; i <= nlists; i++) {
90			listsize = split(cpulists[i], cpus, "-");
91			if (listsize == 1)
92				cpus[2] = cpus[1];
93			for (j = cpus[1]; j <= cpus[2]; j++) {
94				print "cpu[" nodenum "][" idx "] = " j ";";
95				idx++;
96			}
97		}
98	}
99
100	END {
101		print "nodecpus[" nodenum "] = " idx ";";
102	}'
103	nodenum=`expr $nodenum + 1`
104done
105echo "numnodes = $nodenum;"
106