cpu-on-off-test.sh 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. #!/bin/bash
  2. # SPDX-License-Identifier: GPL-2.0
  3. SYSFS=
  4. prerequisite()
  5. {
  6. msg="skip all tests:"
  7. if [ $UID != 0 ]; then
  8. echo $msg must be run as root >&2
  9. exit 0
  10. fi
  11. taskset -p 01 $$
  12. SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`
  13. if [ ! -d "$SYSFS" ]; then
  14. echo $msg sysfs is not mounted >&2
  15. exit 0
  16. fi
  17. if ! ls $SYSFS/devices/system/cpu/cpu* > /dev/null 2>&1; then
  18. echo $msg cpu hotplug is not supported >&2
  19. exit 0
  20. fi
  21. echo "CPU online/offline summary:"
  22. online_cpus=`cat $SYSFS/devices/system/cpu/online`
  23. online_max=${online_cpus##*-}
  24. if [[ "$online_cpus" = "$online_max" ]]; then
  25. echo "$msg: since there is only one cpu: $online_cpus"
  26. exit 0
  27. fi
  28. echo -e "\t Cpus in online state: $online_cpus"
  29. offline_cpus=`cat $SYSFS/devices/system/cpu/offline`
  30. if [[ "a$offline_cpus" = "a" ]]; then
  31. offline_cpus=0
  32. else
  33. offline_max=${offline_cpus##*-}
  34. fi
  35. echo -e "\t Cpus in offline state: $offline_cpus"
  36. }
  37. #
  38. # list all hot-pluggable CPUs
  39. #
  40. hotpluggable_cpus()
  41. {
  42. local state=${1:-.\*}
  43. for cpu in $SYSFS/devices/system/cpu/cpu*; do
  44. if [ -f $cpu/online ] && grep -q $state $cpu/online; then
  45. echo ${cpu##/*/cpu}
  46. fi
  47. done
  48. }
  49. hotplaggable_offline_cpus()
  50. {
  51. hotpluggable_cpus 0
  52. }
  53. hotpluggable_online_cpus()
  54. {
  55. hotpluggable_cpus 1
  56. }
  57. cpu_is_online()
  58. {
  59. grep -q 1 $SYSFS/devices/system/cpu/cpu$1/online
  60. }
  61. cpu_is_offline()
  62. {
  63. grep -q 0 $SYSFS/devices/system/cpu/cpu$1/online
  64. }
  65. online_cpu()
  66. {
  67. echo 1 > $SYSFS/devices/system/cpu/cpu$1/online
  68. }
  69. offline_cpu()
  70. {
  71. echo 0 > $SYSFS/devices/system/cpu/cpu$1/online
  72. }
  73. online_cpu_expect_success()
  74. {
  75. local cpu=$1
  76. if ! online_cpu $cpu; then
  77. echo $FUNCNAME $cpu: unexpected fail >&2
  78. exit 1
  79. elif ! cpu_is_online $cpu; then
  80. echo $FUNCNAME $cpu: unexpected offline >&2
  81. exit 1
  82. fi
  83. }
  84. online_cpu_expect_fail()
  85. {
  86. local cpu=$1
  87. if online_cpu $cpu 2> /dev/null; then
  88. echo $FUNCNAME $cpu: unexpected success >&2
  89. exit 1
  90. elif ! cpu_is_offline $cpu; then
  91. echo $FUNCNAME $cpu: unexpected online >&2
  92. exit 1
  93. fi
  94. }
  95. offline_cpu_expect_success()
  96. {
  97. local cpu=$1
  98. if ! offline_cpu $cpu; then
  99. echo $FUNCNAME $cpu: unexpected fail >&2
  100. exit 1
  101. elif ! cpu_is_offline $cpu; then
  102. echo $FUNCNAME $cpu: unexpected offline >&2
  103. exit 1
  104. fi
  105. }
  106. offline_cpu_expect_fail()
  107. {
  108. local cpu=$1
  109. if offline_cpu $cpu 2> /dev/null; then
  110. echo $FUNCNAME $cpu: unexpected success >&2
  111. exit 1
  112. elif ! cpu_is_online $cpu; then
  113. echo $FUNCNAME $cpu: unexpected offline >&2
  114. exit 1
  115. fi
  116. }
  117. error=-12
  118. allcpus=0
  119. priority=0
  120. online_cpus=0
  121. online_max=0
  122. offline_cpus=0
  123. offline_max=0
  124. while getopts e:ahp: opt; do
  125. case $opt in
  126. e)
  127. error=$OPTARG
  128. ;;
  129. a)
  130. allcpus=1
  131. ;;
  132. h)
  133. echo "Usage $0 [ -a ] [ -e errno ] [ -p notifier-priority ]"
  134. echo -e "\t default offline one cpu"
  135. echo -e "\t run with -a option to offline all cpus"
  136. exit
  137. ;;
  138. p)
  139. priority=$OPTARG
  140. ;;
  141. esac
  142. done
  143. if ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then
  144. echo "error code must be -4095 <= errno < 0" >&2
  145. exit 1
  146. fi
  147. prerequisite
  148. #
  149. # Safe test (default) - offline and online one cpu
  150. #
  151. if [ $allcpus -eq 0 ]; then
  152. echo "Limited scope test: one hotplug cpu"
  153. echo -e "\t (leaves cpu in the original state):"
  154. echo -e "\t online to offline to online: cpu $online_max"
  155. offline_cpu_expect_success $online_max
  156. online_cpu_expect_success $online_max
  157. if [[ $offline_cpus -gt 0 ]]; then
  158. echo -e "\t offline to online to offline: cpu $offline_max"
  159. online_cpu_expect_success $offline_max
  160. offline_cpu_expect_success $offline_max
  161. fi
  162. exit 0
  163. else
  164. echo "Full scope test: all hotplug cpus"
  165. echo -e "\t online all offline cpus"
  166. echo -e "\t offline all online cpus"
  167. echo -e "\t online all offline cpus"
  168. fi
  169. #
  170. # Online all hot-pluggable CPUs
  171. #
  172. for cpu in `hotplaggable_offline_cpus`; do
  173. online_cpu_expect_success $cpu
  174. done
  175. #
  176. # Offline all hot-pluggable CPUs
  177. #
  178. for cpu in `hotpluggable_online_cpus`; do
  179. offline_cpu_expect_success $cpu
  180. done
  181. #
  182. # Online all hot-pluggable CPUs again
  183. #
  184. for cpu in `hotplaggable_offline_cpus`; do
  185. online_cpu_expect_success $cpu
  186. done
  187. #
  188. # Test with cpu notifier error injection
  189. #
  190. DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'`
  191. NOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/cpu
  192. prerequisite_extra()
  193. {
  194. msg="skip extra tests:"
  195. /sbin/modprobe -q -r cpu-notifier-error-inject
  196. /sbin/modprobe -q cpu-notifier-error-inject priority=$priority
  197. if [ ! -d "$DEBUGFS" ]; then
  198. echo $msg debugfs is not mounted >&2
  199. exit 0
  200. fi
  201. if [ ! -d $NOTIFIER_ERR_INJECT_DIR ]; then
  202. echo $msg cpu-notifier-error-inject module is not available >&2
  203. exit 0
  204. fi
  205. }
  206. prerequisite_extra
  207. #
  208. # Offline all hot-pluggable CPUs
  209. #
  210. echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error
  211. for cpu in `hotpluggable_online_cpus`; do
  212. offline_cpu_expect_success $cpu
  213. done
  214. #
  215. # Test CPU hot-add error handling (offline => online)
  216. #
  217. echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_UP_PREPARE/error
  218. for cpu in `hotplaggable_offline_cpus`; do
  219. online_cpu_expect_fail $cpu
  220. done
  221. #
  222. # Online all hot-pluggable CPUs
  223. #
  224. echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_UP_PREPARE/error
  225. for cpu in `hotplaggable_offline_cpus`; do
  226. online_cpu_expect_success $cpu
  227. done
  228. #
  229. # Test CPU hot-remove error handling (online => offline)
  230. #
  231. echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error
  232. for cpu in `hotpluggable_online_cpus`; do
  233. offline_cpu_expect_fail $cpu
  234. done
  235. echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error
  236. /sbin/modprobe -q -r cpu-notifier-error-inject