blob: 68bd89af8d8af832a5c9ea66389151e2bcc039d1 [file] [log] [blame]
Anders Roxelle3f51b82024-07-04 12:30:01 +02001#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0-only
3# Copyright (C) 2024 Linaro Ltd.
4
5# shellcheck disable=SC1091
6. ../../lib/sh-test-lib
7OUTPUT="$(pwd)/output"
8RESULT_FILE="${OUTPUT}/result.txt"
9export RESULT_FILE
10
11MODULES_LIST=""
12MODULES_SUBDIRS=""
13MODULE_MODPROBE_NUMBER="1"
Anders Roxell8aa8dbf2024-07-11 14:42:19 +020014SKIPLIST=""
Anders Roxelle3f51b82024-07-04 12:30:01 +020015SHARD_NUMBER=1
16SHARD_INDEX=1
17
18usage() {
19 echo "Usage: $0 [-d <subdir of the modules directory> ]
20 [-l <space separated module list> ]
21 [-c <Number of load/unload of a module> ]
22 [-i <sharding bucket to run> ]
23 [-n <number of shard buckets to create> ]
Anders Roxell8aa8dbf2024-07-11 14:42:19 +020024 [-s <skiplist modules to skip> ]
Anders Roxelle3f51b82024-07-04 12:30:01 +020025 [-h ]" 1>&2
26 exit 0
27}
28
Anders Roxell8aa8dbf2024-07-11 14:42:19 +020029while getopts "c:d:i:l:n:s:h" o; do
Anders Roxelle3f51b82024-07-04 12:30:01 +020030 case "$o" in
31 d) MODULES_SUBDIRS="${OPTARG}" ;;
32 l) MODULES_LIST="${OPTARG}" ;;
33 c) MODULE_MODPROBE_NUMBER="${OPTARG}" ;;
34 i) SHARD_INDEX="${OPTARG}" ;;
35 n) SHARD_NUMBER="${OPTARG}" ;;
Anders Roxell8aa8dbf2024-07-11 14:42:19 +020036 s) SKIPLIST="${OPTARG}" ;;
Anders Roxelle3f51b82024-07-04 12:30:01 +020037 h|*) usage ;;
38 esac
39done
40
Anders Roxellcb19cb92025-06-06 00:25:27 +020041get_mem_usage_kb() {
42 grep -i "MemAvailable:" /proc/meminfo | awk '{ print $2 }'
43}
44
45compare_memory_usage() {
46 local before_kb=$1
47 local after_kb=$2
48 local module=$3
49 local diff_kb
50 diff_kb=$((before_kb - after_kb))
51 echo "memcheck: before ${before_kb}, after ${after_kb}, diff ${diff_kb}"
52 if [ "$diff_kb" -lt 0 ]; then
53 report_fail "memcheck_${module}"
54 else
55 report_pass "memcheck_${module}"
56 fi
57}
58
Anders Roxelle3f51b82024-07-04 12:30:01 +020059get_modules_list() {
60 if [ -z "${MODULES_LIST}" ]; then
Anders Roxell25fd9512025-04-28 13:50:31 +020061 if [ -n "${MODULES_SUBDIRS}" ]; then
62 subdir=$(echo "${MODULES_SUBDIRS}" | tr ' ' '|')
63 grep -E "kernel/(${subdir})" /lib/modules/"$(uname -r)"/modules.order > /tmp/find_modules.txt
64 else
65 # No subdir given, default to all modules
66 cat /lib/modules/"$(uname -r)"/modules.order > /tmp/find_modules.txt
67 fi
68
69 if [ -n "${SKIPLIST}" ]; then
70 skiplist=$(echo "${SKIPLIST}" | tr ' ' '|')
71 grep -E -v "(${skiplist})" /tmp/find_modules.txt > /tmp/modules_to_run.txt
72 else
73 cp /tmp/find_modules.txt /tmp/modules_to_run.txt
74 fi
75
Anders Roxell8aa8dbf2024-07-11 14:42:19 +020076 split --verbose --numeric-suffixes=1 -n l/"${SHARD_INDEX}"/"${SHARD_NUMBER}" /tmp/modules_to_run.txt > /tmp/shardfile
Anders Roxellbde4f2e2024-07-09 19:29:06 +020077 echo "============== Tests to run ==============="
78 cat /tmp/shardfile
79 echo "===========End Tests to run ==============="
80 if [ -s /tmp/shardfile ]; then
81 report_pass "shardfile"
82 else
83 report_fail "shardfile"
84 fi
Anders Roxelle3f51b82024-07-04 12:30:01 +020085 while IFS= read -r line
86 do
87 module_basename=$(basename "${line}")
88 module_name=${module_basename%.*}
89 MODULES_LIST="${MODULES_LIST} ${module_name}"
90 done < /tmp/shardfile
91 fi
92}
93
94report() {
95 local _modprop_flag="${1}"
96 local _module="${2}"
97 local _text="${3}"
98 local _num="${4}"
99 echo
100 echo "${_text} module: ${_module}"
101 if ! modprobe "${_module}" "${_modprop_flag}"; then
102 report_fail "${_text}_module_${_num}_${_module}"
103 else
104 report_pass "${_text}_module_${_num}_${_module}"
105 fi
106}
107
Anders Roxella7b173b2025-04-28 12:24:19 +0200108scan_dmesg_for_errors() {
109 echo "=== Scanning dmesg for errors ==="
110 dmesg -l 0,1,2,3,4,5 | grep -Ei "BUG:|WARNING:|Oops:|Call Trace:" && report_fail "dmesg_error_scan" || report_pass "dmesg_error_scan"
111}
112
Anders Roxelle6199bd2025-04-28 12:25:03 +0200113check_module_unloaded() {
114 local _module="$1"
115 if lsmod | grep "^${_module} " > /dev/null; then
116 echo "Module ${_module} still loaded after removal!"
117 report_fail "module_stuck_${_module}"
118 else
119 report_pass "module_unloaded_${_module}"
120 fi
121}
122
Anders Roxellad114aa2025-04-28 12:25:26 +0200123kmemleak_scan() {
124 if [ -e /sys/kernel/debug/kmemleak ]; then
125 echo "Triggering kmemleak scan..."
126 echo scan > /sys/kernel/debug/kmemleak
127 sleep 5
128 if grep -q . /sys/kernel/debug/kmemleak; then
129 echo "Potential memory leaks detected:"
130 cat /sys/kernel/debug/kmemleak
131 report_fail "kmemleak_detected"
132 else
133 report_pass "kmemleak_no_leaks"
134 fi
135 else
136 echo "kmemleak not available, skipping scan."
137 fi
138}
139
Anders Roxelle3f51b82024-07-04 12:30:01 +0200140run () {
141 for module in ${MODULES_LIST}; do
142 # don't insert/remove modules that is already inserted.
143 if ! lsmod | grep "^${module}"; then
144 for num in $(seq "${MODULE_MODPROBE_NUMBER}"); do
145 dmesg -C
Anders Roxellcb19cb92025-06-06 00:25:27 +0200146 mem_before=$(get_mem_usage_kb)
Anders Roxelle3f51b82024-07-04 12:30:01 +0200147 report "" "${module}" "insert" "${num}"
148 echo
149 echo "modinfo ${module}"
150 modinfo "${module}"
Anders Roxella7b173b2025-04-28 12:24:19 +0200151 scan_dmesg_for_errors
152
Anders Roxelle3f51b82024-07-04 12:30:01 +0200153 report "--remove" "${module}" "remove" "${num}"
Anders Roxella7b173b2025-04-28 12:24:19 +0200154 scan_dmesg_for_errors
Anders Roxelle6199bd2025-04-28 12:25:03 +0200155
156 check_module_unloaded "${module}"
Anders Roxellcb19cb92025-06-06 00:25:27 +0200157 mem_after=$(get_mem_usage_kb)
158 compare_memory_usage "$mem_before" "$mem_after" "$module"
Anders Roxelle3f51b82024-07-04 12:30:01 +0200159 done
160 fi
161 done
162}
163
164# Test run.
165! check_root && error_msg "This script must be run as root"
166create_out_dir "${OUTPUT}"
167info_msg "Output directory: ${OUTPUT}"
168info_msg "About to run load/unload kernel modules ..."
169get_modules_list
170run
Anders Roxellad114aa2025-04-28 12:25:26 +0200171kmemleak_scan