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