[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v10 (RESEND) 08/20] acpi/ghes: Use HEST table offsets when prepar
From: |
Mauro Carvalho Chehab |
Subject: |
[PATCH v10 (RESEND) 08/20] acpi/ghes: Use HEST table offsets when preparing GHES records |
Date: |
Thu, 12 Jun 2025 17:17:32 +0200 |
There are two pointers that are needed during error injection:
1. The start address of the CPER block to be stored;
2. The address of the read ack.
It is preferable to calculate them from the HEST table. This allows
checking the source ID, the size of the table and the type of the
HEST error block structures.
Yet, keep the old code, as this is needed for migration purposes
from older QEMU versions.
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
---
hw/acpi/ghes.c | 100 +++++++++++++++++++++++++++++++++++++++++
include/hw/acpi/ghes.h | 2 +-
2 files changed, 101 insertions(+), 1 deletion(-)
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
index cbc96c1909f0..668ca72587c7 100644
--- a/hw/acpi/ghes.c
+++ b/hw/acpi/ghes.c
@@ -41,6 +41,12 @@
/* Address offset in Generic Address Structure(GAS) */
#define GAS_ADDR_OFFSET 4
+/*
+ * ACPI spec 1.0b
+ * 5.2.3 System Description Table Header
+ */
+#define ACPI_DESC_HEADER_OFFSET 36
+
/*
* The total size of Generic Error Data Entry
* ACPI 6.1/6.2: 18.3.2.7.1 Generic Error Data,
@@ -61,6 +67,30 @@
*/
#define ACPI_GHES_GESB_SIZE 20
+/*
+ * See the memory layout map at docs/specs/acpi_hest_ghes.rst.
+ */
+
+/*
+ * ACPI 6.1: 18.3.2.8 Generic Hardware Error Source version 2
+ * Table 18-344 Generic Hardware Error Source version 2 (GHESv2) Structure
+ */
+#define HEST_GHES_V2_ENTRY_SIZE 92
+
+/*
+ * ACPI 6.1: 18.3.2.8 Generic Hardware Error Source version 2
+ * Table 18-344 Generic Hardware Error Source version 2 (GHESv2) Structure
+ * Read Ack Register
+ */
+#define GHES_READ_ACK_ADDR_OFF 64
+
+/*
+ * ACPI 6.1: 18.3.2.7: Generic Hardware Error Source
+ * Table 18-341 Generic Hardware Error Source Structure
+ * Error Status Address
+ */
+#define GHES_ERR_STATUS_ADDR_OFF 20
+
/*
* Values for error_severity field
*/
@@ -408,6 +438,73 @@ static void get_hw_error_offsets(uint64_t ghes_addr,
*read_ack_register_addr = ghes_addr + sizeof(uint64_t);
}
+static void get_ghes_source_offsets(uint16_t source_id,
+ uint64_t hest_addr,
+ uint64_t *cper_addr,
+ uint64_t *read_ack_start_addr,
+ Error **errp)
+{
+ uint64_t hest_err_block_addr, hest_read_ack_addr;
+ uint64_t err_source_entry, error_block_addr;
+ uint32_t num_sources, i;
+
+ hest_addr += ACPI_DESC_HEADER_OFFSET;
+
+ cpu_physical_memory_read(hest_addr, &num_sources,
+ sizeof(num_sources));
+ num_sources = le32_to_cpu(num_sources);
+
+ err_source_entry = hest_addr + sizeof(num_sources);
+
+ /*
+ * Currently, HEST Error source navigates only for GHESv2 tables
+ */
+ for (i = 0; i < num_sources; i++) {
+ uint64_t addr = err_source_entry;
+ uint16_t type, src_id;
+
+ cpu_physical_memory_read(addr, &type, sizeof(type));
+ type = le16_to_cpu(type);
+
+ /* For now, we only know the size of GHESv2 table */
+ if (type != ACPI_GHES_SOURCE_GENERIC_ERROR_V2) {
+ error_setg(errp, "HEST: type %d not supported.", type);
+ return;
+ }
+
+ /* Compare CPER source ID at the GHESv2 structure */
+ addr += sizeof(type);
+ cpu_physical_memory_read(addr, &src_id, sizeof(src_id));
+ if (le16_to_cpu(src_id) == source_id) {
+ break;
+ }
+
+ err_source_entry += HEST_GHES_V2_ENTRY_SIZE;
+ }
+ if (i == num_sources) {
+ error_setg(errp, "HEST: Source %d not found.", source_id);
+ return;
+ }
+
+ /* Navigate through table address pointers */
+ hest_err_block_addr = err_source_entry + GHES_ERR_STATUS_ADDR_OFF +
+ GAS_ADDR_OFFSET;
+
+ cpu_physical_memory_read(hest_err_block_addr, &error_block_addr,
+ sizeof(error_block_addr));
+ error_block_addr = le64_to_cpu(error_block_addr);
+
+ cpu_physical_memory_read(error_block_addr, cper_addr,
+ sizeof(*cper_addr));
+ *cper_addr = le64_to_cpu(*cper_addr);
+
+ hest_read_ack_addr = err_source_entry + GHES_READ_ACK_ADDR_OFF +
+ GAS_ADDR_OFFSET;
+ cpu_physical_memory_read(hest_read_ack_addr, read_ack_start_addr,
+ sizeof(*read_ack_start_addr));
+ *read_ack_start_addr = le64_to_cpu(*read_ack_start_addr);
+}
+
void ghes_record_cper_errors(AcpiGhesState *ags, const void *cper, size_t len,
uint16_t source_id, Error **errp)
{
@@ -423,6 +520,9 @@ void ghes_record_cper_errors(AcpiGhesState *ags, const void
*cper, size_t len,
if (!ags->use_hest_addr) {
get_hw_error_offsets(le64_to_cpu(ags->hw_error_le),
&cper_addr, &read_ack_register_addr);
+ } else {
+ get_ghes_source_offsets(source_id, le64_to_cpu(ags->hest_addr_le),
+ &cper_addr, &read_ack_register_addr, errp);
}
cpu_physical_memory_read(read_ack_register_addr,
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
index ea9baab764e2..5265102ba51f 100644
--- a/include/hw/acpi/ghes.h
+++ b/include/hw/acpi/ghes.h
@@ -78,7 +78,7 @@ enum {
typedef struct AcpiGhesState {
uint64_t hest_addr_le;
uint64_t hw_error_le;
- bool use_hest_addr; /* Currently, always false */
+ bool use_hest_addr; /* True if HEST address is present */
} AcpiGhesState;
void acpi_build_hest(AcpiGhesState *ags, GArray *table_data,
--
2.49.0
- [PATCH v10 (RESEND) 06/20] acpi/ghes: prepare to change the way HEST offsets are calculated, (continued)
- [PATCH v10 (RESEND) 06/20] acpi/ghes: prepare to change the way HEST offsets are calculated, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 10/20] acpi/ghes: add a notifier to notify when error data is ready, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 02/20] tests/qtest/bios-tables-test: extend to also check HEST table, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 09/20] acpi/ghes: don't hard-code the number of sources for HEST table, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 03/20] tests/acpi: virt: update HEST file with its current data, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 05/20] acpi/ghes: Cleanup the code which gets ghes ged state, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 01/20] tests/acpi: virt: add an empty HEST file, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 04/20] Revert "hw/acpi/ghes: Make ghes_record_cper_errors() static", Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 11/20] acpi/generic_event_device: Update GHES migration to cover hest addr, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 07/20] acpi/ghes: add a firmware file with HEST address, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 08/20] acpi/ghes: Use HEST table offsets when preparing GHES records,
Mauro Carvalho Chehab <=
- [PATCH v10 (RESEND) 13/20] acpi/generic_event_device: add an APEI error device, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 14/20] tests/acpi: virt: allow acpi table changes at DSDT and HEST tables, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 12/20] acpi/generic_event_device: add logic to detect if HEST addr is available, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 17/20] acpi/generic_event_device.c: enable use_hest_addr for QEMU 10.x, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 15/20] arm/virt: Wire up a GED error device for ACPI / GHES, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 18/20] tests/acpi: virt: update HEST and DSDT tables, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 20/20] scripts/ghes_inject: add a script to generate GHES error inject, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 16/20] qapi/acpi-hest: add an interface to do generic CPER error injection, Mauro Carvalho Chehab, 2025/06/12
- [PATCH v10 (RESEND) 19/20] docs: hest: add new "etc/acpi_table_hest_addr" and update workflow, Mauro Carvalho Chehab, 2025/06/12