1#!/bin/sh
2
3# cpuhotplug_hotplug.sh - Collection of functions for hotplugging
4# operations.
5
6# Routines in this library are set up to allow timing to be done
7# by defining $TIME to a timing command.
8TIME=${TIME:-""}
9
10# get_all_irqs()
11#
12#  Gets list of all available IRQs in the system
13#
14get_all_irqs()
15{
16    echo `egrep [0-9]+: /proc/interrupts | cut -d ':' -f 1`
17    return
18}
19
20# migrate_irq(CPU, IRQS)
21#
22#  Sets the smp_affinity for the list of $IRQS to the given
23#  CPU number
24#
25migrate_irq()
26{
27    CPU=${1#cpu}
28    MASK=$((1<<${CPU}))
29    IRQS=$2
30    for irq in ${IRQS}; do
31      echo $MASK > /proc/irq/${irq}/smp_affinity || \
32        tst_resm TINFO "It is NOT permitted to change the IRQ $irq smp_affinity"
33    done
34}
35
36
37# get_affinity(PID)
38#
39#  Echos the CPU affinity for the given process ID to stdout
40#
41get_affinity_mask()
42{
43    AFFINITY=`taskset -p ${1}`
44    echo ${AFFINITY}
45    return
46}
47
48# set_affinity(PID, CPU)
49#
50#  Sets the affinity for the given PID to the specified CPU.
51#
52set_affinity()
53{
54    PID="$1"
55    CPU="$2"
56    MASK=$((1<<${CPU_TO_TEST}))
57    `taskset -p ${MASK} ${PID} > /dev/null 2>&1`
58    return $?
59}
60
61# online_cpu(CPU)
62#
63#  Onlines the given CPU.  Returns a true value if it was able
64#  to perform the online operation successfully, false otherwise.
65#
66#  $CPU should either be a specific number like 4, or the cpu name,
67#  as in 'cpu4'.
68#
69online_cpu()
70{
71    CPU=${1#cpu}
72    if [ ! -w /sys/devices/system/cpu/cpu${CPU}/online ]; then
73        return 1
74    fi
75
76    cpu_is_online ${CPU} && return 0
77
78    $TIME echo 1 > /sys/devices/system/cpu/cpu${CPU}/online
79    RC=$?
80    report_timing "Online cpu ${CPU}"
81    return $RC
82}
83
84
85# offline_cpu(CPU)
86#
87#  Offlines the given CPU.  Returns a true value if it was able
88#  to perform the offline operation successfully, false otherwise.
89#
90offline_cpu()
91{
92    CPU=${1#cpu}
93    if [ ! -w /sys/devices/system/cpu/cpu${CPU}/online ]; then
94        return 1
95    fi
96
97    ! cpu_is_online ${CPU} && return 0
98
99    $TIME echo 0 > /sys/devices/system/cpu/cpu${CPU}/online
100    RC=$?
101    report_timing "Offline cpu ${CPU}"
102    return $RC
103}
104
105# get_cpus_num()
106#
107#  Prints the number of all available CPUs, regardless of whether they're
108#  currently online or offline.
109#
110get_cpus_num()
111{
112	[ -d /sys/devices/system/cpu/cpu0 ] || return -1
113	NUM=`ls /sys/devices/system/cpu/ \
114			| grep -c "cpu[0-9][0-9]*"`
115	return $NUM
116}
117
118# get_all_cpus()
119#
120#  Prints a list of all available CPUs, regardless of whether they're
121#  currently online or offline.
122#
123#  This routine will work even if the CPUs are not hotpluggable, however
124#  it requires you have sysfs enabled in the kernel.
125#
126get_all_cpus()
127{
128    [ -d /sys/devices/system/cpu ] || return 1
129    (cd /sys/devices/system/cpu; ls -d cpu[0-9]*)
130}
131
132# get_present_cpus()
133#
134#  Prints a list of present CPUs, regardless of whether they're
135#  currently online or offline.
136#
137get_present_cpus()
138{
139    local present_mask="/sys/devices/system/cpu/present"
140    local present_cpus=""
141
142    # if sysfs present mask is missing, assume all cpu are present
143    if [ ! -e "$present_mask" ]; then
144        get_all_cpus
145        return
146    fi
147
148    for part in $(cat $present_mask | tr "," " "); do
149        if echo $part | grep -q "-"; then
150            range_low=$(echo $part | cut -d - -f 1)
151            range_high=$(echo $part | cut -d - -f 2)
152        else
153            range_low=$part
154            range_high=$part
155        fi
156        for cpu in $(seq $range_low $range_high); do
157            if [ -e /sys/devices/system/cpu/cpu$cpu ]; then
158                present_cpus="$present_cpus cpu$cpu"
159            fi
160        done
161    done
162    echo $present_cpus
163}
164
165# get_present_cpus_num()
166#
167#  Prints the number of present CPUs
168#
169get_present_cpus_num()
170{
171    echo $(get_present_cpus | wc -w)
172}
173
174# get_hotplug_cpus()
175#
176#  Prints a list of present hotpluggable CPUs, regardless of whether they're
177#  currently online or offline.
178#
179get_hotplug_cpus()
180{
181    local present_cpus="$(get_present_cpus)"
182    local hotplug_cpus=""
183
184    for cpu in $present_cpus; do
185        if [ -e /sys/devices/system/cpu/$cpu/online ]; then
186            hotplug_cpus="$hotplug_cpus $cpu"
187	fi
188    done
189    echo $hotplug_cpus
190}
191
192# get_hotplug_cpus_num()
193#
194#  Prints the number of hotpluggable CPUs
195#
196get_hotplug_cpus_num()
197{
198    echo $(get_hotplug_cpus | wc -w)
199}
200
201# get_all_cpu_states()
202#
203#  Collects the current online/offline state of CPUs in the
204#  system, printing it in a format that can be passed to
205#  set_all_cpu_states() later.
206#
207get_all_cpu_states()
208{
209    echo `cd /sys/devices/system/cpu/ && grep '' */online | \
210		sed -e 's/\/online//'`
211    return
212}
213
214# set_all_cpu_states(STATES)
215#
216#  Sets all of the CPU states according to STATES, which must be
217#  of the form "cpuX:Y", where X is the CPU number and Y its state.
218#  Each must be on a separate line.
219#
220set_all_cpu_states()
221{
222    for cpu_state in $1; do
223        cpu=`echo $cpu_state | cut -d: -f 1`
224        state=`echo $cpu_state | cut -d: -f 2`
225        if [ $state = 1 ]; then
226            online_cpu $cpu
227        else
228            offline_cpu $cpu
229        fi
230    done
231}
232
233
234# get_online_cpus()
235#
236#  Prints a list of all CPUs currently online.  This function only
237#  works if the system's CPUs have hotplug capabilities
238#
239get_online_cpus()
240{
241    echo `cd /sys/devices/system/cpu/ && grep 1 */online | cut -d '/' -f 1`
242    return
243}
244
245
246# get_offline_cpus()
247#
248#  Prints a list of all CPUs currently offline.  This function only
249#  works if the system's CPUs have hotplug capabilities
250#
251get_offline_cpus()
252{
253    echo `cd /sys/devices/system/cpu/ && grep 0 */online | cut -d '/' -f 1`
254    return
255}
256
257# cpu_is_valid(CPU)
258#
259#  Checks to see if the given CPU number is available for hotplugging
260#  in the system.  Returns 0 if the CPU is available, 1 otherwise.
261#
262cpu_is_valid()
263{
264    CPU=${1#cpu}
265    echo "CPU is $CPU"
266    cat /sys/devices/system/cpu/cpu${CPU}/online > /dev/null 2>&1
267    return $?
268}
269
270
271# cpu_is_online(CPU)
272#
273#  Returns a 0 value if the given CPU number is currently online,
274#  1 otherwise.  This function requires the system's CPUs have
275#  hotplug capabilities.
276#
277cpu_is_online()
278{
279    CPU=${1#cpu}
280    if [ `cat /sys/devices/system/cpu/cpu${CPU}/online` = "1" ]; then
281        return 0
282    else
283        return 1
284    fi
285}
286