* [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation
@ 2024-08-08 12:26 Mauro Carvalho Chehab
2024-08-08 12:26 ` [PATCH v6 01/10] acpi/generic_event_device: add an APEI error device Mauro Carvalho Chehab
` (10 more replies)
0 siblings, 11 replies; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2024-08-08 12:26 UTC (permalink / raw)
Cc: Jonathan Cameron, Shiju Jose, Mauro Carvalho Chehab, Ani Sinha,
Dongjiu Geng, Paolo Bonzini, Peter Maydell, Shannon Zhao,
qemu-arm, qemu-devel
Testing OS kernel ACPI APEI CPER support is tricky, as one depends on
having hardware with special-purpose BIOS and/or hardware.
With QEMU, it becomes a lot easier, as it can be done via QMP.
This series add support for injecting CPER records on ARM emulation.
The QEMU side changes add a QAPI able to do CPER error injection
on ARM, with a raw data parameter, making it very flexible.
A script is provided at the final patch implementing support for
ARM Processor CPER error injection according with ACPI 6.x and
UEFI 2.9A/2.10 specs, via QMP.
Injecting such errors can be done using the provided script:
$ ./scripts/ghes_inject.py arm
Error injected.
Produces a simple CPER register, properly handled by the Linux
Kernel:
[ 794.983753] {4}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 1
[ 794.984150] {4}[Hardware Error]: event severity: recoverable
[ 794.984391] {4}[Hardware Error]: Error 0, type: recoverable
[ 794.984652] {4}[Hardware Error]: section_type: ARM processor error
[ 794.984926] {4}[Hardware Error]: MIDR: 0x0000000000000000
[ 794.985184] {4}[Hardware Error]: running state: 0x0
[ 794.985411] {4}[Hardware Error]: Power State Coordination Interface state: 0
[ 794.985720] {4}[Hardware Error]: Error info structure 0:
[ 794.985960] {4}[Hardware Error]: num errors: 2
[ 794.986175] {4}[Hardware Error]: error_type: 0x02: cache error
[ 794.986442] {4}[Hardware Error]: error_info: 0x000000000091000f
[ 794.986755] {4}[Hardware Error]: transaction type: Data Access
[ 794.987027] {4}[Hardware Error]: cache error, operation type: Data write
[ 794.987310] {4}[Hardware Error]: cache level: 2
[ 794.987529] {4}[Hardware Error]: processor context not corrupted
[ 794.987867] [Firmware Warn]: GHES: Unhandled processor error type 0x02: cache error
More complex use cases can be done, like:
$ ./scripts/ghes_inject.py arm --mpidr 0x444 --running --affinity 1 \
--error-info 12345678 --vendor 0x13,123,4,5,1 --ctx-array 0,1,2,3,4,5 \
-t cache tlb bus micro-arch tlb,micro-arch
Error injected.
[ 899.181246] {5}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 1
[ 899.181769] {5}[Hardware Error]: event severity: recoverable
[ 899.182069] {5}[Hardware Error]: Error 0, type: recoverable
[ 899.182370] {5}[Hardware Error]: section_type: ARM processor error
[ 899.182689] {5}[Hardware Error]: MIDR: 0x0000000000000000
[ 899.182980] {5}[Hardware Error]: Multiprocessor Affinity Register (MPIDR): 0x0000000000000000
[ 899.183395] {5}[Hardware Error]: error affinity level: 0
[ 899.183683] {5}[Hardware Error]: running state: 0x1
[ 899.183962] {5}[Hardware Error]: Power State Coordination Interface state: 0
[ 899.184332] {5}[Hardware Error]: Error info structure 0:
[ 899.184610] {5}[Hardware Error]: num errors: 2
[ 899.184864] {5}[Hardware Error]: error_type: 0x02: cache error
[ 899.185181] {5}[Hardware Error]: error_info: 0x0000000000bc614e
[ 899.185504] {5}[Hardware Error]: cache level: 2
[ 899.185771] {5}[Hardware Error]: processor context not corrupted
[ 899.186082] {5}[Hardware Error]: Error info structure 1:
[ 899.186366] {5}[Hardware Error]: num errors: 2
[ 899.186613] {5}[Hardware Error]: error_type: 0x04: TLB error
[ 899.186929] {5}[Hardware Error]: error_info: 0x000000000054007f
[ 899.187236] {5}[Hardware Error]: transaction type: Instruction
[ 899.187588] {5}[Hardware Error]: TLB error, operation type: Instruction fetch
[ 899.187962] {5}[Hardware Error]: TLB level: 1
[ 899.188209] {5}[Hardware Error]: processor context not corrupted
[ 899.188535] {5}[Hardware Error]: the error has not been corrected
[ 899.188853] {5}[Hardware Error]: PC is imprecise
[ 899.189114] {5}[Hardware Error]: Error info structure 2:
[ 899.189404] {5}[Hardware Error]: num errors: 2
[ 899.189653] {5}[Hardware Error]: error_type: 0x08: bus error
[ 899.189967] {5}[Hardware Error]: error_info: 0x00000080d6460fff
[ 899.190293] {5}[Hardware Error]: transaction type: Generic
[ 899.190611] {5}[Hardware Error]: bus error, operation type: Generic read (type of instruction or data request cannot be determined)
[ 899.191174] {5}[Hardware Error]: affinity level at which the bus error occurred: 1
[ 899.191563] {5}[Hardware Error]: processor context corrupted
[ 899.191872] {5}[Hardware Error]: the error has been corrected
[ 899.192185] {5}[Hardware Error]: PC is imprecise
[ 899.192445] {5}[Hardware Error]: Program execution can be restarted reliably at the PC associated with the error.
[ 899.192939] {5}[Hardware Error]: participation type: Local processor observed
[ 899.193324] {5}[Hardware Error]: request timed out
[ 899.193596] {5}[Hardware Error]: address space: External Memory Access
[ 899.193945] {5}[Hardware Error]: memory access attributes:0x20
[ 899.194273] {5}[Hardware Error]: access mode: secure
[ 899.194544] {5}[Hardware Error]: Error info structure 3:
[ 899.194838] {5}[Hardware Error]: num errors: 2
[ 899.195088] {5}[Hardware Error]: error_type: 0x10: micro-architectural error
[ 899.195456] {5}[Hardware Error]: error_info: 0x0000000078da03ff
[ 899.195782] {5}[Hardware Error]: Error info structure 4:
[ 899.196070] {5}[Hardware Error]: num errors: 2
[ 899.196331] {5}[Hardware Error]: error_type: 0x14: TLB error|micro-architectural error
[ 899.196733] {5}[Hardware Error]: Context info structure 0:
[ 899.197024] {5}[Hardware Error]: register context type: AArch64 EL1 context registers
[ 899.197427] {5}[Hardware Error]: 00000000: 00000000 00000000
[ 899.197741] {5}[Hardware Error]: Vendor specific error info has 5 bytes:
[ 899.198096] {5}[Hardware Error]: 00000000: 13 7b 04 05 01 .{...
[ 899.198610] [Firmware Warn]: GHES: Unhandled processor error type 0x02: cache error
[ 899.199000] [Firmware Warn]: GHES: Unhandled processor error type 0x04: TLB error
[ 899.199388] [Firmware Warn]: GHES: Unhandled processor error type 0x08: bus error
[ 899.199767] [Firmware Warn]: GHES: Unhandled processor error type 0x10: micro-architectural error
[ 899.200194] [Firmware Warn]: GHES: Unhandled processor error type 0x14: TLB error|micro-architectural error
---
v6:
- PNP0C33 device creation moved to aml-build.c;
- acpi_ghes record functions now use ACPI notify parameter,
instead of source ID;
- the number of source IDs is now automatically calculated;
- some code cleanups and function/var renames;
- some fixes and cleanups at the error injection script;
- ghes cper stub now produces an error if cper JSON is not compiled;
- Offset calculation logic for GHES was refactored;
- Updated documentation to reflect the GHES allocated size;
- Added a x-mpidr object for QOM usage;
- Added a patch making usage of x-mpidr field at ARM injection
script;
v5:
- CPER guid is now passing as string;
- raw-data is now passed with base64 encode;
- Removed several GPIO left-overs from arm/virt.c changes;
- Lots of cleanups and improvements at the error injection script.
It now better handles QMP dialog and doesn't print debug messages.
Also, code was split on two modules, to make easier to add more
error injection commands.
v4:
- CPER generation moved to happen outside QEMU;
- One patch adding support for mpidr query was removed.
v3:
- patch 1 cleanups with some comment changes and adding another place where
the poweroff GPIO define should be used. No changes on other patches (except
due to conflict resolution).
v2:
- added a new patch using a define for GPIO power pin;
- patch 2 changed to also use a define for generic error GPIO pin;
- a couple cleanups at patch 2 removing uneeded else clauses.
Jonathan Cameron (1):
acpi/ghes: Add support for GED error device
Mauro Carvalho Chehab (9):
acpi/generic_event_device: add an APEI error device
arm/virt: Wire up a GED error device for ACPI / GHES
qapi/ghes-cper: add an interface to do generic CPER error injection
acpi/ghes: rework the logic to handle HEST source ID
acpi/ghes: add support for generic error injection via QAPI
docs: acpi_hest_ghes: fix documentation for CPER size
scripts/ghes_inject: add a script to generate GHES error inject
target/arm: add an experimental mpidr arm cpu property object
scripts/arm_processor_error.py: retrieve mpidr if not filled
MAINTAINERS | 10 +
docs/specs/acpi_hest_ghes.rst | 6 +-
hw/acpi/Kconfig | 5 +
hw/acpi/aml-build.c | 10 +
hw/acpi/generic_event_device.c | 8 +
hw/acpi/ghes-stub.c | 3 +-
hw/acpi/ghes.c | 308 ++++++++++++++----
hw/acpi/ghes_cper.c | 45 +++
hw/acpi/ghes_cper_stub.c | 19 ++
hw/acpi/meson.build | 2 +
hw/arm/Kconfig | 5 +
hw/arm/virt-acpi-build.c | 1 +
hw/arm/virt.c | 12 +-
include/hw/acpi/acpi_dev_interface.h | 1 +
include/hw/acpi/aml-build.h | 2 +
include/hw/acpi/generic_event_device.h | 1 +
include/hw/acpi/ghes.h | 24 +-
include/hw/arm/virt.h | 1 +
qapi/ghes-cper.json | 55 ++++
qapi/meson.build | 1 +
qapi/qapi-schema.json | 1 +
scripts/arm_processor_error.py | 389 ++++++++++++++++++++++
scripts/ghes_inject.py | 48 +++
scripts/qmp_helper.py | 431 +++++++++++++++++++++++++
target/arm/cpu.c | 1 +
target/arm/cpu.h | 1 +
target/arm/helper.c | 10 +-
27 files changed, 1316 insertions(+), 84 deletions(-)
create mode 100644 hw/acpi/ghes_cper.c
create mode 100644 hw/acpi/ghes_cper_stub.c
create mode 100644 qapi/ghes-cper.json
create mode 100644 scripts/arm_processor_error.py
create mode 100755 scripts/ghes_inject.py
create mode 100644 scripts/qmp_helper.py
--
2.45.2
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v6 01/10] acpi/generic_event_device: add an APEI error device
2024-08-08 12:26 [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
@ 2024-08-08 12:26 ` Mauro Carvalho Chehab
2024-08-12 11:20 ` Igor Mammedov
2024-08-08 12:26 ` [PATCH v6 02/10] arm/virt: Wire up a GED error device for ACPI / GHES Mauro Carvalho Chehab
` (9 subsequent siblings)
10 siblings, 1 reply; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2024-08-08 12:26 UTC (permalink / raw)
Cc: Jonathan Cameron, Shiju Jose, Mauro Carvalho Chehab,
Michael S. Tsirkin, Ani Sinha, Igor Mammedov, linux-kernel,
qemu-devel
Adds a generic error device to handle generic hardware error
events as specified at ACPI 6.5 specification at 18.3.2.7.2:
https://uefi.org/specs/ACPI/6.5/18_Platform_Error_Interfaces.html#event-notification-for-generic-error-sources
using HID PNP0C33.
The PNP0C33 device is used to report hardware errors to
the guest via ACPI APEI Generic Hardware Error Source (GHES).
Co-authored-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Co-authored-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
hw/acpi/aml-build.c | 10 ++++++++++
hw/acpi/generic_event_device.c | 8 ++++++++
include/hw/acpi/acpi_dev_interface.h | 1 +
include/hw/acpi/aml-build.h | 2 ++
include/hw/acpi/generic_event_device.h | 1 +
5 files changed, 22 insertions(+)
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 6d4517cfbe3d..cb167523859f 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -2520,3 +2520,13 @@ Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source)
return var;
}
+
+/* ACPI 5.0: 18.3.2.6.2 Event Notification For Generic Error Sources */
+Aml *aml_error_device(void)
+{
+ Aml *dev = aml_device(ACPI_APEI_ERROR_DEVICE);
+ aml_append(dev, aml_name_decl("_HID", aml_string("PNP0C33")));
+ aml_append(dev, aml_name_decl("_UID", aml_int(0)));
+
+ return dev;
+}
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
index 15b4c3ebbf24..1673e9695be3 100644
--- a/hw/acpi/generic_event_device.c
+++ b/hw/acpi/generic_event_device.c
@@ -26,6 +26,7 @@ static const uint32_t ged_supported_events[] = {
ACPI_GED_PWR_DOWN_EVT,
ACPI_GED_NVDIMM_HOTPLUG_EVT,
ACPI_GED_CPU_HOTPLUG_EVT,
+ ACPI_GED_ERROR_EVT
};
/*
@@ -116,6 +117,11 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev,
aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
aml_int(0x80)));
break;
+ case ACPI_GED_ERROR_EVT:
+ aml_append(if_ctx,
+ aml_notify(aml_name(ACPI_APEI_ERROR_DEVICE),
+ aml_int(0x80)));
+ break;
case ACPI_GED_NVDIMM_HOTPLUG_EVT:
aml_append(if_ctx,
aml_notify(aml_name("\\_SB.NVDR"),
@@ -295,6 +301,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
sel = ACPI_GED_MEM_HOTPLUG_EVT;
} else if (ev & ACPI_POWER_DOWN_STATUS) {
sel = ACPI_GED_PWR_DOWN_EVT;
+ } else if (ev & ACPI_GENERIC_ERROR) {
+ sel = ACPI_GED_ERROR_EVT;
} else if (ev & ACPI_NVDIMM_HOTPLUG_STATUS) {
sel = ACPI_GED_NVDIMM_HOTPLUG_EVT;
} else if (ev & ACPI_CPU_HOTPLUG_STATUS) {
diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h
index 68d9d15f50aa..8294f8f0ccca 100644
--- a/include/hw/acpi/acpi_dev_interface.h
+++ b/include/hw/acpi/acpi_dev_interface.h
@@ -13,6 +13,7 @@ typedef enum {
ACPI_NVDIMM_HOTPLUG_STATUS = 16,
ACPI_VMGENID_CHANGE_STATUS = 32,
ACPI_POWER_DOWN_STATUS = 64,
+ ACPI_GENERIC_ERROR = 128,
} AcpiEventStatusBits;
#define TYPE_ACPI_DEVICE_IF "acpi-device-interface"
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index a3784155cb33..44d1a6af0c69 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -252,6 +252,7 @@ struct CrsRangeSet {
/* Consumer/Producer */
#define AML_SERIAL_BUS_FLAG_CONSUME_ONLY (1 << 1)
+#define ACPI_APEI_ERROR_DEVICE "GEDD"
/**
* init_aml_allocator:
*
@@ -382,6 +383,7 @@ Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz,
uint8_t channel);
Aml *aml_sleep(uint64_t msec);
Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source);
+Aml *aml_error_device(void);
/* Block AML object primitives */
Aml *aml_scope(const char *name_format, ...) G_GNUC_PRINTF(1, 2);
diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
index 40af3550b56d..9ace8fe70328 100644
--- a/include/hw/acpi/generic_event_device.h
+++ b/include/hw/acpi/generic_event_device.h
@@ -98,6 +98,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED)
#define ACPI_GED_PWR_DOWN_EVT 0x2
#define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4
#define ACPI_GED_CPU_HOTPLUG_EVT 0x8
+#define ACPI_GED_ERROR_EVT 0x10
typedef struct GEDState {
MemoryRegion evt;
--
2.45.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v6 02/10] arm/virt: Wire up a GED error device for ACPI / GHES
2024-08-08 12:26 [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
2024-08-08 12:26 ` [PATCH v6 01/10] acpi/generic_event_device: add an APEI error device Mauro Carvalho Chehab
@ 2024-08-08 12:26 ` Mauro Carvalho Chehab
2024-08-12 11:27 ` Igor Mammedov
2024-08-08 12:26 ` [PATCH v6 03/10] acpi/ghes: Add support for GED error device Mauro Carvalho Chehab
` (8 subsequent siblings)
10 siblings, 1 reply; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2024-08-08 12:26 UTC (permalink / raw)
Cc: Jonathan Cameron, Shiju Jose, Mauro Carvalho Chehab,
Michael S. Tsirkin, Ani Sinha, Dongjiu Geng, Igor Mammedov,
Peter Maydell, Shannon Zhao, linux-kernel, qemu-arm, qemu-devel
Adds support to ARM virtualization to allow handling
generic error ACPI Event via GED & error source device.
It is aligned with Linux Kernel patch:
https://lore.kernel.org/lkml/1272350481-27951-8-git-send-email-ying.huang@intel.com/
Co-authored-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Co-authored-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
hw/acpi/ghes.c | 3 +++
hw/arm/virt-acpi-build.c | 1 +
hw/arm/virt.c | 12 +++++++++++-
include/hw/acpi/ghes.h | 3 +++
include/hw/arm/virt.h | 1 +
5 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
index e9511d9b8f71..13b105c5d02d 100644
--- a/hw/acpi/ghes.c
+++ b/hw/acpi/ghes.c
@@ -444,6 +444,9 @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
return ret;
}
+NotifierList acpi_generic_error_notifiers =
+ NOTIFIER_LIST_INITIALIZER(error_device_notifiers);
+
bool acpi_ghes_present(void)
{
AcpiGedState *acpi_ged_state;
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index f76fb117adff..1769467d23b2 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -858,6 +858,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
}
acpi_dsdt_add_power_button(scope);
+ aml_append(scope, aml_error_device());
#ifdef CONFIG_TPM
acpi_dsdt_add_tpm(scope, vms);
#endif
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 687fe0bb8bc9..22448e5c5b73 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -677,7 +677,7 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
DeviceState *dev;
MachineState *ms = MACHINE(vms);
int irq = vms->irqmap[VIRT_ACPI_GED];
- uint32_t event = ACPI_GED_PWR_DOWN_EVT;
+ uint32_t event = ACPI_GED_PWR_DOWN_EVT | ACPI_GED_ERROR_EVT;
if (ms->ram_slots) {
event |= ACPI_GED_MEM_HOTPLUG_EVT;
@@ -1009,6 +1009,13 @@ static void virt_powerdown_req(Notifier *n, void *opaque)
}
}
+static void virt_generic_error_req(Notifier *n, void *opaque)
+{
+ VirtMachineState *s = container_of(n, VirtMachineState, generic_error_notifier);
+
+ acpi_send_event(s->acpi_dev, ACPI_GENERIC_ERROR);
+}
+
static void create_gpio_keys(char *fdt, DeviceState *pl061_dev,
uint32_t phandle)
{
@@ -2385,6 +2392,9 @@ static void machvirt_init(MachineState *machine)
if (has_ged && aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) {
vms->acpi_dev = create_acpi_ged(vms);
+ vms->generic_error_notifier.notify = virt_generic_error_req;
+ notifier_list_add(&acpi_generic_error_notifiers,
+ &vms->generic_error_notifier);
} else {
create_gpio_devices(vms, VIRT_GPIO, sysmem);
}
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
index 674f6958e905..fb80897e7eac 100644
--- a/include/hw/acpi/ghes.h
+++ b/include/hw/acpi/ghes.h
@@ -23,6 +23,9 @@
#define ACPI_GHES_H
#include "hw/acpi/bios-linker-loader.h"
+#include "qemu/notify.h"
+
+extern NotifierList acpi_generic_error_notifiers;
/*
* Values for Hardware Error Notification Type field
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index a4d937ed45ac..ad9f6e94dcc5 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -175,6 +175,7 @@ struct VirtMachineState {
DeviceState *gic;
DeviceState *acpi_dev;
Notifier powerdown_notifier;
+ Notifier generic_error_notifier;
PCIBus *bus;
char *oem_id;
char *oem_table_id;
--
2.45.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v6 03/10] acpi/ghes: Add support for GED error device
2024-08-08 12:26 [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
2024-08-08 12:26 ` [PATCH v6 01/10] acpi/generic_event_device: add an APEI error device Mauro Carvalho Chehab
2024-08-08 12:26 ` [PATCH v6 02/10] arm/virt: Wire up a GED error device for ACPI / GHES Mauro Carvalho Chehab
@ 2024-08-08 12:26 ` Mauro Carvalho Chehab
2024-08-12 11:28 ` Igor Mammedov
2024-08-08 12:26 ` [PATCH v6 04/10] qapi/ghes-cper: add an interface to do generic CPER error injection Mauro Carvalho Chehab
` (7 subsequent siblings)
10 siblings, 1 reply; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2024-08-08 12:26 UTC (permalink / raw)
Cc: Jonathan Cameron, Shiju Jose, Michael S. Tsirkin, Ani Sinha,
Dongjiu Geng, Igor Mammedov, linux-kernel, qemu-arm, qemu-devel,
Mauro Carvalho Chehab
From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
As a GED error device is now defined, add another type
of notification.
Add error notification to GHES v2 using a GED error device GED
triggered via interrupt.
[mchehab: do some cleanups at ACPI_HEST_SRC_ID_* checks and
rename HEST event to better identify GED interrupt OSPM]
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
hw/acpi/ghes.c | 12 +++++++++---
include/hw/acpi/ghes.h | 3 ++-
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
index 13b105c5d02d..d6cbeed6e3d5 100644
--- a/hw/acpi/ghes.c
+++ b/hw/acpi/ghes.c
@@ -34,8 +34,8 @@
/* The max size in bytes for one error block */
#define ACPI_GHES_MAX_RAW_DATA_LENGTH (1 * KiB)
-/* Now only support ARMv8 SEA notification type error source */
-#define ACPI_GHES_ERROR_SOURCE_COUNT 1
+/* Support ARMv8 SEA notification type error source and GPIO interrupt. */
+#define ACPI_GHES_ERROR_SOURCE_COUNT 2
/* Generic Hardware Error Source version 2 */
#define ACPI_GHES_SOURCE_GENERIC_ERROR_V2 10
@@ -290,6 +290,9 @@ void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker)
static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker)
{
uint64_t address_offset;
+
+ assert(source_id < ACPI_HEST_SRC_ID_RESERVED);
+
/*
* Type:
* Generic Hardware Error Source version 2(GHESv2 - Type 10)
@@ -327,6 +330,9 @@ static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker)
*/
build_ghes_hw_error_notification(table_data, ACPI_GHES_NOTIFY_SEA);
break;
+ case ACPI_HEST_NOTIFY_EXTERNAL:
+ build_ghes_hw_error_notification(table_data, ACPI_GHES_NOTIFY_GPIO);
+ break;
default:
error_report("Not support this error source");
abort();
@@ -370,6 +376,7 @@ void acpi_build_hest(GArray *table_data, BIOSLinker *linker,
/* Error Source Count */
build_append_int_noprefix(table_data, ACPI_GHES_ERROR_SOURCE_COUNT, 4);
build_ghes_v2(table_data, ACPI_HEST_SRC_ID_SEA, linker);
+ build_ghes_v2(table_data, ACPI_HEST_NOTIFY_EXTERNAL, linker);
acpi_table_end(linker, &table);
}
@@ -406,7 +413,6 @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
start_addr = le64_to_cpu(ags->ghes_addr_le);
if (physical_address) {
-
if (source_id < ACPI_HEST_SRC_ID_RESERVED) {
start_addr += source_id * sizeof(uint64_t);
}
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
index fb80897e7eac..ce6f82a1155a 100644
--- a/include/hw/acpi/ghes.h
+++ b/include/hw/acpi/ghes.h
@@ -59,9 +59,10 @@ enum AcpiGhesNotifyType {
ACPI_GHES_NOTIFY_RESERVED = 12
};
+/* Those are used as table indexes when building GHES tables */
enum {
ACPI_HEST_SRC_ID_SEA = 0,
- /* future ids go here */
+ ACPI_HEST_NOTIFY_EXTERNAL,
ACPI_HEST_SRC_ID_RESERVED,
};
--
2.45.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v6 04/10] qapi/ghes-cper: add an interface to do generic CPER error injection
2024-08-08 12:26 [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
` (2 preceding siblings ...)
2024-08-08 12:26 ` [PATCH v6 03/10] acpi/ghes: Add support for GED error device Mauro Carvalho Chehab
@ 2024-08-08 12:26 ` Mauro Carvalho Chehab
2024-08-08 13:23 ` Markus Armbruster
2024-08-12 11:57 ` Igor Mammedov
2024-08-08 12:26 ` [PATCH v6 05/10] acpi/ghes: rework the logic to handle HEST source ID Mauro Carvalho Chehab
` (6 subsequent siblings)
10 siblings, 2 replies; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2024-08-08 12:26 UTC (permalink / raw)
Cc: Jonathan Cameron, Shiju Jose, Mauro Carvalho Chehab,
Michael S. Tsirkin, Ani Sinha, Dongjiu Geng, Eric Blake,
Igor Mammedov, Markus Armbruster, Michael Roth, Paolo Bonzini,
Peter Maydell, linux-kernel, qemu-arm, qemu-devel
Creates a QMP command to be used for generic ACPI APEI hardware error
injection (HEST) via GHESv2.
The actual GHES code will be added at the followup patch.
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
MAINTAINERS | 7 +++++
hw/acpi/Kconfig | 5 ++++
hw/acpi/ghes_cper.c | 45 ++++++++++++++++++++++++++++++++
hw/acpi/ghes_cper_stub.c | 19 ++++++++++++++
hw/acpi/meson.build | 2 ++
hw/arm/Kconfig | 5 ++++
include/hw/acpi/ghes.h | 7 +++++
qapi/ghes-cper.json | 55 ++++++++++++++++++++++++++++++++++++++++
qapi/meson.build | 1 +
qapi/qapi-schema.json | 1 +
10 files changed, 147 insertions(+)
create mode 100644 hw/acpi/ghes_cper.c
create mode 100644 hw/acpi/ghes_cper_stub.c
create mode 100644 qapi/ghes-cper.json
diff --git a/MAINTAINERS b/MAINTAINERS
index 10af21263293..a0c36f9b5d0c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2077,6 +2077,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/ghes-cper.json
+
ppc4xx
L: qemu-ppc@nongnu.org
S: Orphan
diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
index e07d3204eb36..73ffbb82c150 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_cper.c b/hw/acpi/ghes_cper.c
new file mode 100644
index 000000000000..7aa7e71e90dc
--- /dev/null
+++ b/hw/acpi/ghes_cper.c
@@ -0,0 +1,45 @@
+/*
+ * ARM Processor error injection
+ *
+ * Copyright(C) 2024 Huawei LTD.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+
+#include "qemu/base64.h"
+#include "qemu/error-report.h"
+#include "qemu/uuid.h"
+#include "qapi/qapi-commands-ghes-cper.h"
+#include "hw/acpi/ghes.h"
+
+void qmp_ghes_cper(CommonPlatformErrorRecord *qmp_cper,
+ Error **errp)
+{
+ int rc;
+ AcpiGhesCper cper;
+ QemuUUID be_uuid, le_uuid;
+
+ rc = qemu_uuid_parse(qmp_cper->notification_type, &be_uuid);
+ if (rc) {
+ error_setg(errp, "GHES: Invalid UUID: %s",
+ qmp_cper->notification_type);
+ return;
+ }
+
+ le_uuid = qemu_uuid_bswap(be_uuid);
+ cper.guid = le_uuid.data;
+
+ cper.data = qbase64_decode(qmp_cper->raw_data, -1,
+ &cper.data_len, errp);
+ if (!cper.data) {
+ return;
+ }
+
+ /* TODO: call a function at ghes */
+
+ g_free(cper.data);
+}
diff --git a/hw/acpi/ghes_cper_stub.c b/hw/acpi/ghes_cper_stub.c
new file mode 100644
index 000000000000..2358e039b181
--- /dev/null
+++ b/hw/acpi/ghes_cper_stub.c
@@ -0,0 +1,19 @@
+/*
+ * ARM Processor error injection
+ *
+ * Copyright(C) 2024 Huawei LTD.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qapi/qapi-commands-ghes-cper.h"
+#include "hw/acpi/ghes.h"
+
+void qmp_ghes_cper(CommonPlatformErrorRecord *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 fa5c07db9068..6cbf430eb66d 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/Kconfig b/hw/arm/Kconfig
index 1ad60da7aa2d..bed6ba27d715 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -712,3 +712,8 @@ config ARMSSE
select UNIMP
select SSE_COUNTER
select SSE_TIMER
+
+config GHES_CPER
+ bool
+ depends on ARM
+ default y if AARCH64
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
index ce6f82a1155a..a7a18c7b50cf 100644
--- a/include/hw/acpi/ghes.h
+++ b/include/hw/acpi/ghes.h
@@ -23,6 +23,7 @@
#define ACPI_GHES_H
#include "hw/acpi/bios-linker-loader.h"
+#include "qapi/error.h"
#include "qemu/notify.h"
extern NotifierList acpi_generic_error_notifiers;
@@ -78,6 +79,12 @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
GArray *hardware_errors);
int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr);
+typedef struct AcpiGhesCper {
+ uint8_t *guid;
+ uint8_t *data;
+ size_t data_len;
+} AcpiGhesCper;
+
/**
* acpi_ghes_present: Report whether ACPI GHES table is present
*
diff --git a/qapi/ghes-cper.json b/qapi/ghes-cper.json
new file mode 100644
index 000000000000..3cc4f9f2aaa9
--- /dev/null
+++ b/qapi/ghes-cper.json
@@ -0,0 +1,55 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+
+##
+# = GHESv2 CPER Error Injection
+#
+# These are defined at
+# ACPI 6.2: 18.3.2.8 Generic Hardware Error Source version 2
+# (GHESv2 - Type 10)
+##
+
+##
+# @CommonPlatformErrorRecord:
+#
+# Common Platform Error Record - CPER - as defined at the UEFI
+# specification. See
+# https://uefi.org/specs/UEFI/2.10/Apx_N_Common_Platform_Error_Record.html#record-header
+# for more details.
+#
+# @notification-type: pre-assigned GUID string indicating the record
+# association with an error event notification type, as defined
+# at https://uefi.org/specs/UEFI/2.10/Apx_N_Common_Platform_Error_Record.html#record-header
+#
+# @raw-data: Contains a base64 encoded string with the payload of
+# the CPER.
+#
+# Since: 9.2
+##
+{ 'struct': 'CommonPlatformErrorRecord',
+ 'data': {
+ 'notification-type': 'str',
+ 'raw-data': 'str'
+ }
+}
+
+##
+# @ghes-cper:
+#
+# Inject ARM Processor error with data to be filled according with
+# ACPI 6.2 GHESv2 spec.
+#
+# @cper: a single CPER record to be sent to the guest OS.
+#
+# Features:
+#
+# @unstable: This command is experimental.
+#
+# Since: 9.2
+##
+{ 'command': 'ghes-cper',
+ 'data': {
+ 'cper': 'CommonPlatformErrorRecord'
+ },
+ 'features': [ 'unstable' ]
+}
diff --git a/qapi/meson.build b/qapi/meson.build
index e7bc54e5d047..bd13cd7d40c9 100644
--- a/qapi/meson.build
+++ b/qapi/meson.build
@@ -35,6 +35,7 @@ qapi_all_modules = [
'dump',
'ebpf',
'error',
+ 'ghes-cper',
'introspect',
'job',
'machine-common',
diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json
index b1581988e4eb..c1a267399fe5 100644
--- a/qapi/qapi-schema.json
+++ b/qapi/qapi-schema.json
@@ -75,6 +75,7 @@
{ 'include': 'misc-target.json' }
{ 'include': 'audio.json' }
{ 'include': 'acpi.json' }
+{ 'include': 'ghes-cper.json' }
{ 'include': 'pci.json' }
{ 'include': 'stats.json' }
{ 'include': 'virtio.json' }
--
2.45.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v6 05/10] acpi/ghes: rework the logic to handle HEST source ID
2024-08-08 12:26 [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
` (3 preceding siblings ...)
2024-08-08 12:26 ` [PATCH v6 04/10] qapi/ghes-cper: add an interface to do generic CPER error injection Mauro Carvalho Chehab
@ 2024-08-08 12:26 ` Mauro Carvalho Chehab
2024-08-08 12:26 ` [PATCH v6 06/10] acpi/ghes: add support for generic error injection via QAPI Mauro Carvalho Chehab
` (5 subsequent siblings)
10 siblings, 0 replies; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2024-08-08 12:26 UTC (permalink / raw)
Cc: Jonathan Cameron, Shiju Jose, Mauro Carvalho Chehab,
Michael S. Tsirkin, Ani Sinha, Dongjiu Geng, Igor Mammedov,
linux-kernel, qemu-arm, qemu-devel
The current logic is based on a lot of duct tape, with
offsets calculated based on one define with the number of
source IDs and an enum.
Rewrite the logic in a way that it would be more resilient
of code changes, by moving the source ID count to an enum
and make the offset calculus more explicit.
Such change was inspired on a patch from Jonathan Cameron
splitting the logic to get the CPER address on a separate
function, as this will be needed to support generic error
injection.
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
hw/acpi/ghes-stub.c | 3 +-
hw/acpi/ghes.c | 225 ++++++++++++++++++++++++++++-------------
include/hw/acpi/ghes.h | 12 +--
3 files changed, 158 insertions(+), 82 deletions(-)
diff --git a/hw/acpi/ghes-stub.c b/hw/acpi/ghes-stub.c
index c315de1802d6..8762449870b5 100644
--- a/hw/acpi/ghes-stub.c
+++ b/hw/acpi/ghes-stub.c
@@ -11,7 +11,8 @@
#include "qemu/osdep.h"
#include "hw/acpi/ghes.h"
-int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
+int acpi_ghes_record_errors(enum AcpiGhesNotifyType notify,
+ uint64_t physical_address)
{
return -1;
}
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
index d6cbeed6e3d5..26e93dd0f6e2 100644
--- a/hw/acpi/ghes.c
+++ b/hw/acpi/ghes.c
@@ -34,8 +34,16 @@
/* The max size in bytes for one error block */
#define ACPI_GHES_MAX_RAW_DATA_LENGTH (1 * KiB)
-/* Support ARMv8 SEA notification type error source and GPIO interrupt. */
-#define ACPI_GHES_ERROR_SOURCE_COUNT 2
+/*
+ * ID numbers used to fill HEST source ID field
+ */
+enum AcpiHestSourceId {
+ ACPI_HEST_SRC_ID_SEA,
+ ACPI_HEST_SRC_ID_GED,
+
+ /* Shall be the last one */
+ ACPI_HEST_SRC_ID_COUNT
+} AcpiHestSourceId;
/* Generic Hardware Error Source version 2 */
#define ACPI_GHES_SOURCE_GENERIC_ERROR_V2 10
@@ -241,12 +249,12 @@ void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker)
int i, error_status_block_offset;
/* Build error_block_address */
- for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
+ for (i = 0; i < ACPI_HEST_SRC_ID_COUNT; i++) {
build_append_int_noprefix(hardware_errors, 0, sizeof(uint64_t));
}
/* Build read_ack_register */
- for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
+ for (i = 0; i < ACPI_HEST_SRC_ID_COUNT; i++) {
/*
* Initialize the value of read_ack_register to 1, so GHES can be
* writable after (re)boot.
@@ -261,13 +269,13 @@ void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker)
/* Reserve space for Error Status Data Block */
acpi_data_push(hardware_errors,
- ACPI_GHES_MAX_RAW_DATA_LENGTH * ACPI_GHES_ERROR_SOURCE_COUNT);
+ ACPI_GHES_MAX_RAW_DATA_LENGTH * ACPI_HEST_SRC_ID_COUNT);
/* Tell guest firmware to place hardware_errors blob into RAM */
bios_linker_loader_alloc(linker, ACPI_GHES_ERRORS_FW_CFG_FILE,
hardware_errors, sizeof(uint64_t), false);
- for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
+ for (i = 0; i < ACPI_HEST_SRC_ID_COUNT; i++) {
/*
* Tell firmware to patch error_block_address entries to point to
* corresponding "Generic Error Status Block"
@@ -286,12 +294,95 @@ void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker)
0, sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, 0);
}
+static bool acpi_hest_address_offset(enum AcpiGhesNotifyType notify,
+ uint64_t *error_block_offset,
+ uint64_t *ack_offset,
+ uint64_t *cper_offset,
+ enum AcpiHestSourceId *source_id)
+{
+ enum AcpiHestSourceId source;
+ uint64_t offset;
+
+ switch (notify) {
+ case ACPI_GHES_NOTIFY_SEA: /* Only on ARMv8 */
+ source = ACPI_HEST_SRC_ID_SEA;
+ break;
+ case ACPI_GHES_NOTIFY_GPIO:
+ source = ACPI_HEST_SRC_ID_GED;
+ break;
+ default:
+ return true;
+ }
+
+ if (source_id) {
+ *source_id = source;
+ }
+
+ /*
+ * Please see docs/specs/acpi_hest_ghes.rst for the memory layout.
+ * In summary, memory starts with error addresses, then acks and
+ * finally CPER blocks.
+ */
+
+ offset = source * sizeof(uint64_t);
+
+ if (error_block_offset) {
+ *error_block_offset = offset;
+ }
+ if (ack_offset) {
+ *ack_offset = offset + ACPI_HEST_SRC_ID_COUNT * sizeof(uint64_t);
+ }
+ if (cper_offset) {
+ *cper_offset = 2 * ACPI_HEST_SRC_ID_COUNT * sizeof(uint64_t) +
+ source * ACPI_GHES_MAX_RAW_DATA_LENGTH;
+ }
+
+ return false;
+}
+
+static int ghes_get_hardware_errors_address(enum AcpiGhesNotifyType notify,
+ uint64_t *error_block_addr,
+ uint64_t *read_ack_addr,
+ uint64_t *cper_addr,
+ enum AcpiHestSourceId *source_id)
+{
+ AcpiGedState *acpi_ged_state =
+ ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED, NULL));
+ AcpiGhesState *ags = &acpi_ged_state->ghes_state;
+
+ if (acpi_hest_address_offset(notify, error_block_addr, read_ack_addr,
+ cper_addr, source_id)) {
+ return -1;
+ }
+
+ if (error_block_addr) {
+ *error_block_addr += le64_to_cpu(ags->ghes_addr_le);
+ }
+
+ if (read_ack_addr) {
+ *read_ack_addr += le64_to_cpu(ags->ghes_addr_le);
+ }
+
+ if (cper_addr) {
+ *cper_addr += le64_to_cpu(ags->ghes_addr_le);
+ }
+
+ return 0;
+}
+
/* Build Generic Hardware Error Source version 2 (GHESv2) */
-static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker)
+static void build_ghes_v2(GArray *table_data,
+ enum AcpiGhesNotifyType notify,
+ BIOSLinker *linker)
{
- uint64_t address_offset;
+ uint64_t address_offset, ack_offset, block_addr_offset;
+ enum AcpiHestSourceId source_id;
- assert(source_id < ACPI_HEST_SRC_ID_RESERVED);
+ if (acpi_hest_address_offset(notify, &block_addr_offset, &ack_offset,
+ NULL, &source_id)) {
+ error_report("Error: notify %d not supported", notify);
+ abort();
+ }
/*
* Type:
@@ -319,22 +410,21 @@ static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker)
build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0x40, 0,
4 /* QWord access */, 0);
bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
- address_offset + GAS_ADDR_OFFSET, sizeof(uint64_t),
- ACPI_GHES_ERRORS_FW_CFG_FILE, source_id * sizeof(uint64_t));
+ address_offset + GAS_ADDR_OFFSET,
+ sizeof(uint64_t),
+ ACPI_GHES_ERRORS_FW_CFG_FILE,
+ block_addr_offset);
+ /* Notification Structure */
switch (source_id) {
case ACPI_HEST_SRC_ID_SEA:
- /*
- * Notification Structure
- * Now only enable ARMv8 SEA notification type
- */
build_ghes_hw_error_notification(table_data, ACPI_GHES_NOTIFY_SEA);
break;
- case ACPI_HEST_NOTIFY_EXTERNAL:
+ case ACPI_HEST_SRC_ID_GED:
build_ghes_hw_error_notification(table_data, ACPI_GHES_NOTIFY_GPIO);
break;
default:
- error_report("Not support this error source");
+ error_report("Error: Source ID %d not supported", source_id);
abort();
}
@@ -350,9 +440,10 @@ static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker)
build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0x40, 0,
4 /* QWord access */, 0);
bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
- address_offset + GAS_ADDR_OFFSET,
- sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE,
- (ACPI_GHES_ERROR_SOURCE_COUNT + source_id) * sizeof(uint64_t));
+ address_offset + GAS_ADDR_OFFSET,
+ sizeof(uint64_t),
+ ACPI_GHES_ERRORS_FW_CFG_FILE,
+ ack_offset);
/*
* Read Ack Preserve field
@@ -374,9 +465,9 @@ void acpi_build_hest(GArray *table_data, BIOSLinker *linker,
acpi_table_begin(&table, table_data);
/* Error Source Count */
- build_append_int_noprefix(table_data, ACPI_GHES_ERROR_SOURCE_COUNT, 4);
- build_ghes_v2(table_data, ACPI_HEST_SRC_ID_SEA, linker);
- build_ghes_v2(table_data, ACPI_HEST_NOTIFY_EXTERNAL, linker);
+ build_append_int_noprefix(table_data, ACPI_HEST_SRC_ID_COUNT, 4);
+ build_ghes_v2(table_data, ACPI_GHES_NOTIFY_SEA, linker);
+ build_ghes_v2(table_data, ACPI_GHES_NOTIFY_GPIO, linker);
acpi_table_end(linker, &table);
}
@@ -395,56 +486,46 @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
ags->present = true;
}
-int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
+int acpi_ghes_record_errors(enum AcpiGhesNotifyType notify,
+ uint64_t physical_address)
{
- uint64_t error_block_addr, read_ack_register_addr, read_ack_register = 0;
- uint64_t start_addr;
- bool ret = -1;
- AcpiGedState *acpi_ged_state;
- AcpiGhesState *ags;
-
- assert(source_id < ACPI_HEST_SRC_ID_RESERVED);
-
- acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED,
- NULL));
- g_assert(acpi_ged_state);
- ags = &acpi_ged_state->ghes_state;
-
- start_addr = le64_to_cpu(ags->ghes_addr_le);
-
- if (physical_address) {
- if (source_id < ACPI_HEST_SRC_ID_RESERVED) {
- start_addr += source_id * sizeof(uint64_t);
- }
-
- cpu_physical_memory_read(start_addr, &error_block_addr,
- sizeof(error_block_addr));
-
- error_block_addr = le64_to_cpu(error_block_addr);
-
- read_ack_register_addr = start_addr +
- ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t);
-
- cpu_physical_memory_read(read_ack_register_addr,
- &read_ack_register, sizeof(read_ack_register));
-
- /* zero means OSPM does not acknowledge the error */
- if (!read_ack_register) {
- error_report("OSPM does not acknowledge previous error,"
- " so can not record CPER for current error anymore");
- } else if (error_block_addr) {
- read_ack_register = cpu_to_le64(0);
- /*
- * Clear the Read Ack Register, OSPM will write it to 1 when
- * it acknowledges this error.
- */
- cpu_physical_memory_write(read_ack_register_addr,
- &read_ack_register, sizeof(uint64_t));
-
- ret = acpi_ghes_record_mem_error(error_block_addr,
- physical_address);
- } else
- error_report("can not find Generic Error Status Block");
+ uint64_t error_block_addr, read_ack_register = 0;
+ uint64_t cper_addr, read_ack_start_addr;
+ int ret;
+
+ ret = ghes_get_hardware_errors_address(notify, NULL,
+ &read_ack_start_addr,
+ &cper_addr, NULL);
+
+ if (ret || !physical_address) {
+ error_report("can not find Generic Error Status Block for notify %d",
+ notify);
+ return ret;
+ }
+
+ cpu_physical_memory_read(cper_addr, &error_block_addr,
+ sizeof(error_block_addr));
+
+ error_block_addr = le64_to_cpu(error_block_addr);
+
+ cpu_physical_memory_read(read_ack_start_addr,
+ &read_ack_register, sizeof(read_ack_register));
+
+ /* zero means OSPM does not acknowledge the error */
+ if (!read_ack_register) {
+ error_report("OSPM does not acknowledge previous error,"
+ " so can not record CPER for current error anymore");
+ } else if (error_block_addr) {
+ read_ack_register = cpu_to_le64(0);
+ /*
+ * Clear the Read Ack Register, OSPM will write it to 1 when
+ * it acknowledges this error.
+ */
+ cpu_physical_memory_write(read_ack_start_addr,
+ &read_ack_register, sizeof(uint64_t));
+
+ ret = acpi_ghes_record_mem_error(error_block_addr,
+ physical_address);
}
return ret;
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
index a7a18c7b50cf..2fcfa1cc8090 100644
--- a/include/hw/acpi/ghes.h
+++ b/include/hw/acpi/ghes.h
@@ -29,7 +29,7 @@
extern NotifierList acpi_generic_error_notifiers;
/*
- * Values for Hardware Error Notification Type field
+ * ACPI spec values for Hardware Error Notification Type field
*/
enum AcpiGhesNotifyType {
/* Polled */
@@ -60,13 +60,6 @@ enum AcpiGhesNotifyType {
ACPI_GHES_NOTIFY_RESERVED = 12
};
-/* Those are used as table indexes when building GHES tables */
-enum {
- ACPI_HEST_SRC_ID_SEA = 0,
- ACPI_HEST_NOTIFY_EXTERNAL,
- ACPI_HEST_SRC_ID_RESERVED,
-};
-
typedef struct AcpiGhesState {
uint64_t ghes_addr_le;
bool present; /* True if GHES is present at all on this board */
@@ -77,7 +70,8 @@ void acpi_build_hest(GArray *table_data, BIOSLinker *linker,
const char *oem_id, const char *oem_table_id);
void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
GArray *hardware_errors);
-int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr);
+int acpi_ghes_record_errors(enum AcpiGhesNotifyType notify,
+ uint64_t error_physical_addr);
typedef struct AcpiGhesCper {
uint8_t *guid;
--
2.45.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v6 06/10] acpi/ghes: add support for generic error injection via QAPI
2024-08-08 12:26 [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
` (4 preceding siblings ...)
2024-08-08 12:26 ` [PATCH v6 05/10] acpi/ghes: rework the logic to handle HEST source ID Mauro Carvalho Chehab
@ 2024-08-08 12:26 ` Mauro Carvalho Chehab
2024-08-08 12:26 ` [PATCH v6 07/10] docs: acpi_hest_ghes: fix documentation for CPER size Mauro Carvalho Chehab
` (4 subsequent siblings)
10 siblings, 0 replies; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2024-08-08 12:26 UTC (permalink / raw)
Cc: Jonathan Cameron, Shiju Jose, Mauro Carvalho Chehab,
Michael S. Tsirkin, Ani Sinha, Dongjiu Geng, Igor Mammedov,
linux-kernel, qemu-arm, qemu-devel
Provide a generic interface for error injection via GHESv2.
This patch is 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>
---
hw/acpi/ghes.c | 78 ++++++++++++++++++++++++++++++++++++++++++
hw/acpi/ghes_cper.c | 2 +-
include/hw/acpi/ghes.h | 3 ++
3 files changed, 82 insertions(+), 1 deletion(-)
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
index 26e93dd0f6e2..8525481bb828 100644
--- a/hw/acpi/ghes.c
+++ b/hw/acpi/ghes.c
@@ -534,6 +534,84 @@ int acpi_ghes_record_errors(enum AcpiGhesNotifyType notify,
NotifierList acpi_generic_error_notifiers =
NOTIFIER_LIST_INITIALIZER(error_device_notifiers);
+void ghes_record_cper_errors(AcpiGhesCper *cper, Error **errp,
+ enum AcpiGhesNotifyType notify)
+{
+ uint64_t cper_addr, read_ack_start_addr;
+ uint64_t read_ack = 0;
+ uint32_t data_length;
+ GArray *block;
+ uint32_t i;
+
+ if (ghes_get_hardware_errors_address(notify, NULL, &read_ack_start_addr,
+ &cper_addr, NULL)) {
+ error_setg(errp,
+ "GHES: Invalid error block/ack address(es) for notify %d",
+ notify);
+ return;
+ }
+
+ cpu_physical_memory_read(read_ack_start_addr,
+ &read_ack, sizeof(uint64_t));
+
+ /* zero means OSPM does not acknowledge the error */
+ if (!read_ack) {
+ error_setg(errp,
+ "Last CPER record was not acknowledged yet");
+ read_ack = 1;
+ cpu_physical_memory_write(read_ack_start_addr,
+ &read_ack, sizeof(uint64_t));
+ return;
+ }
+
+ read_ack = cpu_to_le64(0);
+ cpu_physical_memory_write(read_ack_start_addr,
+ &read_ack, sizeof(uint64_t));
+
+ /* Build CPER record */
+
+ /*
+ * Invalid fru id: ACPI 4.0: 17.3.2.6.1 Generic Error Data,
+ * Table 17-13 Generic Error Data Entry
+ */
+ QemuUUID fru_id = {};
+
+ block = g_array_new(false, true /* clear */, 1);
+ data_length = ACPI_GHES_DATA_LENGTH + cper->data_len;
+
+ /*
+ * It should not run out of the preallocated memory if
+ * adding a new generic error data entry
+ */
+ if ((data_length + ACPI_GHES_GESB_SIZE) >
+ ACPI_GHES_MAX_RAW_DATA_LENGTH) {
+ error_setg(errp, "GHES CPER record is too big: %d",
+ data_length);
+ }
+
+ /* Build the new generic error status block header */
+ acpi_ghes_generic_error_status(block, ACPI_GEBS_UNCORRECTABLE,
+ 0, 0, data_length,
+ ACPI_CPER_SEV_RECOVERABLE);
+
+ /* Build this new generic error data entry header */
+ acpi_ghes_generic_error_data(block, cper->guid,
+ ACPI_CPER_SEV_RECOVERABLE, 0, 0,
+ cper->data_len, fru_id, 0);
+
+ /* Add CPER data */
+ for (i = 0; i < cper->data_len; i++) {
+ build_append_int_noprefix(block, cper->data[i], 1);
+ }
+
+ /* Write the generic error data entry into guest memory */
+ cpu_physical_memory_write(cper_addr, block->data, block->len);
+
+ g_array_free(block, true);
+
+ notifier_list_notify(&acpi_generic_error_notifiers, NULL);
+}
+
bool acpi_ghes_present(void)
{
AcpiGedState *acpi_ged_state;
diff --git a/hw/acpi/ghes_cper.c b/hw/acpi/ghes_cper.c
index 7aa7e71e90dc..d7ff7debee74 100644
--- a/hw/acpi/ghes_cper.c
+++ b/hw/acpi/ghes_cper.c
@@ -39,7 +39,7 @@ void qmp_ghes_cper(CommonPlatformErrorRecord *qmp_cper,
return;
}
- /* TODO: call a function at ghes */
+ ghes_record_cper_errors(&cper, errp, ACPI_GHES_NOTIFY_GPIO);
g_free(cper.data);
}
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
index 2fcfa1cc8090..5a7bdb08f8e2 100644
--- a/include/hw/acpi/ghes.h
+++ b/include/hw/acpi/ghes.h
@@ -79,6 +79,9 @@ typedef struct AcpiGhesCper {
size_t data_len;
} AcpiGhesCper;
+void ghes_record_cper_errors(AcpiGhesCper *cper, Error **errp,
+ enum AcpiGhesNotifyType notify);
+
/**
* acpi_ghes_present: Report whether ACPI GHES table is present
*
--
2.45.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v6 07/10] docs: acpi_hest_ghes: fix documentation for CPER size
2024-08-08 12:26 [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
` (5 preceding siblings ...)
2024-08-08 12:26 ` [PATCH v6 06/10] acpi/ghes: add support for generic error injection via QAPI Mauro Carvalho Chehab
@ 2024-08-08 12:26 ` Mauro Carvalho Chehab
2024-08-12 11:59 ` Igor Mammedov
2024-08-08 12:26 ` [PATCH v6 08/10] scripts/ghes_inject: add a script to generate GHES error inject Mauro Carvalho Chehab
` (3 subsequent siblings)
10 siblings, 1 reply; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2024-08-08 12:26 UTC (permalink / raw)
Cc: Jonathan Cameron, Shiju Jose, Mauro Carvalho Chehab, Dongjiu Geng,
linux-kernel, qemu-arm, qemu-devel
While the spec defines a CPER size of 4KiB for each record,
currently it is set to 1KiB. Fix the documentation and add
a pointer to the macro name there, as this may help to keep
it updated.
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
docs/specs/acpi_hest_ghes.rst | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/docs/specs/acpi_hest_ghes.rst b/docs/specs/acpi_hest_ghes.rst
index 68f1fbe0a4af..c3e9f8d9a702 100644
--- a/docs/specs/acpi_hest_ghes.rst
+++ b/docs/specs/acpi_hest_ghes.rst
@@ -67,8 +67,10 @@ Design Details
(3) The address registers table contains N Error Block Address entries
and N Read Ack Register entries. The size for each entry is 8-byte.
The Error Status Data Block table contains N Error Status Data Block
- entries. The size for each entry is 4096(0x1000) bytes. The total size
- for the "etc/hardware_errors" fw_cfg blob is (N * 8 * 2 + N * 4096) bytes.
+ entries. The size for each entry is defined at the source code as
+ ACPI_GHES_MAX_RAW_DATA_LENGTH (currently 1024 bytes). The total size
+ for the "etc/hardware_errors" fw_cfg blob is
+ (N * 8 * 2 + N * ACPI_GHES_MAX_RAW_DATA_LENGTH) bytes.
N is the number of the kinds of hardware error sources.
(4) QEMU generates the ACPI linker/loader script for the firmware. The
--
2.45.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v6 08/10] scripts/ghes_inject: add a script to generate GHES error inject
2024-08-08 12:26 [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
` (6 preceding siblings ...)
2024-08-08 12:26 ` [PATCH v6 07/10] docs: acpi_hest_ghes: fix documentation for CPER size Mauro Carvalho Chehab
@ 2024-08-08 12:26 ` Mauro Carvalho Chehab
2024-08-08 13:21 ` Markus Armbruster
2024-08-08 12:26 ` [PATCH v6 09/10] target/arm: add an experimental mpidr arm cpu property object Mauro Carvalho Chehab
` (2 subsequent siblings)
10 siblings, 1 reply; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2024-08-08 12:26 UTC (permalink / raw)
Cc: Jonathan Cameron, Shiju Jose, Mauro Carvalho Chehab, Cleber Rosa,
Eric Blake, John Snow, Markus Armbruster, linux-kernel,
qemu-devel
Using the QMP GHESv2 API requires preparing a raw data array
containing a CPER record.
Add a helper script with subcommands to prepare such data.
Currently, only ARM Processor error CPER record is supported.
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
MAINTAINERS | 3 +
qapi/ghes-cper.json | 4 +-
scripts/arm_processor_error.py | 375 ++++++++++++++++++++++++++++
scripts/ghes_inject.py | 48 ++++
scripts/qmp_helper.py | 431 +++++++++++++++++++++++++++++++++
5 files changed, 859 insertions(+), 2 deletions(-)
create mode 100644 scripts/arm_processor_error.py
create mode 100755 scripts/ghes_inject.py
create mode 100644 scripts/qmp_helper.py
diff --git a/MAINTAINERS b/MAINTAINERS
index a0c36f9b5d0c..9ad336381dbe 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2083,6 +2083,9 @@ S: Maintained
F: hw/arm/ghes_cper.c
F: hw/acpi/ghes_cper_stub.c
F: qapi/ghes-cper.json
+F: scripts/ghes_inject.py
+F: scripts/arm_processor_error.py
+F: scripts/qmp_helper.py
ppc4xx
L: qemu-ppc@nongnu.org
diff --git a/qapi/ghes-cper.json b/qapi/ghes-cper.json
index 3cc4f9f2aaa9..d650996a7150 100644
--- a/qapi/ghes-cper.json
+++ b/qapi/ghes-cper.json
@@ -36,8 +36,8 @@
##
# @ghes-cper:
#
-# Inject ARM Processor error with data to be filled according with
-# ACPI 6.2 GHESv2 spec.
+# Inject a CPER error data to be filled according with ACPI 6.2
+# spec via GHESv2.
#
# @cper: a single CPER record to be sent to the guest OS.
#
diff --git a/scripts/arm_processor_error.py b/scripts/arm_processor_error.py
new file mode 100644
index 000000000000..b464254c8b7c
--- /dev/null
+++ b/scripts/arm_processor_error.py
@@ -0,0 +1,375 @@
+#!/usr/bin/env python3
+#
+# pylint: disable=C0301,C0114,R0903,R0912,R0913,R0914,R0915,W0511
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2024 Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+
+# TODO: current implementation has dummy defaults.
+#
+# For a better implementation, a QMP addition/call is needed to
+# retrieve some data for ARM Processor Error injection:
+#
+# - ARM registers: power_state, mpidr.
+
+import argparse
+import re
+
+from qmp_helper import qmp, util, cper_guid
+
+class ArmProcessorEinj:
+ """
+ Implements ARM Processor Error injection via GHES
+ """
+
+ DESC = """
+ Generates an ARM processor error CPER, compatible with
+ UEFI 2.9A Errata.
+ """
+
+ ACPI_GHES_ARM_CPER_LENGTH = 40
+ ACPI_GHES_ARM_CPER_PEI_LENGTH = 32
+
+ # Context types
+ CONTEXT_AARCH32_EL1 = 1
+ CONTEXT_AARCH64_EL1 = 5
+ CONTEXT_MISC_REG = 8
+
+ def __init__(self, subparsers):
+ """Initialize the error injection class and add subparser"""
+
+ # Valid choice values
+ self.arm_valid_bits = {
+ "mpidr": util.bit(0),
+ "affinity": util.bit(1),
+ "running": util.bit(2),
+ "vendor": util.bit(3),
+ }
+
+ self.pei_flags = {
+ "first": util.bit(0),
+ "last": util.bit(1),
+ "propagated": util.bit(2),
+ "overflow": util.bit(3),
+ }
+
+ self.pei_error_types = {
+ "cache": util.bit(1),
+ "tlb": util.bit(2),
+ "bus": util.bit(3),
+ "micro-arch": util.bit(4),
+ }
+
+ self.pei_valid_bits = {
+ "multiple-error": util.bit(0),
+ "flags": util.bit(1),
+ "error-info": util.bit(2),
+ "virt-addr": util.bit(3),
+ "phy-addr": util.bit(4),
+ }
+
+ self.data = bytearray()
+
+ parser = subparsers.add_parser("arm", description=self.DESC)
+
+ arm_valid_bits = ",".join(self.arm_valid_bits.keys())
+ flags = ",".join(self.pei_flags.keys())
+ error_types = ",".join(self.pei_error_types.keys())
+ pei_valid_bits = ",".join(self.pei_valid_bits.keys())
+
+ # UEFI N.16 ARM Validation bits
+ g_arm = parser.add_argument_group("ARM processor")
+ g_arm.add_argument("--arm", "--arm-valid",
+ help=f"ARM valid bits: {arm_valid_bits}")
+ g_arm.add_argument("-a", "--affinity", "--level", "--affinity-level",
+ type=lambda x: int(x, 0),
+ help="Affinity level (when multiple levels apply)")
+ g_arm.add_argument("-l", "--mpidr", type=lambda x: int(x, 0),
+ help="Multiprocessor Affinity Register")
+ g_arm.add_argument("-i", "--midr", type=lambda x: int(x, 0),
+ help="Main ID Register")
+ g_arm.add_argument("-r", "--running",
+ action=argparse.BooleanOptionalAction,
+ default=None,
+ help="Indicates if the processor is running or not")
+ g_arm.add_argument("--psci", "--psci-state",
+ type=lambda x: int(x, 0),
+ help="Power State Coordination Interface - PSCI state")
+
+ # TODO: Add vendor-specific support
+
+ # UEFI N.17 bitmaps (type and flags)
+ g_pei = parser.add_argument_group("ARM Processor Error Info (PEI)")
+ g_pei.add_argument("-t", "--type", nargs="+",
+ help=f"one or more error types: {error_types}")
+ g_pei.add_argument("-f", "--flags", nargs="*",
+ help=f"zero or more error flags: {flags}")
+ g_pei.add_argument("-V", "--pei-valid", "--error-valid", nargs="*",
+ help=f"zero or more PEI valid bits: {pei_valid_bits}")
+
+ # UEFI N.17 Integer values
+ g_pei.add_argument("-m", "--multiple-error", nargs="+",
+ help="Number of errors: 0: Single error, 1: Multiple errors, 2-65535: Error count if known")
+ g_pei.add_argument("-e", "--error-info", nargs="+",
+ help="Error information (UEFI 2.10 tables N.18 to N.20)")
+ g_pei.add_argument("-p", "--physical-address", nargs="+",
+ help="Physical address")
+ g_pei.add_argument("-v", "--virtual-address", nargs="+",
+ help="Virtual address")
+
+ # UEFI N.21 Context
+ g_ctx = parser.add_argument_group("Processor Context")
+ g_ctx.add_argument("--ctx-type", "--context-type", nargs="*",
+ help="Type of the context (0=ARM32 GPR, 5=ARM64 EL1, other values supported)")
+ g_ctx.add_argument("--ctx-size", "--context-size", nargs="*",
+ help="Minimal size of the context")
+ g_ctx.add_argument("--ctx-array", "--context-array", nargs="*",
+ help="Comma-separated arrays for each context")
+
+ # Vendor-specific data
+ g_vendor = parser.add_argument_group("Vendor-specific data")
+ g_vendor.add_argument("--vendor", "--vendor-specific", nargs="+",
+ help="Vendor-specific byte arrays of data")
+
+ parser.set_defaults(func=self.send_cper)
+
+ def send_cper(self, args):
+ """Parse subcommand arguments and send a CPER via QMP"""
+
+ qmp_cmd = qmp(args.host, args.port, args.debug)
+
+ is_cpu_type = re.compile(r"^([\w+]+\-)?arm\-cpu$")
+ cpus = qmp_cmd.search_qom("/machine/unattached/device",
+ "type", is_cpu_type)
+
+ cper = {}
+ pei = {}
+ ctx = {}
+ vendor = {}
+
+ arg = vars(args)
+
+ # Handle global parameters
+ if args.arm:
+ arm_valid_init = False
+ cper["valid"] = util.get_choice(name="valid",
+ value=args.arm,
+ choices=self.arm_valid_bits,
+ suffixes=["-error", "-err"])
+ else:
+ cper["valid"] = 0
+ arm_valid_init = True
+
+ if "running" in arg:
+ if args.running:
+ cper["running-state"] = util.bit(0)
+ else:
+ cper["running-state"] = 0
+ else:
+ cper["running-state"] = 0
+
+ if arm_valid_init:
+ if args.affinity:
+ cper["valid"] |= self.arm_valid_bits["affinity"]
+
+ if args.mpidr:
+ cper["valid"] |= self.arm_valid_bits["mpidr"]
+
+ if "running-state" in cper:
+ cper["valid"] |= self.arm_valid_bits["running"]
+
+ if args.psci:
+ cper["valid"] |= self.arm_valid_bits["running"]
+
+ # Handle PEI
+ if not args.type:
+ args.type = ["cache-error"]
+
+ util.get_mult_choices(
+ pei,
+ name="valid",
+ values=args.pei_valid,
+ choices=self.pei_valid_bits,
+ suffixes=["-valid", "--addr"],
+ )
+ util.get_mult_choices(
+ pei,
+ name="type",
+ values=args.type,
+ choices=self.pei_error_types,
+ suffixes=["-error", "-err"],
+ )
+ util.get_mult_choices(
+ pei,
+ name="flags",
+ values=args.flags,
+ choices=self.pei_flags,
+ suffixes=["-error", "-cap"],
+ )
+ util.get_mult_int(pei, "error-info", args.error_info)
+ util.get_mult_int(pei, "multiple-error", args.multiple_error)
+ util.get_mult_int(pei, "phy-addr", args.physical_address)
+ util.get_mult_int(pei, "virt-addr", args.virtual_address)
+
+ # Handle context
+ util.get_mult_int(ctx, "type", args.ctx_type, allow_zero=True)
+ util.get_mult_int(ctx, "minimal-size", args.ctx_size, allow_zero=True)
+ util.get_mult_array(ctx, "register", args.ctx_array, allow_zero=True)
+
+ util.get_mult_array(vendor, "bytes", args.vendor, max_val=255)
+
+ # Store PEI
+ pei_data = bytearray()
+ default_flags = self.pei_flags["first"]
+ default_flags |= self.pei_flags["last"]
+
+ error_info_num = 0
+
+ for i, p in pei.items(): # pylint: disable=W0612
+ error_info_num += 1
+
+ # UEFI 2.10 doesn't define how to encode error information
+ # when multiple types are raised. So, provide a default only
+ # if a single type is there
+ if "error-info" not in p:
+ if p["type"] == util.bit(1):
+ p["error-info"] = 0x0091000F
+ if p["type"] == util.bit(2):
+ p["error-info"] = 0x0054007F
+ if p["type"] == util.bit(3):
+ p["error-info"] = 0x80D6460FFF
+ if p["type"] == util.bit(4):
+ p["error-info"] = 0x78DA03FF
+
+ if "valid" not in p:
+ p["valid"] = 0
+ if "multiple-error" in p:
+ p["valid"] |= self.pei_valid_bits["multiple-error"]
+
+ if "flags" in p:
+ p["valid"] |= self.pei_valid_bits["flags"]
+
+ if "error-info" in p:
+ p["valid"] |= self.pei_valid_bits["error-info"]
+
+ if "phy-addr" in p:
+ p["valid"] |= self.pei_valid_bits["phy-addr"]
+
+ if "virt-addr" in p:
+ p["valid"] |= self.pei_valid_bits["virt-addr"]
+
+ # Version
+ util.data_add(pei_data, 0, 1)
+
+ util.data_add(pei_data,
+ self.ACPI_GHES_ARM_CPER_PEI_LENGTH, 1)
+
+ util.data_add(pei_data, p["valid"], 2)
+ util.data_add(pei_data, p["type"], 1)
+ util.data_add(pei_data, p.get("multiple-error", 1), 2)
+ util.data_add(pei_data, p.get("flags", default_flags), 1)
+ util.data_add(pei_data, p.get("error-info", 0), 8)
+ util.data_add(pei_data, p.get("virt-addr", 0xDEADBEEF), 8)
+ util.data_add(pei_data, p.get("phy-addr", 0xABBA0BAD), 8)
+
+ # Store Context
+ ctx_data = bytearray()
+ context_info_num = 0
+
+ if ctx:
+ ret = qmp_cmd.send_cmd('{ "execute": "query-target" }',
+ may_open=True)
+
+ default_ctx = self.CONTEXT_MISC_REG
+
+ if "arch" in ret:
+ if ret["arch"] == "aarch64":
+ default_ctx = self.CONTEXT_AARCH64_EL1
+ elif ret["arch"] == "arm":
+ default_ctx = self.CONTEXT_AARCH32_EL1
+
+ for k in sorted(ctx.keys()):
+ context_info_num += 1
+
+ if "type" not in ctx[k]:
+ ctx[k]["type"] = default_ctx
+
+ if "register" not in ctx[k]:
+ ctx[k]["register"] = []
+
+ reg_size = len(ctx[k]["register"])
+ size = 0
+
+ if "minimal-size" in ctx:
+ size = ctx[k]["minimal-size"]
+
+ size = max(size, reg_size)
+
+ size = (size + 1) % 0xFFFE
+
+ # Version
+ util.data_add(ctx_data, 0, 2)
+
+ util.data_add(ctx_data, ctx[k]["type"], 2)
+
+ util.data_add(ctx_data, 8 * size, 4)
+
+ for r in ctx[k]["register"]:
+ util.data_add(ctx_data, r, 8)
+
+ for i in range(reg_size, size): # pylint: disable=W0612
+ util.data_add(ctx_data, 0, 8)
+
+ # Vendor-specific bytes are not grouped
+ vendor_data = bytearray()
+ if vendor:
+ for k in sorted(vendor.keys()):
+ for b in vendor[k]["bytes"]:
+ util.data_add(vendor_data, b, 1)
+
+ # Encode ARM Processor Error
+ data = bytearray()
+
+ util.data_add(data, cper["valid"], 4)
+
+ util.data_add(data, error_info_num, 2)
+ util.data_add(data, context_info_num, 2)
+
+ # Calculate the length of the CPER data
+ cper_length = self.ACPI_GHES_ARM_CPER_LENGTH
+ cper_length += len(pei_data)
+ cper_length += len(vendor_data)
+ cper_length += len(ctx_data)
+ util.data_add(data, cper_length, 4)
+
+ util.data_add(data, arg.get("affinity-level", 0), 1)
+
+ # Reserved
+ util.data_add(data, 0, 3)
+
+ if "midr-el1" not in arg:
+ if cpus:
+ get_mpidr = {
+ "execute": "qom-get",
+ "arguments": {
+ 'path': cpus[0],
+ 'property': "midr"
+ }
+ }
+ ret = qmp_cmd.send_cmd(get_mpidr, may_open=True)
+ if isinstance(ret, int):
+ arg["midr-el1"] = ret
+
+ util.data_add(data, arg.get("mpidr-el1", 0), 8)
+ util.data_add(data, arg.get("midr-el1", 0), 8)
+ util.data_add(data, cper["running-state"], 4)
+ util.data_add(data, arg.get("psci-state", 0), 4)
+
+ # Add PEI
+ data.extend(pei_data)
+ data.extend(ctx_data)
+ data.extend(vendor_data)
+
+ self.data = data
+
+ qmp_cmd.send_cper(cper_guid.CPER_PROC_ARM, self.data)
diff --git a/scripts/ghes_inject.py b/scripts/ghes_inject.py
new file mode 100755
index 000000000000..16bd1462e847
--- /dev/null
+++ b/scripts/ghes_inject.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python3
+#
+# pylint: disable=C0301, C0114
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2024 Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+
+import argparse
+import sys
+
+from arm_processor_error import ArmProcessorEinj
+
+EINJ_DESC = """
+Handle ACPI GHESv2 error injection logic QEMU QMP interface.
+
+It allows using UEFI BIOS EINJ features to generate GHES records.
+
+It helps testing CPER and GHES drivers at the guest OS and how
+userspace applications at the guest handle them.
+"""
+
+def main():
+ """Main program"""
+
+ # Main parser - handle generic args like QEMU QMP TCP socket options
+ parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+ usage="%(prog)s [options]",
+ description=EINJ_DESC)
+
+ g_options = parser.add_argument_group("QEMU QMP socket options")
+ g_options.add_argument("-H", "--host", default="localhost", type=str,
+ help="host name")
+ g_options.add_argument("-P", "--port", default=4445, type=int,
+ help="TCP port number")
+ g_options.add_argument('-d', '--debug', action='store_true')
+
+ subparsers = parser.add_subparsers()
+
+ ArmProcessorEinj(subparsers)
+
+ args = parser.parse_args()
+ if "func" in args:
+ args.func(args)
+ else:
+ sys.exit(f"Please specify a valid command for {sys.argv[0]}")
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/qmp_helper.py b/scripts/qmp_helper.py
new file mode 100644
index 000000000000..e9e9388bcb8b
--- /dev/null
+++ b/scripts/qmp_helper.py
@@ -0,0 +1,431 @@
+#!/usr/bin/env python3
+#
+# pylint: disable=C0103,C0301,C0114,R0912,R0913,R0915,E0213,E1135,E1136,E1137,R0903
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2024 Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+
+import json
+import socket
+import sys
+
+from base64 import b64encode
+
+class qmp:
+ """
+ Opens a connection and send/receive QMP commands.
+ """
+
+ def send_cmd(self, command, may_open=False,return_error=True):
+ """Send a command to QMP, optinally opening a connection"""
+
+ if may_open:
+ self._connect()
+ elif not self.socket:
+ return None
+
+ if isinstance(command, dict):
+ data = json.dumps(command).encode("utf-8")
+ else:
+ data = command.encode("utf-8")
+
+ self.socket.sendall(data)
+ data = self.socket.recv(1024)
+ try:
+ obj = json.loads(data.decode("utf-8"))
+ except json.JSONDecodeError as e:
+ print(f"Invalid QMP answer: {e}")
+ self._close()
+ return None
+
+ if "return" in obj:
+ if isinstance(obj.get("return"), dict):
+ if obj["return"]:
+ return obj["return"]
+ return "OK"
+ else:
+ return obj["return"]
+
+ elif isinstance(obj.get("error"), dict):
+ error = obj["error"]
+ if return_error:
+ print(f'{error["class"]}: {error["desc"]}')
+ else:
+ print(json.dumps(obj))
+
+ return None
+
+ def _close(self):
+ """Shutdown and close the socket, if opened"""
+ if not self.socket:
+ return
+
+ self.socket.shutdown(socket.SHUT_WR)
+ while 1:
+ data = self.socket.recv(1024)
+ if data == b"":
+ break
+ try:
+ obj = json.loads(data.decode("utf-8"))
+ except json.JSONDecodeError as e:
+ print(f"Invalid QMP answer: {e}")
+ self.socket.close()
+ self.socket = None
+ return
+
+ if isinstance(obj.get("return"), dict):
+ print(json.dumps(obj["return"]))
+ if isinstance(obj.get("error"), dict):
+ error = obj["error"]
+ print(f'{error["class"]}: {error["desc"]}')
+ else:
+ print(json.dumps(obj))
+
+ self.socket.close()
+ self.socket = None
+
+ def _connect(self):
+ """Connect to a QMP TCP/IP port, if not connected yet"""
+
+ if self.socket:
+ return True
+
+ self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ try:
+ self.socket.connect((self.host, self.port))
+ except ConnectionRefusedError:
+ sys.exit(f"Can't connect to QMP host {self.host}:{self.port}")
+
+ data = self.socket.recv(1024)
+ try:
+ obj = json.loads(data.decode("utf-8"))
+ except json.JSONDecodeError as e:
+ print(f"Invalid QMP answer: {e}")
+ self._close()
+ return False
+
+ if "QMP" not in obj:
+ print(f"Invalid QMP answer: {data.decode('utf-8')}")
+ self._close()
+ return False
+
+ result = self.send_cmd('{ "execute": "qmp_capabilities" }')
+ if not result:
+ self._close()
+ return False
+
+ return True
+
+ def __init__(self, host, port, debug=False):
+ """Initialize variables used by the QMP send logic"""
+
+ self.socket = None
+ self.host = host
+ self.port = port
+ self.debug = debug
+
+ def __del__(self):
+ self._close()
+
+ #
+ # Socket QMP send command
+ #
+ def send_cper(self, guid, data):
+ """Send commands to QEMU though QMP TCP socket"""
+
+ base64_data = b64encode(bytes(data)).decode('ascii')
+
+ cmd_arg = {
+ 'cper': {
+ 'notification-type': guid,
+ "raw-data": base64_data
+ }
+ }
+
+ command = '{ "execute": "ghes-cper", '
+ command += '"arguments": ' + json.dumps(cmd_arg) + " }"
+
+ if self.debug:
+ print(f"GUID: {guid}")
+ print("CPER:")
+
+ for ln_start in range(0, len(data), 16):
+ ln_end = min(ln_start + 16, len(data))
+ print(f" {ln_start:08x} ", end="")
+ for i in range(ln_start, ln_end):
+ print(f"{data[i]:02x} ", end="")
+ for i in range(ln_end, ln_start + 16):
+ print(" ", end="")
+ print(" ", end="")
+ for i in range(ln_start, ln_end):
+ if data[i] >= 32 and data[i] < 127:
+ print(chr(data[i]), end="")
+ else:
+ print(".", end="")
+
+ print()
+ print()
+
+ self._connect()
+
+ if self.send_cmd(command):
+ print("Error injected.")
+
+ def search_qom(self, path, prop, regex):
+ """
+ Return a list of devices that match path array like:
+
+ /machine/unattached/device
+ /machine/peripheral-anon/device
+ ...
+ """
+
+ found = []
+
+ i = 0
+ while 1:
+ dev = f"{path}[{i}]"
+ cmd = {
+ "execute": "qom-get",
+ "arguments": {
+ 'path': dev,
+ 'property': prop
+ }
+ }
+ ret = self.send_cmd(cmd, may_open=True, return_error=False)
+ if not ret:
+ break
+
+ if isinstance(ret, str):
+ if regex.search(ret):
+ found.append(dev)
+
+ i += 1
+
+ return found
+
+class util:
+ """
+ Ancillary functions to deal with bitmaps, parse arguments,
+ generate GUID and encode data on a bytearray buffer.
+ """
+
+ #
+ # Helper routines to handle multiple choice arguments
+ #
+ def get_choice(name, value, choices, suffixes=None):
+ """Produce a list from multiple choice argument"""
+
+ new_values = 0
+
+ if not value:
+ return new_values
+
+ for val in value.split(","):
+ val = val.lower()
+
+ if suffixes:
+ for suffix in suffixes:
+ val = val.removesuffix(suffix)
+
+ if val not in choices.keys():
+ if suffixes:
+ for suffix in suffixes:
+ if val + suffix in choices.keys():
+ val += suffix
+ break
+
+ if val not in choices.keys():
+ sys.exit(f"Error on '{name}': choice '{val}' is invalid.")
+
+ val = choices[val]
+
+ new_values |= val
+
+ return new_values
+
+
+ def get_mult_array(mult, name, values, allow_zero=False, max_val=None):
+ """Add numbered hashes from integer lists"""
+
+ if not allow_zero:
+ if not values:
+ return
+ else:
+ if values is None:
+ return
+
+ if not values:
+ i = 0
+ if i not in mult:
+ mult[i] = {}
+
+ mult[i][name] = []
+ return
+
+ i = 0
+ for value in values:
+ for val in value.split(","):
+ try:
+ val = int(val, 0)
+ except ValueError:
+ sys.exit(f"Error on '{name}': {val} is not an integer")
+
+ if val < 0:
+ sys.exit(f"Error on '{name}': {val} is not unsigned")
+
+ if max_val and val > max_val:
+ sys.exit(f"Error on '{name}': {val} is too little")
+
+ if i not in mult:
+ mult[i] = {}
+
+ if name not in mult[i]:
+ mult[i][name] = []
+
+ mult[i][name].append(val)
+
+ i += 1
+
+
+ def get_mult_choices(mult, name, values, choices,
+ suffixes=None, allow_zero=False):
+ """Add numbered hashes from multiple choice arguments"""
+
+ if not allow_zero:
+ if not values:
+ return
+ else:
+ if values is None:
+ return
+
+ i = 0
+ for val in values:
+ new_values = util.get_choice(name, val, choices, suffixes)
+
+ if i not in mult:
+ mult[i] = {}
+
+ mult[i][name] = new_values
+ i += 1
+
+
+ def get_mult_int(mult, name, values, allow_zero=False):
+ """Add numbered hashes from integer arguments"""
+ if not allow_zero:
+ if not values:
+ return
+ else:
+ if values is None:
+ return
+
+ i = 0
+ for val in values:
+ try:
+ val = int(val, 0)
+ except ValueError:
+ sys.exit(f"Error on '{name}': {val} is not an integer")
+
+ if val < 0:
+ sys.exit(f"Error on '{name}': {val} is not unsigned")
+
+ if i not in mult:
+ mult[i] = {}
+
+ mult[i][name] = val
+ i += 1
+
+
+ #
+ # Data encode helper functions
+ #
+ def bit(b):
+ """Simple macro to define a bit on a bitmask"""
+ return 1 << b
+
+
+ def data_add(data, value, num_bytes):
+ """Adds bytes from value inside a bitarray"""
+
+ data.extend(value.to_bytes(num_bytes, byteorder="little")) # pylint: disable=E1101
+
+ def to_guid(time_low, time_mid, time_high, nodes):
+ """Create an GUID string"""
+
+ assert len(nodes) == 8
+
+ clock = nodes[0] << 8 | nodes[1]
+
+ node = 0
+ for i in range(2, len(nodes)):
+ node = node << 8 | nodes[i]
+
+ s = f"{time_low:08x}-{time_mid:04x}-"
+ s += f"{time_high:04x}-{clock:04x}-{node:012x}"
+ return s
+
+class cper_guid:
+ """
+ Contains CPER GUID, as per:
+ https://uefi.org/specs/UEFI/2.10/Apx_N_Common_Platform_Error_Record.html
+ """
+
+ CPER_PROC_GENERIC = util.to_guid(0x9876CCAD, 0x47B4, 0x4bdb,
+ [0xB6, 0x5E, 0x16, 0xF1,
+ 0x93, 0xC4, 0xF3, 0xDB])
+
+ CPER_PROC_X86 = util.to_guid(0xDC3EA0B0, 0xA144, 0x4797,
+ [0xB9, 0x5B, 0x53, 0xFA,
+ 0x24, 0x2B, 0x6E, 0x1D])
+
+ CPER_PROC_ITANIUM = util.to_guid(0xe429faf1, 0x3cb7, 0x11d4,
+ [0xbc, 0xa7, 0x00, 0x80,
+ 0xc7, 0x3c, 0x88, 0x81])
+
+ CPER_PROC_ARM = util.to_guid(0xE19E3D16, 0xBC11, 0x11E4,
+ [0x9C, 0xAA, 0xC2, 0x05,
+ 0x1D, 0x5D, 0x46, 0xB0])
+
+ CPER_PLATFORM_MEM = util.to_guid(0xA5BC1114, 0x6F64, 0x4EDE,
+ [0xB8, 0x63, 0x3E, 0x83,
+ 0xED, 0x7C, 0x83, 0xB1])
+
+ CPER_PLATFORM_MEM2 = util.to_guid(0x61EC04FC, 0x48E6, 0xD813,
+ [0x25, 0xC9, 0x8D, 0xAA,
+ 0x44, 0x75, 0x0B, 0x12])
+
+ CPER_PCIE = util.to_guid(0xD995E954, 0xBBC1, 0x430F,
+ [0xAD, 0x91, 0xB4, 0x4D,
+ 0xCB, 0x3C, 0x6F, 0x35])
+
+ CPER_PCI_BUS = util.to_guid(0xC5753963, 0x3B84, 0x4095,
+ [0xBF, 0x78, 0xED, 0xDA,
+ 0xD3, 0xF9, 0xC9, 0xDD])
+
+ CPER_PCI_DEV = util.to_guid(0xEB5E4685, 0xCA66, 0x4769,
+ [0xB6, 0xA2, 0x26, 0x06,
+ 0x8B, 0x00, 0x13, 0x26])
+
+ CPER_FW_ERROR = util.to_guid(0x81212A96, 0x09ED, 0x4996,
+ [0x94, 0x71, 0x8D, 0x72,
+ 0x9C, 0x8E, 0x69, 0xED])
+
+ CPER_DMA_GENERIC = util.to_guid(0x5B51FEF7, 0xC79D, 0x4434,
+ [0x8F, 0x1B, 0xAA, 0x62,
+ 0xDE, 0x3E, 0x2C, 0x64])
+
+ CPER_DMA_VT = util.to_guid(0x71761D37, 0x32B2, 0x45cd,
+ [0xA7, 0xD0, 0xB0, 0xFE,
+ 0xDD, 0x93, 0xE8, 0xCF])
+
+ CPER_DMA_IOMMU = util.to_guid(0x036F84E1, 0x7F37, 0x428c,
+ [0xA7, 0x9E, 0x57, 0x5F,
+ 0xDF, 0xAA, 0x84, 0xEC])
+
+ CPER_CCIX_PER = util.to_guid(0x91335EF6, 0xEBFB, 0x4478,
+ [0xA6, 0xA6, 0x88, 0xB7,
+ 0x28, 0xCF, 0x75, 0xD7])
+
+ CPER_CXL_PROT_ERR = util.to_guid(0x80B9EFB4, 0x52B5, 0x4DE3,
+ [0xA7, 0x77, 0x68, 0x78,
+ 0x4B, 0x77, 0x10, 0x48])
--
2.45.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v6 09/10] target/arm: add an experimental mpidr arm cpu property object
2024-08-08 12:26 [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
` (7 preceding siblings ...)
2024-08-08 12:26 ` [PATCH v6 08/10] scripts/ghes_inject: add a script to generate GHES error inject Mauro Carvalho Chehab
@ 2024-08-08 12:26 ` Mauro Carvalho Chehab
2024-08-12 12:02 ` Igor Mammedov
2024-08-08 12:26 ` [PATCH v6 10/10] scripts/arm_processor_error.py: retrieve mpidr if not filled Mauro Carvalho Chehab
2024-08-08 12:57 ` [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
10 siblings, 1 reply; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2024-08-08 12:26 UTC (permalink / raw)
Cc: Jonathan Cameron, Shiju Jose, Mauro Carvalho Chehab,
Peter Maydell, linux-kernel, qemu-arm, qemu-devel
Accurately injecting an ARM Processor error ACPI/APEI GHES
error record requires the value of the ARM Multiprocessor
Affinity Register (mpidr).
While ARM implements it, this is currently not visible.
Add a field at CPU storing it, and place it at arm_cpu_properties
as experimental, thus allowing it to be queried via QMP using
qom-get function.
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
target/arm/cpu.c | 1 +
target/arm/cpu.h | 1 +
target/arm/helper.c | 10 ++++++++--
3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 19191c239181..30fcf0a10f46 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2619,6 +2619,7 @@ static ObjectClass *arm_cpu_class_by_name(const char *cpu_model)
static Property arm_cpu_properties[] = {
DEFINE_PROP_UINT64("midr", ARMCPU, midr, 0),
+ DEFINE_PROP_UINT64("x-mpidr", ARMCPU, mpidr, 0),
DEFINE_PROP_UINT64("mp-affinity", ARMCPU,
mp_affinity, ARM64_AFFINITY_INVALID),
DEFINE_PROP_INT32("node-id", ARMCPU, node_id, CPU_UNSET_NUMA_NODE_ID),
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index a12859fc5335..d2e86f0877cc 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1033,6 +1033,7 @@ struct ArchCPU {
uint64_t reset_pmcr_el0;
} isar;
uint64_t midr;
+ uint64_t mpidr;
uint32_t revidr;
uint32_t reset_fpsid;
uint64_t ctr;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 8fb4b474e83f..16e75b7c5ed9 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -4692,7 +4692,7 @@ static uint64_t mpidr_read_val(CPUARMState *env)
return mpidr;
}
-static uint64_t mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+static uint64_t mpidr_read(CPUARMState *env)
{
unsigned int cur_el = arm_current_el(env);
@@ -4702,6 +4702,11 @@ static uint64_t mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
return mpidr_read_val(env);
}
+static uint64_t mpidr_read_ri(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ return mpidr_read(env);
+}
+
static const ARMCPRegInfo lpae_cp_reginfo[] = {
/* NOP AMAIR0/1 */
{ .name = "AMAIR0", .state = ARM_CP_STATE_BOTH,
@@ -9723,7 +9728,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
{ .name = "MPIDR_EL1", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 5,
.fgt = FGT_MPIDR_EL1,
- .access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_RAW },
+ .access = PL1_R, .readfn = mpidr_read_ri, .type = ARM_CP_NO_RAW },
};
#ifdef CONFIG_USER_ONLY
static const ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
@@ -9733,6 +9738,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
modify_arm_cp_regs(mpidr_cp_reginfo, mpidr_user_cp_reginfo);
#endif
define_arm_cp_regs(cpu, mpidr_cp_reginfo);
+ cpu->mpidr = mpidr_read(env);
}
if (arm_feature(env, ARM_FEATURE_AUXCR)) {
--
2.45.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v6 10/10] scripts/arm_processor_error.py: retrieve mpidr if not filled
2024-08-08 12:26 [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
` (8 preceding siblings ...)
2024-08-08 12:26 ` [PATCH v6 09/10] target/arm: add an experimental mpidr arm cpu property object Mauro Carvalho Chehab
@ 2024-08-08 12:26 ` Mauro Carvalho Chehab
2024-08-08 12:57 ` [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
10 siblings, 0 replies; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2024-08-08 12:26 UTC (permalink / raw)
Cc: Jonathan Cameron, Shiju Jose, Mauro Carvalho Chehab, Cleber Rosa,
John Snow, linux-kernel, qemu-devel
Add support to retrieve mpidr value via qom-get.
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
scripts/arm_processor_error.py | 30 ++++++++++++++++++++++--------
1 file changed, 22 insertions(+), 8 deletions(-)
diff --git a/scripts/arm_processor_error.py b/scripts/arm_processor_error.py
index b464254c8b7c..756935a2263c 100644
--- a/scripts/arm_processor_error.py
+++ b/scripts/arm_processor_error.py
@@ -5,12 +5,10 @@
#
# Copyright (C) 2024 Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
-# TODO: current implementation has dummy defaults.
-#
-# For a better implementation, a QMP addition/call is needed to
-# retrieve some data for ARM Processor Error injection:
-#
-# - ARM registers: power_state, mpidr.
+# Note: currently it lacks a method to fill the ARM Processor Error CPER
+# psci field from emulation. On a real hardware, this is filled only
+# when a CPU is not running. Implementing support for it to simulate a
+# real hardware is not trivial.
import argparse
import re
@@ -168,11 +166,27 @@ def send_cper(self, args):
else:
cper["running-state"] = 0
+ if args.mpidr:
+ cper["mpidr-el1"] = arg["mpidr"]
+ elif cpus:
+ get_mpidr = {
+ "execute": "qom-get",
+ "arguments": {
+ 'path': cpus[0],
+ 'property': "x-mpidr"
+ }
+ }
+ ret = qmp_cmd.send_cmd(get_mpidr, may_open=True)
+ if isinstance(ret, int):
+ cper["mpidr-el1"] = ret
+ else:
+ cper["mpidr-el1"] = 0
+
if arm_valid_init:
if args.affinity:
cper["valid"] |= self.arm_valid_bits["affinity"]
- if args.mpidr:
+ if "mpidr-el1" in cper:
cper["valid"] |= self.arm_valid_bits["mpidr"]
if "running-state" in cper:
@@ -360,7 +374,7 @@ def send_cper(self, args):
if isinstance(ret, int):
arg["midr-el1"] = ret
- util.data_add(data, arg.get("mpidr-el1", 0), 8)
+ util.data_add(data, cper["mpidr-el1"], 8)
util.data_add(data, arg.get("midr-el1", 0), 8)
util.data_add(data, cper["running-state"], 4)
util.data_add(data, arg.get("psci-state", 0), 4)
--
2.45.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation
2024-08-08 12:26 [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
` (9 preceding siblings ...)
2024-08-08 12:26 ` [PATCH v6 10/10] scripts/arm_processor_error.py: retrieve mpidr if not filled Mauro Carvalho Chehab
@ 2024-08-08 12:57 ` Mauro Carvalho Chehab
2024-08-12 12:18 ` Igor Mammedov
10 siblings, 1 reply; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2024-08-08 12:57 UTC (permalink / raw)
Cc: Jonathan Cameron, Shiju Jose, Ani Sinha, Dongjiu Geng,
Paolo Bonzini, Peter Maydell, Shannon Zhao, qemu-arm, qemu-devel
Em Thu, 8 Aug 2024 14:26:26 +0200
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> escreveu:
> v6:
> - PNP0C33 device creation moved to aml-build.c;
> - acpi_ghes record functions now use ACPI notify parameter,
> instead of source ID;
> - the number of source IDs is now automatically calculated;
> - some code cleanups and function/var renames;
> - some fixes and cleanups at the error injection script;
> - ghes cper stub now produces an error if cper JSON is not compiled;
> - Offset calculation logic for GHES was refactored;
> - Updated documentation to reflect the GHES allocated size;
> - Added a x-mpidr object for QOM usage;
> - Added a patch making usage of x-mpidr field at ARM injection
> script;
Forgot to mention: I dropped the PIN cleanup from this series, submitting
it in separate - and it is not related anymore with this changeset:
https://lore.kernel.org/qemu-devel/ef0e7f5fca6cd94eda415ecee670c3028c671b74.1723121692.git.mchehab+huawei@kernel.org/T/#u
Thanks,
Mauro
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v6 08/10] scripts/ghes_inject: add a script to generate GHES error inject
2024-08-08 12:26 ` [PATCH v6 08/10] scripts/ghes_inject: add a script to generate GHES error inject Mauro Carvalho Chehab
@ 2024-08-08 13:21 ` Markus Armbruster
0 siblings, 0 replies; 23+ messages in thread
From: Markus Armbruster @ 2024-08-08 13:21 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Jonathan Cameron, Shiju Jose, Cleber Rosa, Eric Blake, John Snow,
linux-kernel, qemu-devel
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:
> Using the QMP GHESv2 API requires preparing a raw data array
> containing a CPER record.
>
> Add a helper script with subcommands to prepare such data.
>
> Currently, only ARM Processor error CPER record is supported.
>
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
[...]
> diff --git a/qapi/ghes-cper.json b/qapi/ghes-cper.json
> index 3cc4f9f2aaa9..d650996a7150 100644
> --- a/qapi/ghes-cper.json
> +++ b/qapi/ghes-cper.json
> @@ -36,8 +36,8 @@
> ##
> # @ghes-cper:
> #
> -# Inject ARM Processor error with data to be filled according with
> -# ACPI 6.2 GHESv2 spec.
> +# Inject a CPER error data to be filled according with ACPI 6.2
> +# spec via GHESv2.
> #
> # @cper: a single CPER record to be sent to the guest OS.
> #
Accident? Drop, or squash into PATCH 04 instead?
[...]
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v6 04/10] qapi/ghes-cper: add an interface to do generic CPER error injection
2024-08-08 12:26 ` [PATCH v6 04/10] qapi/ghes-cper: add an interface to do generic CPER error injection Mauro Carvalho Chehab
@ 2024-08-08 13:23 ` Markus Armbruster
2024-08-12 11:57 ` Igor Mammedov
1 sibling, 0 replies; 23+ messages in thread
From: Markus Armbruster @ 2024-08-08 13:23 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Jonathan Cameron, Shiju Jose, Michael S. Tsirkin, Ani Sinha,
Dongjiu Geng, Eric Blake, Igor Mammedov, Michael Roth,
Paolo Bonzini, Peter Maydell, linux-kernel, qemu-arm, qemu-devel
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:
> Creates a QMP command to be used for generic ACPI APEI hardware error
> injection (HEST) via GHESv2.
>
> The actual GHES code will be added at the followup patch.
>
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
My review of v5 still applies. Messages crossed, I suppose.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v6 01/10] acpi/generic_event_device: add an APEI error device
2024-08-08 12:26 ` [PATCH v6 01/10] acpi/generic_event_device: add an APEI error device Mauro Carvalho Chehab
@ 2024-08-12 11:20 ` Igor Mammedov
0 siblings, 0 replies; 23+ messages in thread
From: Igor Mammedov @ 2024-08-12 11:20 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Jonathan Cameron, Shiju Jose, Michael S. Tsirkin, Ani Sinha,
linux-kernel, qemu-devel
On Thu, 8 Aug 2024 14:26:27 +0200
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> wrote:
> Adds a generic error device to handle generic hardware error
> events as specified at ACPI 6.5 specification at 18.3.2.7.2:
> https://uefi.org/specs/ACPI/6.5/18_Platform_Error_Interfaces.html#event-notification-for-generic-error-sources
> using HID PNP0C33.
>
> The PNP0C33 device is used to report hardware errors to
> the guest via ACPI APEI Generic Hardware Error Source (GHES).
>
> Co-authored-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> Co-authored-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
> ---
> hw/acpi/aml-build.c | 10 ++++++++++
> hw/acpi/generic_event_device.c | 8 ++++++++
> include/hw/acpi/acpi_dev_interface.h | 1 +
> include/hw/acpi/aml-build.h | 2 ++
> include/hw/acpi/generic_event_device.h | 1 +
> 5 files changed, 22 insertions(+)
>
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index 6d4517cfbe3d..cb167523859f 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -2520,3 +2520,13 @@ Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source)
>
> return var;
> }
> +
> +/* ACPI 5.0: 18.3.2.6.2 Event Notification For Generic Error Sources */
> +Aml *aml_error_device(void)
> +{
> + Aml *dev = aml_device(ACPI_APEI_ERROR_DEVICE);
> + aml_append(dev, aml_name_decl("_HID", aml_string("PNP0C33")));
> + aml_append(dev, aml_name_decl("_UID", aml_int(0)));
> +
> + return dev;
> +}
> diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
> index 15b4c3ebbf24..1673e9695be3 100644
> --- a/hw/acpi/generic_event_device.c
> +++ b/hw/acpi/generic_event_device.c
> @@ -26,6 +26,7 @@ static const uint32_t ged_supported_events[] = {
> ACPI_GED_PWR_DOWN_EVT,
> ACPI_GED_NVDIMM_HOTPLUG_EVT,
> ACPI_GED_CPU_HOTPLUG_EVT,
> + ACPI_GED_ERROR_EVT
> };
>
> /*
> @@ -116,6 +117,11 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev,
> aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
> aml_int(0x80)));
> break;
> + case ACPI_GED_ERROR_EVT:
> + aml_append(if_ctx,
> + aml_notify(aml_name(ACPI_APEI_ERROR_DEVICE),
> + aml_int(0x80)));
> + break;
> case ACPI_GED_NVDIMM_HOTPLUG_EVT:
> aml_append(if_ctx,
> aml_notify(aml_name("\\_SB.NVDR"),
> @@ -295,6 +301,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
> sel = ACPI_GED_MEM_HOTPLUG_EVT;
> } else if (ev & ACPI_POWER_DOWN_STATUS) {
> sel = ACPI_GED_PWR_DOWN_EVT;
> + } else if (ev & ACPI_GENERIC_ERROR) {
> + sel = ACPI_GED_ERROR_EVT;
> } else if (ev & ACPI_NVDIMM_HOTPLUG_STATUS) {
> sel = ACPI_GED_NVDIMM_HOTPLUG_EVT;
> } else if (ev & ACPI_CPU_HOTPLUG_STATUS) {
> diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h
> index 68d9d15f50aa..8294f8f0ccca 100644
> --- a/include/hw/acpi/acpi_dev_interface.h
> +++ b/include/hw/acpi/acpi_dev_interface.h
> @@ -13,6 +13,7 @@ typedef enum {
> ACPI_NVDIMM_HOTPLUG_STATUS = 16,
> ACPI_VMGENID_CHANGE_STATUS = 32,
> ACPI_POWER_DOWN_STATUS = 64,
> + ACPI_GENERIC_ERROR = 128,
> } AcpiEventStatusBits;
>
> #define TYPE_ACPI_DEVICE_IF "acpi-device-interface"
> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> index a3784155cb33..44d1a6af0c69 100644
> --- a/include/hw/acpi/aml-build.h
> +++ b/include/hw/acpi/aml-build.h
> @@ -252,6 +252,7 @@ struct CrsRangeSet {
> /* Consumer/Producer */
> #define AML_SERIAL_BUS_FLAG_CONSUME_ONLY (1 << 1)
>
> +#define ACPI_APEI_ERROR_DEVICE "GEDD"
> /**
> * init_aml_allocator:
> *
> @@ -382,6 +383,7 @@ Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz,
> uint8_t channel);
> Aml *aml_sleep(uint64_t msec);
> Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source);
> +Aml *aml_error_device(void);
>
> /* Block AML object primitives */
> Aml *aml_scope(const char *name_format, ...) G_GNUC_PRINTF(1, 2);
> diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
> index 40af3550b56d..9ace8fe70328 100644
> --- a/include/hw/acpi/generic_event_device.h
> +++ b/include/hw/acpi/generic_event_device.h
> @@ -98,6 +98,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED)
> #define ACPI_GED_PWR_DOWN_EVT 0x2
> #define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4
> #define ACPI_GED_CPU_HOTPLUG_EVT 0x8
> +#define ACPI_GED_ERROR_EVT 0x10
>
> typedef struct GEDState {
> MemoryRegion evt;
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v6 02/10] arm/virt: Wire up a GED error device for ACPI / GHES
2024-08-08 12:26 ` [PATCH v6 02/10] arm/virt: Wire up a GED error device for ACPI / GHES Mauro Carvalho Chehab
@ 2024-08-12 11:27 ` Igor Mammedov
0 siblings, 0 replies; 23+ messages in thread
From: Igor Mammedov @ 2024-08-12 11:27 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Jonathan Cameron, Shiju Jose, Michael S. Tsirkin, Ani Sinha,
Dongjiu Geng, Peter Maydell, Shannon Zhao, linux-kernel, qemu-arm,
qemu-devel
On Thu, 8 Aug 2024 14:26:28 +0200
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> wrote:
> Adds support to ARM virtualization to allow handling
> generic error ACPI Event via GED & error source device.
>
> It is aligned with Linux Kernel patch:
> https://lore.kernel.org/lkml/1272350481-27951-8-git-send-email-ying.huang@intel.com/
>
> Co-authored-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> Co-authored-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
other than question below mostly to arm/virt maintainers, LGTM
Acked-by: Igor Mammedov <imammedo@redhat.com>
> ---
> hw/acpi/ghes.c | 3 +++
> hw/arm/virt-acpi-build.c | 1 +
> hw/arm/virt.c | 12 +++++++++++-
> include/hw/acpi/ghes.h | 3 +++
> include/hw/arm/virt.h | 1 +
> 5 files changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
> index e9511d9b8f71..13b105c5d02d 100644
> --- a/hw/acpi/ghes.c
> +++ b/hw/acpi/ghes.c
> @@ -444,6 +444,9 @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
> return ret;
> }
>
> +NotifierList acpi_generic_error_notifiers =
> + NOTIFIER_LIST_INITIALIZER(error_device_notifiers);
> +
> bool acpi_ghes_present(void)
> {
> AcpiGedState *acpi_ged_state;
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index f76fb117adff..1769467d23b2 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -858,6 +858,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> }
>
> acpi_dsdt_add_power_button(scope);
> + aml_append(scope, aml_error_device());
> #ifdef CONFIG_TPM
> acpi_dsdt_add_tpm(scope, vms);
> #endif
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 687fe0bb8bc9..22448e5c5b73 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -677,7 +677,7 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
> DeviceState *dev;
> MachineState *ms = MACHINE(vms);
> int irq = vms->irqmap[VIRT_ACPI_GED];
> - uint32_t event = ACPI_GED_PWR_DOWN_EVT;
> + uint32_t event = ACPI_GED_PWR_DOWN_EVT | ACPI_GED_ERROR_EVT;
given how often error injection would be used, does it make a sense
to make it always enabled? (it after all consumes guest RAM for
error block buffer)
Maybe we need to add a machine property to enable it when desired?
What arm/virt folk think?
>
> if (ms->ram_slots) {
> event |= ACPI_GED_MEM_HOTPLUG_EVT;
> @@ -1009,6 +1009,13 @@ static void virt_powerdown_req(Notifier *n, void *opaque)
> }
> }
>
> +static void virt_generic_error_req(Notifier *n, void *opaque)
> +{
> + VirtMachineState *s = container_of(n, VirtMachineState, generic_error_notifier);
> +
> + acpi_send_event(s->acpi_dev, ACPI_GENERIC_ERROR);
> +}
> +
> static void create_gpio_keys(char *fdt, DeviceState *pl061_dev,
> uint32_t phandle)
> {
> @@ -2385,6 +2392,9 @@ static void machvirt_init(MachineState *machine)
>
> if (has_ged && aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) {
> vms->acpi_dev = create_acpi_ged(vms);
> + vms->generic_error_notifier.notify = virt_generic_error_req;
> + notifier_list_add(&acpi_generic_error_notifiers,
> + &vms->generic_error_notifier);
> } else {
> create_gpio_devices(vms, VIRT_GPIO, sysmem);
> }
> diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
> index 674f6958e905..fb80897e7eac 100644
> --- a/include/hw/acpi/ghes.h
> +++ b/include/hw/acpi/ghes.h
> @@ -23,6 +23,9 @@
> #define ACPI_GHES_H
>
> #include "hw/acpi/bios-linker-loader.h"
> +#include "qemu/notify.h"
> +
> +extern NotifierList acpi_generic_error_notifiers;
>
> /*
> * Values for Hardware Error Notification Type field
> diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
> index a4d937ed45ac..ad9f6e94dcc5 100644
> --- a/include/hw/arm/virt.h
> +++ b/include/hw/arm/virt.h
> @@ -175,6 +175,7 @@ struct VirtMachineState {
> DeviceState *gic;
> DeviceState *acpi_dev;
> Notifier powerdown_notifier;
> + Notifier generic_error_notifier;
> PCIBus *bus;
> char *oem_id;
> char *oem_table_id;
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v6 03/10] acpi/ghes: Add support for GED error device
2024-08-08 12:26 ` [PATCH v6 03/10] acpi/ghes: Add support for GED error device Mauro Carvalho Chehab
@ 2024-08-12 11:28 ` Igor Mammedov
0 siblings, 0 replies; 23+ messages in thread
From: Igor Mammedov @ 2024-08-12 11:28 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Jonathan Cameron, Shiju Jose, Michael S. Tsirkin, Ani Sinha,
Dongjiu Geng, linux-kernel, qemu-arm, qemu-devel
On Thu, 8 Aug 2024 14:26:29 +0200
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> wrote:
> From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>
> As a GED error device is now defined, add another type
> of notification.
>
> Add error notification to GHES v2 using a GED error device GED
> triggered via interrupt.
>
> [mchehab: do some cleanups at ACPI_HEST_SRC_ID_* checks and
> rename HEST event to better identify GED interrupt OSPM]
>
> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
> ---
> hw/acpi/ghes.c | 12 +++++++++---
> include/hw/acpi/ghes.h | 3 ++-
> 2 files changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
> index 13b105c5d02d..d6cbeed6e3d5 100644
> --- a/hw/acpi/ghes.c
> +++ b/hw/acpi/ghes.c
> @@ -34,8 +34,8 @@
> /* The max size in bytes for one error block */
> #define ACPI_GHES_MAX_RAW_DATA_LENGTH (1 * KiB)
>
> -/* Now only support ARMv8 SEA notification type error source */
> -#define ACPI_GHES_ERROR_SOURCE_COUNT 1
> +/* Support ARMv8 SEA notification type error source and GPIO interrupt. */
> +#define ACPI_GHES_ERROR_SOURCE_COUNT 2
>
> /* Generic Hardware Error Source version 2 */
> #define ACPI_GHES_SOURCE_GENERIC_ERROR_V2 10
> @@ -290,6 +290,9 @@ void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker)
> static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker)
> {
> uint64_t address_offset;
> +
> + assert(source_id < ACPI_HEST_SRC_ID_RESERVED);
> +
> /*
> * Type:
> * Generic Hardware Error Source version 2(GHESv2 - Type 10)
> @@ -327,6 +330,9 @@ static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker)
> */
> build_ghes_hw_error_notification(table_data, ACPI_GHES_NOTIFY_SEA);
> break;
> + case ACPI_HEST_NOTIFY_EXTERNAL:
> + build_ghes_hw_error_notification(table_data, ACPI_GHES_NOTIFY_GPIO);
> + break;
> default:
> error_report("Not support this error source");
> abort();
> @@ -370,6 +376,7 @@ void acpi_build_hest(GArray *table_data, BIOSLinker *linker,
> /* Error Source Count */
> build_append_int_noprefix(table_data, ACPI_GHES_ERROR_SOURCE_COUNT, 4);
> build_ghes_v2(table_data, ACPI_HEST_SRC_ID_SEA, linker);
> + build_ghes_v2(table_data, ACPI_HEST_NOTIFY_EXTERNAL, linker);
>
> acpi_table_end(linker, &table);
> }
> @@ -406,7 +413,6 @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
> start_addr = le64_to_cpu(ags->ghes_addr_le);
>
> if (physical_address) {
> -
> if (source_id < ACPI_HEST_SRC_ID_RESERVED) {
> start_addr += source_id * sizeof(uint64_t);
> }
> diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
> index fb80897e7eac..ce6f82a1155a 100644
> --- a/include/hw/acpi/ghes.h
> +++ b/include/hw/acpi/ghes.h
> @@ -59,9 +59,10 @@ enum AcpiGhesNotifyType {
> ACPI_GHES_NOTIFY_RESERVED = 12
> };
>
> +/* Those are used as table indexes when building GHES tables */
> enum {
> ACPI_HEST_SRC_ID_SEA = 0,
> - /* future ids go here */
> + ACPI_HEST_NOTIFY_EXTERNAL,
> ACPI_HEST_SRC_ID_RESERVED,
> };
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v6 04/10] qapi/ghes-cper: add an interface to do generic CPER error injection
2024-08-08 12:26 ` [PATCH v6 04/10] qapi/ghes-cper: add an interface to do generic CPER error injection Mauro Carvalho Chehab
2024-08-08 13:23 ` Markus Armbruster
@ 2024-08-12 11:57 ` Igor Mammedov
2024-08-13 22:52 ` Mauro Carvalho Chehab
1 sibling, 1 reply; 23+ messages in thread
From: Igor Mammedov @ 2024-08-12 11:57 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Jonathan Cameron, Shiju Jose, Michael S. Tsirkin, Ani Sinha,
Dongjiu Geng, Eric Blake, Markus Armbruster, Michael Roth,
Paolo Bonzini, Peter Maydell, linux-kernel, qemu-arm, qemu-devel
On Thu, 8 Aug 2024 14:26:30 +0200
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> wrote:
> Creates a QMP command to be used for generic ACPI APEI hardware error
> injection (HEST) via GHESv2.
>
> The actual GHES code will be added at the followup patch.
>
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
> MAINTAINERS | 7 +++++
> hw/acpi/Kconfig | 5 ++++
> hw/acpi/ghes_cper.c | 45 ++++++++++++++++++++++++++++++++
> hw/acpi/ghes_cper_stub.c | 19 ++++++++++++++
> hw/acpi/meson.build | 2 ++
> hw/arm/Kconfig | 5 ++++
> include/hw/acpi/ghes.h | 7 +++++
> qapi/ghes-cper.json | 55 ++++++++++++++++++++++++++++++++++++++++
> qapi/meson.build | 1 +
> qapi/qapi-schema.json | 1 +
> 10 files changed, 147 insertions(+)
> create mode 100644 hw/acpi/ghes_cper.c
> create mode 100644 hw/acpi/ghes_cper_stub.c
> create mode 100644 qapi/ghes-cper.json
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 10af21263293..a0c36f9b5d0c 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2077,6 +2077,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/ghes-cper.json
> +
> ppc4xx
> L: qemu-ppc@nongnu.org
> S: Orphan
> diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
> index e07d3204eb36..73ffbb82c150 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_cper.c b/hw/acpi/ghes_cper.c
> new file mode 100644
> index 000000000000..7aa7e71e90dc
> --- /dev/null
> +++ b/hw/acpi/ghes_cper.c
> @@ -0,0 +1,45 @@
> +/*
> + * ARM Processor error injection
> + *
> + * Copyright(C) 2024 Huawei LTD.
> + *
> + * This code is licensed under the GPL version 2 or later. See the
> + * COPYING file in the top-level directory.
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +
> +#include "qemu/base64.h"
> +#include "qemu/error-report.h"
> +#include "qemu/uuid.h"
> +#include "qapi/qapi-commands-ghes-cper.h"
> +#include "hw/acpi/ghes.h"
> +
> +void qmp_ghes_cper(CommonPlatformErrorRecord *qmp_cper,
> + Error **errp)
> +{
> + int rc;
> + AcpiGhesCper cper;
> + QemuUUID be_uuid, le_uuid;
> +
> + rc = qemu_uuid_parse(qmp_cper->notification_type, &be_uuid);
> + if (rc) {
> + error_setg(errp, "GHES: Invalid UUID: %s",
> + qmp_cper->notification_type);
> + return;
> + }
> +
> + le_uuid = qemu_uuid_bswap(be_uuid);
> + cper.guid = le_uuid.data;
> +
> + cper.data = qbase64_decode(qmp_cper->raw_data, -1,
> + &cper.data_len, errp);
> + if (!cper.data) {
> + return;
> + }
> +
> + /* TODO: call a function at ghes */
> +
> + g_free(cper.data);
> +}
> diff --git a/hw/acpi/ghes_cper_stub.c b/hw/acpi/ghes_cper_stub.c
> new file mode 100644
> index 000000000000..2358e039b181
> --- /dev/null
> +++ b/hw/acpi/ghes_cper_stub.c
> @@ -0,0 +1,19 @@
> +/*
> + * ARM Processor error injection
> + *
> + * Copyright(C) 2024 Huawei LTD.
> + *
> + * This code is licensed under the GPL version 2 or later. See the
> + * COPYING file in the top-level directory.
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qapi/qapi-commands-ghes-cper.h"
> +#include "hw/acpi/ghes.h"
> +
> +void qmp_ghes_cper(CommonPlatformErrorRecord *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 fa5c07db9068..6cbf430eb66d 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/Kconfig b/hw/arm/Kconfig
> index 1ad60da7aa2d..bed6ba27d715 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -712,3 +712,8 @@ config ARMSSE
> select UNIMP
> select SSE_COUNTER
> select SSE_TIMER
> +
> +config GHES_CPER
> + bool
> + depends on ARM
> + default y if AARCH64
> diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
> index ce6f82a1155a..a7a18c7b50cf 100644
> --- a/include/hw/acpi/ghes.h
> +++ b/include/hw/acpi/ghes.h
> @@ -23,6 +23,7 @@
> #define ACPI_GHES_H
>
> #include "hw/acpi/bios-linker-loader.h"
> +#include "qapi/error.h"
> #include "qemu/notify.h"
>
> extern NotifierList acpi_generic_error_notifiers;
> @@ -78,6 +79,12 @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
> GArray *hardware_errors);
> int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr);
>
> +typedef struct AcpiGhesCper {
> + uint8_t *guid;
> + uint8_t *data;
> + size_t data_len;
> +} AcpiGhesCper;
> +
> /**
> * acpi_ghes_present: Report whether ACPI GHES table is present
> *
> diff --git a/qapi/ghes-cper.json b/qapi/ghes-cper.json
> new file mode 100644
> index 000000000000..3cc4f9f2aaa9
> --- /dev/null
> +++ b/qapi/ghes-cper.json
> @@ -0,0 +1,55 @@
> +# -*- Mode: Python -*-
> +# vim: filetype=python
> +
> +##
> +# = GHESv2 CPER Error Injection
> +#
> +# These are defined at
> +# ACPI 6.2: 18.3.2.8 Generic Hardware Error Source version 2
> +# (GHESv2 - Type 10)
> +##
> +
> +##
> +# @CommonPlatformErrorRecord:
> +#
> +# Common Platform Error Record - CPER - as defined at the UEFI
> +# specification. See
> +# https://uefi.org/specs/UEFI/2.10/Apx_N_Common_Platform_Error_Record.html#record-header
> +# for more details.
> +#
> +# @notification-type: pre-assigned GUID string indicating the record
> +# association with an error event notification type, as defined
> +# at https://uefi.org/specs/UEFI/2.10/Apx_N_Common_Platform_Error_Record.html#record-header
> +#
> +# @raw-data: Contains a base64 encoded string with the payload of
> +# the CPER.
> +#
> +# Since: 9.2
> +##
> +{ 'struct': 'CommonPlatformErrorRecord',
> + 'data': {
> + 'notification-type': 'str',
like was mentioned at v5 review,
you only need this for setting cper notification type if you are (re)using
acpi_ghes_generic_error_status() && acpi_ghes_generic_error_data()
however while doing this in (6/10), you are also limiting what
could be encoded in headers to some hardcoded values.
Given QEMU doesn't need to know anything about notification type,
modulo putting it data block header, it would be beneficial
to drop 'notification type' from QAPI interface, and include
error status block and error data headers in raw-data.
This way it should be possible to change headers within python script
without affecting QEMU and QAPI interface. On top of that
ghes_record_cper_errors() could be simplified by dropping (in 6/10)
acpi_ghes_generic_error_status() && acpi_ghes_generic_error_data()
and just copying raw-data as is directly into error buffer (assuming
script put needed headers cper data).
From fusing pov it's also beneficial to try generate junk error status
block headers, for which python script looks like ideal place to put
it in.
> + 'raw-data': 'str'
> + }
> +}
> +
> +##
> +# @ghes-cper:
> +#
> +# Inject ARM Processor error with data to be filled according with
> +# ACPI 6.2 GHESv2 spec.
> +#
> +# @cper: a single CPER record to be sent to the guest OS.
> +#
> +# Features:
> +#
> +# @unstable: This command is experimental.
> +#
> +# Since: 9.2
> +##
> +{ 'command': 'ghes-cper',
> + 'data': {
> + 'cper': 'CommonPlatformErrorRecord'
> + },
> + 'features': [ 'unstable' ]
> +}
> diff --git a/qapi/meson.build b/qapi/meson.build
> index e7bc54e5d047..bd13cd7d40c9 100644
> --- a/qapi/meson.build
> +++ b/qapi/meson.build
> @@ -35,6 +35,7 @@ qapi_all_modules = [
> 'dump',
> 'ebpf',
> 'error',
> + 'ghes-cper',
> 'introspect',
> 'job',
> 'machine-common',
> diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json
> index b1581988e4eb..c1a267399fe5 100644
> --- a/qapi/qapi-schema.json
> +++ b/qapi/qapi-schema.json
> @@ -75,6 +75,7 @@
> { 'include': 'misc-target.json' }
> { 'include': 'audio.json' }
> { 'include': 'acpi.json' }
> +{ 'include': 'ghes-cper.json' }
> { 'include': 'pci.json' }
> { 'include': 'stats.json' }
> { 'include': 'virtio.json' }
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v6 07/10] docs: acpi_hest_ghes: fix documentation for CPER size
2024-08-08 12:26 ` [PATCH v6 07/10] docs: acpi_hest_ghes: fix documentation for CPER size Mauro Carvalho Chehab
@ 2024-08-12 11:59 ` Igor Mammedov
0 siblings, 0 replies; 23+ messages in thread
From: Igor Mammedov @ 2024-08-12 11:59 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Jonathan Cameron, Shiju Jose, Dongjiu Geng, linux-kernel,
qemu-arm, qemu-devel
On Thu, 8 Aug 2024 14:26:33 +0200
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> wrote:
> While the spec defines a CPER size of 4KiB for each record,
> currently it is set to 1KiB. Fix the documentation and add
> a pointer to the macro name there, as this may help to keep
> it updated.
>
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Acked-by: Igor Mammedov <imammedo@redhat.com>
> ---
> docs/specs/acpi_hest_ghes.rst | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/docs/specs/acpi_hest_ghes.rst b/docs/specs/acpi_hest_ghes.rst
> index 68f1fbe0a4af..c3e9f8d9a702 100644
> --- a/docs/specs/acpi_hest_ghes.rst
> +++ b/docs/specs/acpi_hest_ghes.rst
> @@ -67,8 +67,10 @@ Design Details
> (3) The address registers table contains N Error Block Address entries
> and N Read Ack Register entries. The size for each entry is 8-byte.
> The Error Status Data Block table contains N Error Status Data Block
> - entries. The size for each entry is 4096(0x1000) bytes. The total size
> - for the "etc/hardware_errors" fw_cfg blob is (N * 8 * 2 + N * 4096) bytes.
> + entries. The size for each entry is defined at the source code as
> + ACPI_GHES_MAX_RAW_DATA_LENGTH (currently 1024 bytes). The total size
> + for the "etc/hardware_errors" fw_cfg blob is
> + (N * 8 * 2 + N * ACPI_GHES_MAX_RAW_DATA_LENGTH) bytes.
> N is the number of the kinds of hardware error sources.
>
> (4) QEMU generates the ACPI linker/loader script for the firmware. The
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v6 09/10] target/arm: add an experimental mpidr arm cpu property object
2024-08-08 12:26 ` [PATCH v6 09/10] target/arm: add an experimental mpidr arm cpu property object Mauro Carvalho Chehab
@ 2024-08-12 12:02 ` Igor Mammedov
0 siblings, 0 replies; 23+ messages in thread
From: Igor Mammedov @ 2024-08-12 12:02 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Jonathan Cameron, Shiju Jose, Peter Maydell, linux-kernel,
qemu-arm, qemu-devel
On Thu, 8 Aug 2024 14:26:35 +0200
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> wrote:
> Accurately injecting an ARM Processor error ACPI/APEI GHES
> error record requires the value of the ARM Multiprocessor
> Affinity Register (mpidr).
>
> While ARM implements it, this is currently not visible.
>
> Add a field at CPU storing it, and place it at arm_cpu_properties
> as experimental, thus allowing it to be queried via QMP using
> qom-get function.
looks fine to me, but it's upto ARM folk to ack this
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> ---
> target/arm/cpu.c | 1 +
> target/arm/cpu.h | 1 +
> target/arm/helper.c | 10 ++++++++--
> 3 files changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> index 19191c239181..30fcf0a10f46 100644
> --- a/target/arm/cpu.c
> +++ b/target/arm/cpu.c
> @@ -2619,6 +2619,7 @@ static ObjectClass *arm_cpu_class_by_name(const char *cpu_model)
>
> static Property arm_cpu_properties[] = {
> DEFINE_PROP_UINT64("midr", ARMCPU, midr, 0),
> + DEFINE_PROP_UINT64("x-mpidr", ARMCPU, mpidr, 0),
> DEFINE_PROP_UINT64("mp-affinity", ARMCPU,
> mp_affinity, ARM64_AFFINITY_INVALID),
> DEFINE_PROP_INT32("node-id", ARMCPU, node_id, CPU_UNSET_NUMA_NODE_ID),
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index a12859fc5335..d2e86f0877cc 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -1033,6 +1033,7 @@ struct ArchCPU {
> uint64_t reset_pmcr_el0;
> } isar;
> uint64_t midr;
> + uint64_t mpidr;
> uint32_t revidr;
> uint32_t reset_fpsid;
> uint64_t ctr;
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 8fb4b474e83f..16e75b7c5ed9 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -4692,7 +4692,7 @@ static uint64_t mpidr_read_val(CPUARMState *env)
> return mpidr;
> }
>
> -static uint64_t mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
> +static uint64_t mpidr_read(CPUARMState *env)
> {
> unsigned int cur_el = arm_current_el(env);
>
> @@ -4702,6 +4702,11 @@ static uint64_t mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
> return mpidr_read_val(env);
> }
>
> +static uint64_t mpidr_read_ri(CPUARMState *env, const ARMCPRegInfo *ri)
> +{
> + return mpidr_read(env);
> +}
> +
> static const ARMCPRegInfo lpae_cp_reginfo[] = {
> /* NOP AMAIR0/1 */
> { .name = "AMAIR0", .state = ARM_CP_STATE_BOTH,
> @@ -9723,7 +9728,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
> { .name = "MPIDR_EL1", .state = ARM_CP_STATE_BOTH,
> .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 5,
> .fgt = FGT_MPIDR_EL1,
> - .access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_RAW },
> + .access = PL1_R, .readfn = mpidr_read_ri, .type = ARM_CP_NO_RAW },
> };
> #ifdef CONFIG_USER_ONLY
> static const ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
> @@ -9733,6 +9738,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
> modify_arm_cp_regs(mpidr_cp_reginfo, mpidr_user_cp_reginfo);
> #endif
> define_arm_cp_regs(cpu, mpidr_cp_reginfo);
> + cpu->mpidr = mpidr_read(env);
> }
>
> if (arm_feature(env, ARM_FEATURE_AUXCR)) {
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation
2024-08-08 12:57 ` [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
@ 2024-08-12 12:18 ` Igor Mammedov
2024-08-13 23:29 ` Mauro Carvalho Chehab
0 siblings, 1 reply; 23+ messages in thread
From: Igor Mammedov @ 2024-08-12 12:18 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Jonathan Cameron, Shiju Jose, Ani Sinha, Dongjiu Geng,
Paolo Bonzini, Peter Maydell, Shannon Zhao, qemu-arm, qemu-devel
On Thu, 8 Aug 2024 14:57:35 +0200
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> wrote:
> Em Thu, 8 Aug 2024 14:26:26 +0200
> Mauro Carvalho Chehab <mchehab+huawei@kernel.org> escreveu:
>
> > v6:
> > - PNP0C33 device creation moved to aml-build.c;
> > - acpi_ghes record functions now use ACPI notify parameter,
> > instead of source ID;
> > - the number of source IDs is now automatically calculated;
> > - some code cleanups and function/var renames;
> > - some fixes and cleanups at the error injection script;
> > - ghes cper stub now produces an error if cper JSON is not compiled;
> > - Offset calculation logic for GHES was refactored;
> > - Updated documentation to reflect the GHES allocated size;
> > - Added a x-mpidr object for QOM usage;
> > - Added a patch making usage of x-mpidr field at ARM injection
> > script;
stopping review at 5/10 and expecting a version with
GHES source to error status block mapping fetched from
HEST in guest RAM, instead of pre-calculated offsets
in source code (as in this series) to avoid migration
issues and keeping compat plumbing manageable down the road.
> Forgot to mention: I dropped the PIN cleanup from this series, submitting
> it in separate - and it is not related anymore with this changeset:
>
> https://lore.kernel.org/qemu-devel/ef0e7f5fca6cd94eda415ecee670c3028c671b74.1723121692.git.mchehab+huawei@kernel.org/T/#u
>
> Thanks,
> Mauro
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v6 04/10] qapi/ghes-cper: add an interface to do generic CPER error injection
2024-08-12 11:57 ` Igor Mammedov
@ 2024-08-13 22:52 ` Mauro Carvalho Chehab
0 siblings, 0 replies; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2024-08-13 22:52 UTC (permalink / raw)
To: Igor Mammedov
Cc: Jonathan Cameron, Shiju Jose, Michael S. Tsirkin, Ani Sinha,
Dongjiu Geng, Eric Blake, Markus Armbruster, Michael Roth,
Paolo Bonzini, Peter Maydell, linux-kernel, qemu-arm, qemu-devel
Em Mon, 12 Aug 2024 13:57:44 +0200
Igor Mammedov <imammedo@redhat.com> escreveu:
> n Platform Error Record - CPER - as defined at the UEFI
> > +# specification. See
> > +# https://uefi.org/specs/UEFI/2.10/Apx_N_Common_Platform_Error_Record.html#record-header
> > +# for more details.
> > +#
> > +# @notification-type: pre-assigned GUID string indicating the record
> > +# association with an error event notification type, as defined
> > +# at https://uefi.org/specs/UEFI/2.10/Apx_N_Common_Platform_Error_Record.html#record-header
> > +#
> > +# @raw-data: Contains a base64 encoded string with the payload of
> > +# the CPER.
> > +#
> > +# Since: 9.2
> > +##
> > +{ 'struct': 'CommonPlatformErrorRecord',
> > + 'data': {
> > + 'notification-type': 'str',
>
> like was mentioned at v5 review,
> you only need this for setting cper notification type if you are (re)using
>
> acpi_ghes_generic_error_status() && acpi_ghes_generic_error_data()
>
> however while doing this in (6/10), you are also limiting what
> could be encoded in headers to some hardcoded values.
>
> Given QEMU doesn't need to know anything about notification type,
> modulo putting it data block header, it would be beneficial
> to drop 'notification type' from QAPI interface, and include
> error status block and error data headers in raw-data.
>
> This way it should be possible to change headers within python script
> without affecting QEMU and QAPI interface. On top of that
> ghes_record_cper_errors() could be simplified by dropping (in 6/10)
> acpi_ghes_generic_error_status() && acpi_ghes_generic_error_data()
> and just copying raw-data as is directly into error buffer (assuming
> script put needed headers cper data).
>
> From fusing pov it's also beneficial to try generate junk error status
> block headers, for which python script looks like ideal place to put
> it in.
Got it. Will change it to just:
{ 'command': 'ghes-cper',
'data': {
'cper': 'str'
},
'features': [ 'unstable' ]
}
where cper contains an base64-encoded string with the entire raw data
including generic error status end generic error data.
I'm moving the current defaults to the python script. Let's merge
this with the defaults there. The script can later be modified to
allow changing such defaults.
Thanks,
Mauro
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation
2024-08-12 12:18 ` Igor Mammedov
@ 2024-08-13 23:29 ` Mauro Carvalho Chehab
0 siblings, 0 replies; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2024-08-13 23:29 UTC (permalink / raw)
To: Igor Mammedov
Cc: Jonathan Cameron, Shiju Jose, Ani Sinha, Dongjiu Geng,
Paolo Bonzini, Peter Maydell, Shannon Zhao, qemu-arm, qemu-devel
Em Mon, 12 Aug 2024 14:18:35 +0200
Igor Mammedov <imammedo@redhat.com> escreveu:
> On Thu, 8 Aug 2024 14:57:35 +0200
> Mauro Carvalho Chehab <mchehab+huawei@kernel.org> wrote:
>
> > Em Thu, 8 Aug 2024 14:26:26 +0200
> > Mauro Carvalho Chehab <mchehab+huawei@kernel.org> escreveu:
> >
> > > v6:
> > > - PNP0C33 device creation moved to aml-build.c;
> > > - acpi_ghes record functions now use ACPI notify parameter,
> > > instead of source ID;
> > > - the number of source IDs is now automatically calculated;
> > > - some code cleanups and function/var renames;
> > > - some fixes and cleanups at the error injection script;
> > > - ghes cper stub now produces an error if cper JSON is not compiled;
> > > - Offset calculation logic for GHES was refactored;
> > > - Updated documentation to reflect the GHES allocated size;
> > > - Added a x-mpidr object for QOM usage;
> > > - Added a patch making usage of x-mpidr field at ARM injection
> > > script;
>
> stopping review at 5/10 and expecting a version with
> GHES source to error status block mapping fetched from
> HEST in guest RAM, instead of pre-calculated offsets
> in source code (as in this series) to avoid migration
> issues and keeping compat plumbing manageable down the road.
Done. Sent a version 7 addressing it, and the other received
feedbacks. On this version, there are just two offsets used
during error injection:
1) the ack offset: represented relative to HEST table;
2) the CPER data offset: relative to /etc/hardware_errors table.
Thanks,
Mauro
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2024-08-13 23:30 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-08 12:26 [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
2024-08-08 12:26 ` [PATCH v6 01/10] acpi/generic_event_device: add an APEI error device Mauro Carvalho Chehab
2024-08-12 11:20 ` Igor Mammedov
2024-08-08 12:26 ` [PATCH v6 02/10] arm/virt: Wire up a GED error device for ACPI / GHES Mauro Carvalho Chehab
2024-08-12 11:27 ` Igor Mammedov
2024-08-08 12:26 ` [PATCH v6 03/10] acpi/ghes: Add support for GED error device Mauro Carvalho Chehab
2024-08-12 11:28 ` Igor Mammedov
2024-08-08 12:26 ` [PATCH v6 04/10] qapi/ghes-cper: add an interface to do generic CPER error injection Mauro Carvalho Chehab
2024-08-08 13:23 ` Markus Armbruster
2024-08-12 11:57 ` Igor Mammedov
2024-08-13 22:52 ` Mauro Carvalho Chehab
2024-08-08 12:26 ` [PATCH v6 05/10] acpi/ghes: rework the logic to handle HEST source ID Mauro Carvalho Chehab
2024-08-08 12:26 ` [PATCH v6 06/10] acpi/ghes: add support for generic error injection via QAPI Mauro Carvalho Chehab
2024-08-08 12:26 ` [PATCH v6 07/10] docs: acpi_hest_ghes: fix documentation for CPER size Mauro Carvalho Chehab
2024-08-12 11:59 ` Igor Mammedov
2024-08-08 12:26 ` [PATCH v6 08/10] scripts/ghes_inject: add a script to generate GHES error inject Mauro Carvalho Chehab
2024-08-08 13:21 ` Markus Armbruster
2024-08-08 12:26 ` [PATCH v6 09/10] target/arm: add an experimental mpidr arm cpu property object Mauro Carvalho Chehab
2024-08-12 12:02 ` Igor Mammedov
2024-08-08 12:26 ` [PATCH v6 10/10] scripts/arm_processor_error.py: retrieve mpidr if not filled Mauro Carvalho Chehab
2024-08-08 12:57 ` [PATCH v6 00/10] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
2024-08-12 12:18 ` Igor Mammedov
2024-08-13 23:29 ` Mauro Carvalho Chehab
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).