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 <Jonathan.Cameron@huawei.com>
Co-authored-by: Shiju Jose <shiju.jose@huawei.com>
Co-authored-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Acked-by: Igor Mammedov <imammedo@redhat.com>
Acked-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <81e2118b3c8b7e5da341817f277d61251655e0db.1758610789.git.mchehab+huawei@kernel.org>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Mauro Carvalho Chehab
2025-09-23 09:04:07 +02:00
committed by Michael S. Tsirkin
parent d352e33e1f
commit ddd8f3baa2
13 changed files with 123 additions and 1 deletions

View File

@ -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 <mchehab+huawei@kernel.org>
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

View File

@ -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

View File

@ -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,

40
hw/acpi/ghes_cper.c Normal file
View File

@ -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);
}

20
hw/acpi/ghes_cper_stub.c Normal file
View File

@ -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");
}

View File

@ -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'))

View File

@ -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[] = {

View File

@ -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);

View File

@ -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 {

View File

@ -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"

36
qapi/acpi-hest.json Normal file
View File

@ -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' ]
}

View File

@ -59,6 +59,7 @@ if have_system
qapi_all_modules += [
'accelerator',
'acpi',
'acpi-hest',
'audio',
'cryptodev',
'qdev',

View File

@ -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' }