From nobody Sun Jan 25 12:00:39 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=kernel.org ARC-Seal: i=1; a=rsa-sha256; t=1769175382; cv=none; d=zohomail.com; s=zohoarc; b=dduZ+maBMWe3M7CdeW+o8ntL5j29S7V4OWJ0S7SH4L791K0Mgk2MtOlfCjH4rgtNds+D7IhM3qVDXHRFX4yOIxGRH6VZSzculXpQPh14u+NjI7RnJ2+2dtzDas+av6fQIh+vJvXWCJv9WAakqXqQiueIrxiPfjV7hJw6UwuIjB4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769175382; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=SmEkZCfmLFmvduzq8+X4/qelB18CQ+Z9lumNkl6cWMs=; b=apd9VUQ1xzT8euoN7hRaGGE7g3/IQNrzINwQvg29YYRZxZAXqMgHbDae5VCZHGDgPGLTq/dRcV+ucgIlMD4TUkvVmcnwOA+6MJzjOsUsOxBkwLgfBoadgaU47Sz2Zm+UyGLUbmGvG3uFUdyRlJlmQV7aYEUmNzPUw8TDrBWMAmU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1769175382824820.5735782119191; Fri, 23 Jan 2026 05:36:22 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vjHKh-0007lF-5f; Fri, 23 Jan 2026 08:36:16 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vjHKV-0007fJ-2O for qemu-devel@nongnu.org; Fri, 23 Jan 2026 08:36:04 -0500 Received: from tor.source.kernel.org ([172.105.4.254]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vjHKS-0004eK-Rc for qemu-devel@nongnu.org; Fri, 23 Jan 2026 08:36:02 -0500 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id AA594600C3; Fri, 23 Jan 2026 13:35:58 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3E4FBC4CEF1; Fri, 23 Jan 2026 13:35:58 +0000 (UTC) Received: from localhost ([::1]) by mail.kernel.org with esmtp (Exim 4.99.1) (envelope-from ) id 1vjHKO-000000063KU-0Qaq; Fri, 23 Jan 2026 14:35:56 +0100 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1769175358; bh=HVXl3Wpl7fLTvcky1zUA5qnO5oRuivfB4qeJv6RWhfs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JzbNFfRmBx1OF2NmkhqP1iorUbtXLMKtSuU9qGm3JH+Dk0prSJ3XIGJkE1aDg+J3g CxOO1ozmFGdFaEaE9BQ3x0SI8stpQ5FPJQw3EIDZQlfng9UqZH8wZUuYePQpHtfom0 N7Bt5w78eN4uwAl1eZwrcjwM+vzB2nJvArjeSayU6kIWQwSpVGXALIKtTsXBf7YS3C /8jLIjEbE1gUxvhFKDuWO9cCuFlSHATbCnd5s7X6HJ6FpNc8v2WOVt2sijrGYsvf8M 1PjLpGdp9P4MFOOH987JvEQfyOfSHrQ6ML3BuES8nXM+3vTuOcmaJ5fnDulIA+wK9O r5/kzzg3WBl+g== From: Mauro Carvalho Chehab To: "Michael S. Tsirkin" Cc: Mauro Carvalho Chehab , qemu-devel@nongnu.org, Cleber Rosa , John Snow , Jonathan Cameron Subject: [PATCH v2 10/13] scripts/ghes_inject: add support for fuzzy logic testing Date: Fri, 23 Jan 2026 14:35:24 +0100 Message-ID: <9df9ac7f31295c0d7f9866e8ee5d55a925985d5f.1769175070.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=172.105.4.254; envelope-from=mchehab+huawei@kernel.org; helo=tor.source.kernel.org X-Spam_score_int: -21 X-Spam_score: -2.2 X-Spam_bar: -- X-Spam_report: (-2.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.079, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @kernel.org) X-ZM-MESSAGEID: 1769175384114158500 Add a command to inject random errors for fuzzy logic testing. By default, it will generate a single test for a random valid GUID with random bytes inside the CPER payload. The command allows specifying: - a single type of CPER; - a range of minimum/maximum payload size; - change its default to fill with zero instead of random; - multiple CPERs with an specified count; - ensure a delay between them; - setup a timeout to retry if an attempt fails (useful when count > 1). Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Jonathan Cameron --- MAINTAINERS | 1 + scripts/fuzzy_error.py | 206 +++++++++++++++++++++++++++++++++++++++++ scripts/ghes_inject.py | 2 + 3 files changed, 209 insertions(+) create mode 100644 scripts/fuzzy_error.py diff --git a/MAINTAINERS b/MAINTAINERS index 1e62064a8672..967aafc35a92 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2228,6 +2228,7 @@ F: qapi/acpi-hest.json F: scripts/ghes_decode.py F: scripts/ghes_inject.py F: scripts/arm_processor_error.py +F: scripts/fuzzy_error.py F: scripts/pci_bus_error.py F: scripts/qmp_helper.py =20 diff --git a/scripts/fuzzy_error.py b/scripts/fuzzy_error.py new file mode 100644 index 000000000000..9f80abb72319 --- /dev/null +++ b/scripts/fuzzy_error.py @@ -0,0 +1,206 @@ +#!/usr/bin/env python3 +# +# pylint: disable=3DC0114,R0903,R0912 +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2024 Mauro Carvalho Chehab + +import argparse +import sys + +from time import sleep +from random import randrange +from qmp_helper import qmp, util, cper_guid + +class FuzzyError: + """ + Implements Fuzzy error injection via GHES + """ + + def __init__(self, subparsers): + """Initialize the error injection class and add subparser""" + + # as defined at UEFI spec v2.10, section N.2.2 + # Sizes here are just hints to have some default + self.types =3D { + "proc-generic": { + "guid": cper_guid.CPER_PROC_GENERIC, + "default_size": 192 + }, + "proc-x86": { + "guid": cper_guid.CPER_PROC_X86, + "default_size": 64 + }, + "proc-itanium": { + "guid": cper_guid.CPER_PROC_ITANIUM, + "default_size": 64 + }, + "proc-arm": { + "guid": cper_guid.CPER_PROC_ARM, + "default_size": 72 + }, + "platform-mem": { + "guid": cper_guid.CPER_PLATFORM_MEM, + "default_size": 80 + }, + "platform-mem2": { + "guid": cper_guid.CPER_PLATFORM_MEM2, + "default_size": 96 + }, + "pcie": { + "guid": cper_guid.CPER_PCIE, + "default_size": 208 + }, + "pci-bus": { + "guid": cper_guid.CPER_PCI_BUS, + "default_size": 72 + }, + "pci-dev": { + "guid": cper_guid.CPER_PCI_DEV, + "default_size": 56 + }, + "firmware-error": { + "guid": cper_guid.CPER_FW_ERROR, + "default_size": 32 + }, + "dma-generic": { + "guid": cper_guid.CPER_DMA_GENERIC, + "default_size": 32 + }, + "dma-vt": { + "guid": cper_guid.CPER_DMA_VT, + "default_size": 144 + }, + "dma-iommu": { + "guid": cper_guid.CPER_DMA_IOMMU, + "default_size": 144 + }, + "ccix-per": { + "guid": cper_guid.CPER_CCIX_PER, + "default_size": 36 + }, + "cxl-prot-err": { + "guid": cper_guid.CPER_CXL_PROT_ERR, + "default_size": 116 + }, + "cxl-evt-media": { + "guid": cper_guid.CPER_CXL_EVT_GEN_MEDIA, + "default_size": 32 + }, + "cxl-evt-dram": { + "guid": cper_guid.CPER_CXL_EVT_DRAM, + "default_size": 64 + }, + "cxl-evt-mem-module": { + "guid": cper_guid.CPER_CXL_EVT_MEM_MODULE, + "default_size": 64 + }, + "cxl-evt-mem-sparing": { + "guid": cper_guid.CPER_CXL_EVT_MEM_SPARING, + "default_size": 64 + }, + "cxl-evt-phy-sw": { + "guid": cper_guid.CPER_CXL_EVT_PHY_SW, + "default_size": 64 + }, + "cxl-evt-virt-sw": { + "guid": cper_guid.CPER_CXL_EVT_VIRT_SW, + "default_size": 64 + }, + "cxl-evt-mdl-port": { + "guid": cper_guid.CPER_CXL_EVT_MLD_PORT, + "default_size": 64 + }, + "cxl-evt-dyna-cap": { + "guid": cper_guid.CPER_CXL_EVT_DYNA_CAP, + "default_size": 64 + }, + "fru-mem-poison": { + "guid": cper_guid.CPER_FRU_MEM_POISON, + "default_size": 72 + }, + } + + parser =3D subparsers.add_parser("fuzzy-test", aliases=3D['fuzzy'], + description=3D"Inject a fuzzy test = CPER", + formatter_class=3Dargparse.RawTextH= elpFormatter) + g_fuzzy =3D parser.add_argument_group("Fuzz testing error inject") + + + cper_types =3D ",".join(self.types.keys()) + + g_fuzzy.add_argument("-T", "--type", + help=3Df"Type of the error: {cper_types}") + g_fuzzy.add_argument("--min-size", + type=3Dlambda x: int(x, 0), + help=3D"Minimal size of the CPER") + g_fuzzy.add_argument("--max-size", + type=3Dlambda x: int(x, 0), + help=3D"Maximal size of the CPER") + g_fuzzy.add_argument("-z", "--zero", action=3D"store_true", + help=3D"Zero all bytes of the CPER payload (de= fault: %(default)s)") + g_fuzzy.add_argument("-t", "--timeout", type=3Dfloat, + default=3D30.0, + help=3D"Specify timeout for CPER send retries (default= : %(default)s seconds)") + g_fuzzy.add_argument("-d", "--delay", type=3Dfloat, + default=3D0, + help=3D"Specify a delay between multiple CPER (default= : %(default)s)") + g_fuzzy.add_argument("-c", "--count", type=3Dint, + default=3D1, + help=3D"Specify the number of CPER records to be sent = (default: %(default)s)") + + parser.set_defaults(func=3Dself.send_cper) + + def send_cper(self, args): + """Parse subcommand arguments and send a CPER via QMP""" + + qmp_cmd =3D qmp(args.host, args.port, args.debug) + + args.count =3D max(args.count, 1) + + for i in range(0, args.count): + if i: + if args.delay > 0: + sleep(args.delay) + + # Handle global parameters + if args.type: + if not args.type in self.types: + sys.exit(f"Invalid type: {args.type}") + + inj_type =3D args.type + else: + i =3D randrange(len(self.types)) + keys =3D list(self.types.keys()) + inj_type =3D keys[i] + + inject =3D self.types[inj_type] + + guid =3D inject["guid"] + min_size =3D inject["default_size"] + max_size =3D min_size + + if args.min_size: + min_size =3D args.min_size + + if args.max_size: + max_size =3D args.max_size + + size =3D min_size + + if min_size < max_size: + size +=3D randrange(max_size - min_size) + + data =3D bytearray() + + if not args.zero: + for i in range(size): + util.data_add(data, randrange(256), 1) + else: + for i in range(size): + util.data_add(data, 0, 1) + + print(f"Injecting {inj_type} with {size} bytes") + ret =3D qmp_cmd.send_cper(guid, data, timeout=3Dargs.timeout) + if ret and ret !=3D "OK": + return ret diff --git a/scripts/ghes_inject.py b/scripts/ghes_inject.py index be2384a59b3e..bcbfffc586e1 100755 --- a/scripts/ghes_inject.py +++ b/scripts/ghes_inject.py @@ -13,6 +13,7 @@ =20 from arm_processor_error import ArmProcessorEinj from pci_bus_error import PciBusError +from fuzzy_error import FuzzyError =20 EINJ_DESC =3D """ Handle ACPI GHESv2 error injection logic QEMU QMP interface. @@ -42,6 +43,7 @@ def main(): =20 ArmProcessorEinj(subparsers) PciBusError(subparsers) + FuzzyError(subparsers) =20 args =3D parser.parse_args() if "func" in args: --=20 2.52.0