Skip to content

Commit 1571e81

Browse files
Merge pull request open-power#938 from shirishaganta1/taskset
Crashtool.py:Added taskset trigger dump on particular cpu
2 parents e02d7fc + 59cf5ab commit 1571e81

File tree

2 files changed

+103
-21
lines changed

2 files changed

+103
-21
lines changed

testcases/Crashtool.py

Lines changed: 98 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,20 @@
2727

2828
import unittest
2929
import os
30+
import random
3031
import OpTestConfiguration
3132
import OpTestLogger
3233

3334
from common.OpTestSystem import OpSystemState
3435
from common.OpTestUtil import OpTestUtil
36+
from testcases.OpTestKernelDump import OptestKernelDump
3537

3638
log = OpTestLogger.optest_logger_glob.get_logger(__name__)
3739

3840

39-
class CrashToolInteractiveTest(unittest.TestCase):
41+
class CrashTool(unittest.TestCase):
4042
"""
41-
Detects and validates the latest crash dump (vmcore) under /var/crash/
42-
43-
Identifies appropriate debug symbols (vmlinux) based on the OS (e.g., RHEL or SLES)
44-
45-
Launches crash vmlinux vmcore in interactive mode on the console
46-
47-
Executes a sequence of commands (log, bt, ps, etc.) in a single session
48-
49-
Verifies command output and exits cleanly from the crash shell
43+
test class providing common setup and helper methods for crash dump testing
5044
"""
5145

5246
def setUp(self):
@@ -58,12 +52,38 @@ def setUp(self):
5852
self.distro = self.op_test_util.distro_name()
5953
self.version = self.op_test_util.get_distro_version().split(".")[0]
6054
self.cv_SYSTEM.goto_state(OpSystemState.OS)
55+
self.c = self.cv_SYSTEM.console
56+
self.bmc_type = conf.args.bmc_type
57+
if self.bmc_type == "FSP_PHYP" or self.bmc_type == "EBMC_PHYP" :
58+
self.is_lpar = True
59+
self.cv_HMC = self.cv_SYSTEM.hmc
6160
try:
6261
self.crash_commands = conf.args.crash_commands
6362
except AttributeError:
6463
self.crash_commands = "log,bt,ps,runq,kmem -i,kmem -o,kmem -h,vm,sys,mod"
6564
self.commands = [cmd.strip() for cmd in self.crash_commands.split(",")]
6665

