The OS kernels navigate between HEST, error source struct and CPER by the usage of some pointers. Double-check if such pointers were properly initializing, ensuring that they match the right address for CPER.
Signed-off-by: Mauro Carvalho Chehab <mchehab+hua...@kernel.org> --- hw/acpi/ghes.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c index a822a5eafaa0..51e2e40e5a9c 100644 --- a/hw/acpi/ghes.c +++ b/hw/acpi/ghes.c @@ -85,6 +85,9 @@ enum AcpiHestSourceId { #define HEST_GHES_V2_TABLE_SIZE 92 #define GHES_ACK_OFFSET (64 + GAS_ADDR_OFFSET + ACPI_HEST_HEADER_SIZE) +/* ACPI 6.2: 18.3.2.7: Generic Hardware Error Source */ +#define GHES_ERR_ST_ADDR_OFFSET (20 + GAS_ADDR_OFFSET + ACPI_HEST_HEADER_SIZE) + /* * Values for error_severity field */ @@ -425,7 +428,10 @@ NotifierList acpi_generic_error_notifiers = void ghes_record_cper_errors(const void *cper, size_t len, enum AcpiGhesNotifyType notify, Error **errp) { - uint64_t cper_addr, read_ack_start_addr; + uint64_t hest_read_ack_start_addr, read_ack_start_addr; + uint64_t read_ack_start_addr_2, err_source_struct; + uint64_t hest_err_block_addr, error_block_addr; + uint64_t cper_addr, cper_addr_2; enum AcpiHestSourceId source; AcpiGedState *acpi_ged_state; AcpiGhesState *ags; @@ -450,6 +456,28 @@ void ghes_record_cper_errors(const void *cper, size_t len, cper_addr += ACPI_HEST_SRC_ID_COUNT * sizeof(uint64_t); cper_addr += source * ACPI_GHES_MAX_RAW_DATA_LENGTH; + err_source_struct = le64_to_cpu(ags->hest_addr_le) + + source * HEST_GHES_V2_TABLE_SIZE; + + /* Check if BIOS addr pointers were properly generated */ + + hest_err_block_addr = err_source_struct + GHES_ERR_ST_ADDR_OFFSET; + hest_read_ack_start_addr = err_source_struct + GHES_ACK_OFFSET; + + cpu_physical_memory_read(hest_err_block_addr, &error_block_addr, + sizeof(error_block_addr)); + + cpu_physical_memory_read(error_block_addr, &cper_addr_2, + sizeof(error_block_addr)); + + cpu_physical_memory_read(hest_read_ack_start_addr, &read_ack_start_addr_2, + sizeof(read_ack_start_addr_2)); + + assert(cper_addr == cper_addr_2); + assert(read_ack_start_addr == read_ack_start_addr_2); + + /* Update ACK offset to notify about a new error */ + cpu_physical_memory_read(read_ack_start_addr, &read_ack, sizeof(uint64_t)); -- 2.46.0