mirror of
				https://gitlab.com/qemu-project/qemu.git
				synced 2025-10-30 07:57:14 +08:00 
			
		
		
		
	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
					Mauro Carvalho Chehab
				
			
				
					committed by
					
						 Michael S. Tsirkin
						Michael S. Tsirkin
					
				
			
			
				
	
			
			
			 Michael S. Tsirkin
						Michael S. Tsirkin
					
				
			
						parent
						
							d352e33e1f
						
					
				
				
					commit
					ddd8f3baa2
				
			| @ -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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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
									
								
							
							
						
						
									
										40
									
								
								hw/acpi/ghes_cper.c
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										20
									
								
								hw/acpi/ghes_cper_stub.c
									
									
									
									
									
										Normal 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"); | ||||
| } | ||||
| @ -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')) | ||||
|  | ||||
| @ -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[] = { | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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 { | ||||
|  | ||||
| @ -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
									
								
							
							
						
						
									
										36
									
								
								qapi/acpi-hest.json
									
									
									
									
									
										Normal 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' ] | ||||
| } | ||||
| @ -59,6 +59,7 @@ if have_system | ||||
|   qapi_all_modules += [ | ||||
|     'accelerator', | ||||
|     'acpi', | ||||
|     'acpi-hest', | ||||
|     'audio', | ||||
|     'cryptodev', | ||||
|     'qdev', | ||||
|  | ||||
| @ -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' } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user