66+
def get_random_crash_cpu(self):
67+
"""
68+
Pick a random valid CPU from available system CPUs
69+
"""
70+
out = self.cv_HOST.host_run_command("nproc")
71+
if out:
72+
nproc = int(out[0].strip())
73+
else:
74+
nproc = int(
75+
self.cv_HOST.host_run_command("getconf _NPROCESSORS_ONLN")[0].strip()
76+
)
77+
if nproc <= 0:
78+
raise Exception("Invalid CPU count detected")
79+
crash_cpu = random.randint(0, nproc - 1)
80+
log.info(
81+
"Selected random crash CPU %d from %d CPUs",
82+
crash_cpu, nproc
83+
)
84+
85+
return crash_cpu
86+
6787
def run_crash_command(self, cmd, timeout=180):
6888
"""
6989
1.Sends a command to the running crash session
@@ -114,17 +134,11 @@ def verify_packages(self):
114134
log.info(
115135
f"All required debug packages for {self.distro} are installed.")
116136

117-
def runTest(self):
137+
def crash_console(self):
118138
"""
119-
1.Gets kernel version (uname -r)
120-
2.Finds latest crash directory (e.g., /var/crash/2025-06-03-07-08/)
121-
3.Validates vmcore file type and size
122-
4.Detects OS type/version and constructs appropriate vmlinux path
123-
5.Launches crash interactively
124-
6.Runs commands (stored in self.commands)
125-
7.Exits crash cleanly
139+
Locates latest crash dump directory, validates vmcore file,
140+
determines correct vmlinux path and launches the crash tool.
126141
"""
127-
self.verify_packages()
128142
kernel_version = self.cv_HOST.host_run_command("uname -r")[0].strip()
129143
cmd = "ls -1td /var/crash/*/ | head -n 1 | xargs basename"
130144
crash_dir = self.cv_HOST.host_run_command(cmd)[0].strip()
@@ -149,11 +163,31 @@ def runTest(self):
149163
self.console.sendline(crash_cmd)
150164
try:
151165
self.console.expect_exact("crash>", timeout=300)
166+
banner = self.console.before
167+
# Return crash startup banner
168+
return banner
152169
except Exception as e:
153170
if "crash>" not in self.console.before:
154171
raise Exception(
155172
"Crash tool failed to launch or kernel panic detected") from e
156173

174+
class CrashToolInteractiveTest(CrashTool):
175+
"""
176+
Interactive test case that verifies crash dump analysis by running a set of crash commands.
177+
"""
178+
179+
def runTest(self):
180+
"""
181+
1.Verifies required packages
182+
2.Triggers a kernel crash
183+
3.Launches crash tool and disables scroll paging.
184+
4.Iterates through configured crash commands (e.g., log, bt, ps, kmem) and captures output.
185+
5.Exits crash session cleanly.
186+
"""
187+
self.verify_packages()
188+
OptestKernelDump.kernel_crash(self)
189+
self.console = self.cv_SYSTEM.console.get_console()
190+
self.crash_console()
157191
# Set scroll off to avoid pager issues
158192
self.run_crash_command("set scroll off")
159193

@@ -165,3 +199,48 @@ def runTest(self):
165199
# Exit crash session
166200
self.console.sendline("exit")
167201
self.console.expect("#", timeout=30)
202+
203+
class CrashTaskset(CrashTool):
204+
"""
205+
Test case that validates crash dump collection when a crash is triggered on a specific CPU
206+
"""
207+
208+
def runTest(self):
209+
self.verify_packages()
210+
# Pick random valid CPU
211+
self.crash_cpu = self.get_random_crash_cpu()
212+
# Trigger crash with CPU affinity
213+
OptestKernelDump.kernel_crash(self, crash_cpu=self.crash_cpu)
214+
self.console = self.cv_SYSTEM.console.get_console()
215+
# Launch crash and capture banner
216+
banner = self.crash_console()
217+
found_cpu = False
218+
for line in banner.splitlines():
219+
line = line.strip()
220+
if line.startswith("CPU:"):
221+
found_cpu = True
222+
cpu = int(line.split()[1])
223+
224+
if cpu != self.crash_cpu:
225+
self.fail(
226+
"Expected crash CPU %d, got %d"
227+
% (self.crash_cpu, cpu)
228+
)
229+
log.info(
230+
"Crash occurred on expected CPU %d", cpu
231+
)
232+
break
233+
234+
if not found_cpu:
235+
self.fail("CPU field not found in crash startup output")
236+
237+
# Exit crash cleanly
238+
self.console.sendline("exit")
239+
self.console.expect("#", timeout=30)
240+
241+
def crash_suite():
242+
s = unittest.TestSuite()
243+
s.addTest(CrashToolInteractiveTest())
244+
s.addTest(CrashTaskset())
245+
return s
246+

testcases/OpTestKernelDump.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ def verify_fadump_unreg(self):
399399
self.c.run_command("rm /tmp/opal_log")
400400
self.c.run_command("rm /tmp/dmesg_log")
401401

402-
def kernel_crash(self, crash_type="echo_c"):
402+
def kernel_crash(self, crash_type="echo_c", crash_cpu=None):
403403
'''
404404
This function will test the kernel crash followed by system
405405
reboot. It has below steps
@@ -421,7 +421,10 @@ def kernel_crash(self, crash_type="echo_c"):
421421
if crash_type == "watchdog":
422422
self.c.pty.sendline("./watchdog-countdown")
423423
elif crash_type == "echo_c":
424-
self.c.pty.sendline("echo c > /proc/sysrq-trigger")
424+
if crash_cpu:
425+
self.c.pty.sendline(f"taskset -c {crash_cpu} echo c > /proc/sysrq-trigger")
426+
else:
427+
self.c.pty.sendline("echo c > /proc/sysrq-trigger")
425428
elif crash_type == "hmc":
426429
self.cv_HMC.run_command("chsysstate -r lpar -m %s -n %s -o dumprestart" %
427430
(self.system_name, self.lpar_name), timeout=300)

0 commit comments

Comments
 (0)