qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Harsh Prateek Bora <harshpb@linux.ibm.com>
To: qemu-devel@nongnu.org
Cc: Aditya Gupta <adityag@linux.ibm.com>,
	Shivang Upadhyay <shivangu@linux.ibm.com>
Subject: [PULL 31/32] tests/functional: Add test for fadump in PSeries
Date: Thu, 23 Oct 2025 17:14:18 +0530	[thread overview]
Message-ID: <20251023114422.3675018-32-harshpb@linux.ibm.com> (raw)
In-Reply-To: <20251023114422.3675018-1-harshpb@linux.ibm.com>

From: Aditya Gupta <adityag@linux.ibm.com>

Add testcases for testing fadump with PSeries and PSeries+KVM
combinations

It tests if fadump is successfully detected and registered in the first
kernel boot. Then crashes the kernel, and verifies whether we have a
/proc/vmcore in the 2nd boot

Also introduce 'wait_for_regex_console_pattern' to check for cases where
there is a single success message, but can have multiple failure
messages.

This is particularly useful for cases such as fadump, where the
success message is
    "Reserved 1024MB ... successfully"
But at the same point, it can fail with multiple errors such as
    "Not supported" or "Allocation failed"

'wait_for_regex_console_pattern' also has a timeout, for cases when we
know the success/failure should appear in a short amount of time,
instead of waiting for the much longer test timeout, such as kernels
with support of fadump will print the success/failure in earlyboot of
the kernel, while kernel without support of fadump won't print anything
for long time, and without a timeout the testcase keeps waiting till
longer test timeout

Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
Tested-by: Shivang Upadhyay <shivangu@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20251021134823.1861675-8-adityag@linux.ibm.com
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
 tests/functional/ppc64/meson.build        |   2 +
 tests/functional/ppc64/test_fadump.py     | 182 ++++++++++++++++++++++
 tests/functional/qemu_test/linuxkernel.py |  59 +++++++
 3 files changed, 243 insertions(+)
 create mode 100755 tests/functional/ppc64/test_fadump.py

