From: Mauro Carvalho Chehab Date: Tue, 23 Sep 2025 07:04:07 +0000 (+0200) Subject: qapi/acpi-hest: add an interface to do generic CPER error injection X-Git-Tag: v10.2.0-rc1~76^2~48 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ddd8f3baa27dc05251f52e94d1b643bfb93cbc83;p=thirdparty%2Fqemu.git qapi/acpi-hest: add an interface to do generic CPER error injection Create a QMP command to be used for generic ACPI APEI hardware error injection (HEST) via GHESv2, and add support for it for ARM guests. Error injection uses ACPI_HEST_SRC_ID_QMP source ID to be platform independent. This is mapped at arch virt bindings, depending on the types supported by QEMU and by the BIOS. So, on ARM, this is supported via ACPI_GHES_NOTIFY_GPIO notification type. This patch was co-authored: - original ghes logic to inject a simple ARM record by Shiju Jose; - generic logic to handle block addresses by Jonathan Cameron; - generic GHESv2 error inject by Mauro Carvalho Chehab; Co-authored-by: Jonathan Cameron Co-authored-by: Shiju Jose Co-authored-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Cameron Signed-off-by: Shiju Jose Signed-off-by: Mauro Carvalho Chehab Acked-by: Igor Mammedov Acked-by: Markus Armbruster Reviewed-by: Michael S. Tsirkin Message-ID: <81e2118b3c8b7e5da341817f277d61251655e0db.1758610789.git.mchehab+huawei@kernel.org> Signed-off-by: Michael S. Tsirkin --- diff --git a/MAINTAINERS b/MAINTAINERS index 406cef88f0..b31ae5193d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2173,6 +2173,13 @@ F: hw/acpi/ghes.c F: include/hw/acpi/ghes.h F: docs/specs/acpi_hest_ghes.rst +ACPI/HEST/GHES/ARM processor CPER +R: Mauro Carvalho Chehab +S: Maintained +F: hw/arm/ghes_cper.c +F: hw/acpi/ghes_cper_stub.c +F: qapi/acpi-hest.json + ppc4xx L: qemu-ppc@nongnu.org S: Orphan diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig index 1d4e9f0845..daabbe6cd1 100644 --- a/hw/acpi/Kconfig +++ b/hw/acpi/Kconfig @@ -51,6 +51,11 @@ config ACPI_APEI bool depends on ACPI +config GHES_CPER + bool + depends on ACPI_APEI + default y + config ACPI_PCI bool depends on ACPI && PCI diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c index d666f1b10b..06555905ce 100644 --- a/hw/acpi/ghes.c +++ b/hw/acpi/ghes.c @@ -553,7 +553,7 @@ void ghes_record_cper_errors(AcpiGhesState *ags, const void *cper, size_t len, /* Write the generic error data entry into guest memory */ cpu_physical_memory_write(cper_addr, cper, len); - notifier_list_notify(&acpi_generic_error_notifiers, NULL); + notifier_list_notify(&acpi_generic_error_notifiers, &source_id); } int acpi_ghes_memory_errors(AcpiGhesState *ags, uint16_t source_id, diff --git a/hw/acpi/ghes_cper.c b/hw/acpi/ghes_cper.c new file mode 100644 index 0000000000..31cb2ffabe --- /dev/null +++ b/hw/acpi/ghes_cper.c @@ -0,0 +1,40 @@ +/* + * CPER payload parser for error injection + * + * Copyright(C) 2024-2025 Huawei LTD. + * + * This code is licensed under the GPL version 2 or later. See the + * COPYING file in the top-level directory. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" + +#include "qemu/base64.h" +#include "qemu/error-report.h" +#include "qemu/uuid.h" +#include "qapi/qapi-commands-acpi-hest.h" +#include "hw/acpi/ghes.h" + +void qmp_inject_ghes_v2_error(const char *qmp_cper, Error **errp) +{ + AcpiGhesState *ags; + uint8_t *cper; + size_t len; + + ags = acpi_ghes_get_state(); + if (!ags) { + return; + } + + cper = qbase64_decode(qmp_cper, -1, &len, errp); + if (!cper) { + error_setg(errp, "missing GHES CPER payload"); + return; + } + + ghes_record_cper_errors(ags, cper, len, ACPI_HEST_SRC_ID_QMP, errp); + + g_free(cper); +} diff --git a/hw/acpi/ghes_cper_stub.c b/hw/acpi/ghes_cper_stub.c new file mode 100644 index 0000000000..b16be73502 --- /dev/null +++ b/hw/acpi/ghes_cper_stub.c @@ -0,0 +1,20 @@ +/* + * Stub interface for CPER payload parser for error injection + * + * Copyright(C) 2024-2025 Huawei LTD. + * + * This code is licensed under the GPL version 2 or later. See the + * COPYING file in the top-level directory. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qapi/qapi-commands-acpi-hest.h" +#include "hw/acpi/ghes.h" + +void qmp_inject_ghes_v2_error(const char *cper, Error **errp) +{ + error_setg(errp, "GHES QMP error inject is not compiled in"); +} diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build index 73f02b9691..56b5d1ec96 100644 --- a/hw/acpi/meson.build +++ b/hw/acpi/meson.build @@ -34,4 +34,6 @@ endif system_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c', 'ghes-stub.c', 'acpi_interface.c')) system_ss.add(when: 'CONFIG_ACPI_PCI_BRIDGE', if_false: files('pci-bridge-stub.c')) system_ss.add_all(when: 'CONFIG_ACPI', if_true: acpi_ss) +system_ss.add(when: 'CONFIG_GHES_CPER', if_true: files('ghes_cper.c')) +system_ss.add(when: 'CONFIG_GHES_CPER', if_false: files('ghes_cper_stub.c')) system_ss.add(files('acpi-qmp-cmds.c')) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 2b63008df0..8bb6b60515 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -1128,6 +1128,7 @@ static void acpi_align_size(GArray *blob, unsigned align) static const AcpiNotificationSourceId hest_ghes_notify[] = { { ACPI_HEST_SRC_ID_SYNC, ACPI_GHES_NOTIFY_SEA }, + { ACPI_HEST_SRC_ID_QMP, ACPI_GHES_NOTIFY_GPIO }, }; static const AcpiNotificationSourceId hest_ghes_notify_10_0[] = { diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 6960f6113f..aad557be1a 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1052,6 +1052,13 @@ static void virt_powerdown_req(Notifier *n, void *opaque) static void virt_generic_error_req(Notifier *n, void *opaque) { + uint16_t *source_id = opaque; + + /* Currently, only QMP source ID is async */ + if (*source_id != ACPI_HEST_SRC_ID_QMP) { + return; + } + VirtMachineState *s = container_of(n, VirtMachineState, generic_error_notifier); acpi_send_event(s->acpi_dev, ACPI_GENERIC_ERROR); diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h index 390943e46d..df2ecbf6e4 100644 --- a/include/hw/acpi/ghes.h +++ b/include/hw/acpi/ghes.h @@ -65,6 +65,7 @@ enum AcpiGhesNotifyType { */ enum AcpiGhesSourceID { ACPI_HEST_SRC_ID_SYNC, + ACPI_HEST_SRC_ID_QMP, /* Use it only for QMP injected errors */ }; typedef struct AcpiNotificationSourceId { diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index e14ea0f9d4..04a09af354 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -33,6 +33,7 @@ #include "exec/hwaddr.h" #include "qemu/notify.h" #include "hw/boards.h" +#include "hw/acpi/ghes.h" #include "hw/arm/boot.h" #include "hw/arm/bsa.h" #include "hw/block/flash.h" diff --git a/qapi/acpi-hest.json b/qapi/acpi-hest.json new file mode 100644 index 0000000000..28af1266a7 --- /dev/null +++ b/qapi/acpi-hest.json @@ -0,0 +1,36 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# SPDX-License-Identifier: GPL-2.0-or-later + +## +# == GHESv2 CPER Error Injection +# +# Defined since ACPI Specification 6.1, +# section 18.3.2.8 Generic Hardware Error Source version 2. See: +# +# https://uefi.org/sites/default/files/resources/ACPI_6_1.pdf +## + + +## +# @inject-ghes-v2-error: +# +# Inject an error with additional ACPI 6.1 GHESv2 error information +# +# @cper: contains a base64 encoded string with raw data for a single +# CPER record with Generic Error Status Block, Generic Error Data +# Entry and generic error data payload, as described at +# https://uefi.org/specs/UEFI/2.10/Apx_N_Common_Platform_Error_Record.html#format +# +# Features: +# +# @unstable: This command is experimental. +# +# Since: 10.2 +## +{ 'command': 'inject-ghes-v2-error', + 'data': { + 'cper': 'str' + }, + 'features': [ 'unstable' ] +} diff --git a/qapi/meson.build b/qapi/meson.build index ca6b61a608..a46269b5a0 100644 --- a/qapi/meson.build +++ b/qapi/meson.build @@ -59,6 +59,7 @@ if have_system qapi_all_modules += [ 'accelerator', 'acpi', + 'acpi-hest', 'audio', 'cryptodev', 'qdev', diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json index 82f111ba06..b93dd68d94 100644 --- a/qapi/qapi-schema.json +++ b/qapi/qapi-schema.json @@ -68,6 +68,7 @@ { 'include': 'misc-i386.json' } { 'include': 'audio.json' } { 'include': 'acpi.json' } +{ 'include': 'acpi-hest.json' } { 'include': 'pci.json' } { 'include': 'stats.json' } { 'include': 'virtio.json' }