diff --git a/tests/functional/ppc64/meson.build b/tests/functional/ppc64/meson.build
index 1fa0a70f7e..f0f8ab8f61 100644
--- a/tests/functional/ppc64/meson.build
+++ b/tests/functional/ppc64/meson.build
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-or-later
 
 test_ppc64_timeouts = {
+  'fadump' : 480,
   'hv' : 1000,
   'mac99' : 120,
   'powernv' : 480,
@@ -16,6 +17,7 @@ tests_ppc64_system_quick = [
 
 tests_ppc64_system_thorough = [
   'e500',
+  'fadump',
   'hv',
   'mac99',
   'powernv',
diff --git a/tests/functional/ppc64/test_fadump.py b/tests/functional/ppc64/test_fadump.py
new file mode 100755
index 0000000000..2d6b8017e8
--- /dev/null
+++ b/tests/functional/ppc64/test_fadump.py
@@ -0,0 +1,182 @@
+#!/usr/bin/env python3
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from unittest import skip
+from qemu_test import Asset
+from qemu_test import wait_for_console_pattern
+from qemu_test import LinuxKernelTest
+from qemu_test import exec_command, exec_command_and_wait_for_pattern
+
+class QEMUFadump(LinuxKernelTest):
+    """
+    Functional test to verify Fadump is working in following scenarios:
+
+    1. test_fadump_pseries:       PSeries
+    2. test_fadump_pseries_kvm:   PSeries + KVM
+    """
+
+    timeout = 90
+    KERNEL_COMMON_COMMAND_LINE = 'console=hvc0 fadump=on '
+    msg_panic = 'Kernel panic - not syncing'
+    msg_not_supported = 'Firmware-Assisted Dump is not supported on this hardware'
+    msg_registered_success = ''
+    msg_registered_failed = ''
+    msg_dump_active = ''
+
+    ASSET_EPAPR_KERNEL = Asset(
+        ('https://github.com/open-power/op-build/releases/download/v2.7/'
+         'zImage.epapr'),
+        '0ab237df661727e5392cee97460e8674057a883c5f74381a128fa772588d45cd')
+
+    ASSET_VMLINUZ_KERNEL = Asset(
+        ('https://archives.fedoraproject.org/pub/archive/fedora-secondary/'
+         'releases/39/Everything/ppc64le/os/ppc/ppc64/vmlinuz'),
+        ('81e5541d243b50c8f9568906c6918dda22239744d637bb9a7b22d23c3d661226'
+         '8d5302beb2ca5c06f93bdbc9736c414ef5120756c8bf496ff488ad07d116d67f')
+        )
+
+    ASSET_FEDORA_INITRD = Asset(
+        ('https://archives.fedoraproject.org/pub/archive/fedora-secondary/'
+        'releases/39/Everything/ppc64le/os/ppc/ppc64/initrd.img'),
+        'e7f24b44cb2aaa67d30e551db6ac8d29cc57c934b158dabca6b7f885f2cfdd9b')
+
+    def do_test_fadump(self, is_kvm=False, is_powernv=False):
+        """
+        Helper Function for Fadump tests below
+
+        It boots the VM with fadump enabled, checks if fadump is correctly
+        registered.
+        Then crashes the system causing a QEMU_SYSTEM_RESET, after which
+        dump should be available in the kernel.
+        Finally it checks the filesize of the exported /proc/vmcore in 2nd
+        kernel to verify it's same as the VM's memory size
+        """
+        if is_kvm:
+            self.require_accelerator("kvm")
+            self.vm.add_args("-accel", "kvm")
+        else:
+            self.require_accelerator("tcg")
+
+        if is_powernv:
+            self.set_machine("powernv10")
+        else:
+            # SLOF takes upto >20s in startup time, use VOF
+            self.set_machine("pseries")
+            self.vm.add_args("-machine", "x-vof=on")
+            self.vm.add_args("-m", "6G")
+
+        self.vm.set_console()
+
+        kernel_path = None
+
+        if is_powernv:
+            kernel_path = self.ASSET_EPAPR_KERNEL.fetch()
+        else:
+            kernel_path = self.ASSET_VMLINUZ_KERNEL.fetch()
+
+        initrd_path = self.ASSET_FEDORA_INITRD.fetch()
+
+        self.vm.add_args('-kernel', kernel_path)
+        self.vm.add_args('-initrd', initrd_path)
+        self.vm.add_args('-append', "fadump=on"\
+                         " -nodefaults -serial mon:stdio crashkernel=2G"\
+                         " rdinit=/bin/sh ")
+
+        self.vm.launch()
+
+        # If kernel detects fadump support, and "fadump=on" is in command
+        # line which we add above, it will print something like:
+        #
+        #     fadump: Reserved 1024MB of memory at 0x00000040000000 ...
+        #
+        # Else, if the kernel doesn't detect fadump support, it prints:
+        #
+        #     fadump: Firmware-Assisted Dump is not supported on this hardware
+        #
+        # Timeout after 20s if kernel doesn't print any fadump logs, this
+        # can happen due to fadump being disabled in the kernel
+        self.wait_for_regex_console_pattern(
+            success_pattern="fadump: Reserved ",
+            failure_pattern=r"fadump: (Firmware-Assisted Dump is not"\
+            " supported on this hardware|Failed to find memory chunk for"\
+            " reservation!)",
+            timeout=20
+        )
+
+        # Ensure fadump is registered successfully, if registration
+        # succeeds, we get a log from rtas fadump:
+        #
+        #     rtas fadump: Registration is successful!
+        self.wait_for_console_pattern(
+            "rtas fadump: Registration is successful!"
+        )
+
+        # Wait for the shell
+        self.wait_for_console_pattern("#")
+
+        # Mount /proc since not available in the initrd used
+        exec_command(self, command="mount -t proc proc /proc")
+
+        # Crash the kernel
+        exec_command(self, command="echo c > /proc/sysrq-trigger")
+
+        # Check for the kernel panic message, setting timeout to 20s as it
+        # should occur almost immediately after previous echo c
+        self.wait_for_regex_console_pattern(
+            success_pattern="Kernel panic - not syncing: sysrq" \
+                " triggered crash",
+            timeout=20
+        )
+
+        # Check if fadump is active
+        # If the kernel shows that fadump is active, that implies it's a
+        # crashkernel boot
+        # Else if the kernel shows "fadump: Reserved ..." then it's
+        # treating this as the first kernel boot, this is likely the case
+        # that qemu didn't pass the 'ibm,kernel-dump' device tree node
+        wait_for_console_pattern(
+            test=self,
+            success_message="rtas fadump: Firmware-assisted dump is active",
+            failure_message="fadump: Reserved "
+        )
+
+        # In a successful fadump boot, we get these logs:
+        #
+        # [    0.000000] fadump: Firmware-assisted dump is active.
+        # [    0.000000] fadump: Reserving <>MB of memory at <> for preserving crash data
+        #
+        # Check if these logs are present in the fadump boot
+        self.wait_for_console_pattern("preserving crash data")
+
+        # Wait for prompt
+        self.wait_for_console_pattern("sh-5.2#")
+
+        # Mount /proc since not available in the initrd used
+        exec_command_and_wait_for_pattern(self,
+            command="mount -t proc proc /proc",
+            success_message="#"
+        )
+
+        # Check if vmcore exists
+        exec_command_and_wait_for_pattern(self,
+            command="stat /proc/vmcore",
+            success_message="File: /proc/vmcore",
+            failure_message="No such file or directory"
+        )
+
+    def test_fadump_pseries(self):
+        return self.do_test_fadump(is_kvm=False, is_powernv=False)
+
+    @skip("PowerNV Fadump not supported yet")
+    def test_fadump_powernv(self):
+        return
+
+    def test_fadump_pseries_kvm(self):
+        """
+        Test Fadump in PSeries with KVM accel
+        """
+        self.do_test_fadump(is_kvm=True, is_powernv=False)
+
+if __name__ == '__main__':
+    QEMUFadump.main()
diff --git a/tests/functional/qemu_test/linuxkernel.py b/tests/functional/qemu_test/linuxkernel.py
index 2aca0ee3cd..c4767527da 100644
--- a/tests/functional/qemu_test/linuxkernel.py
+++ b/tests/functional/qemu_test/linuxkernel.py
@@ -5,6 +5,9 @@
 
 import hashlib
 import urllib.request
+import logging
+import re
+import time
 
 from .cmd import wait_for_console_pattern, exec_command_and_wait_for_pattern
 from .testcase import QemuSystemTest
@@ -19,6 +22,62 @@ def wait_for_console_pattern(self, success_message, vm=None):
                                  failure_message='Kernel panic - not syncing',
                                  vm=vm)
 
+    def wait_for_regex_console_pattern(self, success_pattern,
+                                       failure_pattern=None,
+                                       timeout=None):
+        """
+        Similar to 'wait_for_console_pattern', but supports regex patterns,
+        hence multiple failure/success patterns can be detected at a time.
+
+        Args:
+            success_pattern (str | re.Pattern): A regex pattern that indicates
+                a successful event. If found, the method exits normally.
+            failure_pattern (str | re.Pattern, optional): A regex pattern that
+                indicates a failure event. If found, the test fails
+            timeout (int, optional): The maximum time (in seconds) to wait for
+                a match.
+                If exceeded, the test fails.
+        """
+
+        console = self.vm.console_file
+        console_logger = logging.getLogger('console')
+
+        self.log.debug(
+            f"Console interaction: success_msg='{success_pattern}' " +
+            f"failure_msg='{failure_pattern}' timeout='{timeout}s'")
+
+        # Only consume console output if waiting for something
+        if success_pattern is None and failure_pattern is None:
+            return
+
+        start_time = time.time()
+
+        while time.time() - start_time < timeout:
+            try:
+                msg = console.readline().decode().strip()
+            except UnicodeDecodeError:
+                msg = None
+            if not msg:
+                continue
+            console_logger.debug(msg)
+            if success_pattern is None or re.search(success_pattern, msg):
+                break
+            if failure_pattern:
+                # Find the matching error to print in log
+                match = re.search(failure_pattern, msg)
+                if not match:
+                    continue
+
+                console.close()
+                fail = 'Failure message found in console: "%s".' \
+                        ' Expected: "%s"' % \
+                        (match.group(), success_pattern)
+                self.fail(fail)
+
+        if time.time() - start_time >= timeout:
+            fail = f"Timeout ({timeout}s) while trying to search pattern"
+            self.fail(fail)
+
     def launch_kernel(self, kernel, initrd=None, dtb=None, console_index=0,
                       wait_for=None):
         self.vm.set_console(console_index=console_index)
-- 
2.43.5



  parent reply	other threads:[~2025-10-23 11:50 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-23 11:43 [PULL 00/32] ppc-for-10.2 queue Harsh Prateek Bora
2025-10-23 11:43 ` [PULL 01/32] ppc/spapr: remove deprecated machine pseries-3.0 Harsh Prateek Bora
2025-10-23 11:43 ` [PULL 02/32] hw/ppc/spapr: Remove SpaprMachineClass::nr_xirqs field Harsh Prateek Bora
2025-10-23 11:43 ` [PULL 03/32] ppc/spapr: remove deprecated machine pseries-3.1 Harsh Prateek Bora
2025-10-23 11:43 ` [PULL 04/32] hw/ppc/spapr: Inline spapr_dtb_needed() Harsh Prateek Bora
2025-10-23 11:43 ` [PULL 05/32] hw/ppc/spapr: Inline few SPAPR_IRQ_* uses Harsh Prateek Bora
2025-10-23 11:43 ` [PULL 06/32] target/ppc/kvm: Remove kvmppc_get_host_serial() as unused Harsh Prateek Bora
2025-10-23 11:43 ` [PULL 07/32] target/ppc/kvm: Remove kvmppc_get_host_model() " Harsh Prateek Bora
2025-10-23 11:43 ` [PULL 08/32] ppc/spapr: remove deprecated machine pseries-4.0 Harsh Prateek Bora
2025-10-23 11:43 ` [PULL 09/32] hw/ppc/spapr: Remove SpaprMachineClass::phb_placement callback Harsh Prateek Bora
2025-10-23 11:43 ` [PULL 10/32] ppc/spapr: remove deprecated machine pseries-4.1 Harsh Prateek Bora
2025-10-23 11:43 ` [PULL 11/32] ppc/spapr: remove deprecated machine pseries-4.2 Harsh Prateek Bora
2025-10-23 11:43 ` [PULL 12/32] ppc/amigaone: Free allocated struct Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 13/32] ppc/vof: Make nextprop behave more like Open Firmware Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 14/32] hw/ppc/pegasos2: Remove explicit name properties from device tree Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 15/32] hw/ppc/pegasos2: Change device tree generation Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 16/32] hw/ppc/pegasos2: Remove fdt pointer from machine state Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 17/32] hw/ppc/pegasos2: Rename mv field in " Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 18/32] hw/ppc/pegasos2: Add south bridge pointer in the " Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 19/32] hw/ppc/pegasos2: Move PCI IRQ routing setup to a function Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 20/32] hw/ppc/pegasos2: Move hardware specific parts out of machine reset Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 21/32] hw/ppc/pegasos2: Introduce abstract superclass Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 22/32] hw/ppc/pegasos2: Add bus frequency to machine state Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 23/32] hw/ppc/pegasos2: Add Pegasos I emulation Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 24/32] hw/ppc/pegasos2: Add VOF support for pegasos1 Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 25/32] hw/ppc: Implement fadump register command Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 26/32] hw/ppc: Trigger Fadump boot if fadump is registered Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 27/32] hw/ppc: Preserve memory regions registered for fadump Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 28/32] hw/ppc: Implement saving CPU state in Fadump Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 29/32] hw/ppc: Pass dump-sizes property for fadump in device tree Harsh Prateek Bora
2025-10-23 11:44 ` [PULL 30/32] hw/ppc: Enable fadump for PSeries Harsh Prateek Bora
2025-10-23 11:44 ` Harsh Prateek Bora [this message]
2025-10-23 11:44 ` [PULL 32/32] MAINTAINERS: Add entry for FADump (pSeries) Harsh Prateek Bora
2025-10-23 12:15 ` [PULL 00/32] ppc-for-10.2 queue Harsh Prateek Bora
  -- strict thread matches above, loose matches on Subject: below --
2025-10-23 12:16 [PULL RESEND " Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 31/32] tests/functional: Add test for fadump in PSeries Harsh Prateek Bora

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251023114422.3675018-32-harshpb@linux.ibm.com \
    --to=harshpb@linux.ibm.com \
    --cc=adityag@linux.ibm.com \
    --cc=qemu-devel@nongnu.org \
    --cc=shivangu@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).