|
@@ -364,10 +364,37 @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
|
|
|
ags->present = true;
|
|
|
}
|
|
|
|
|
|
+static void get_hw_error_offsets(uint64_t ghes_addr,
|
|
|
+ uint64_t *cper_addr,
|
|
|
+ uint64_t *read_ack_register_addr)
|
|
|
+{
|
|
|
+ if (!ghes_addr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * non-HEST version supports only one source, so no need to change
|
|
|
+ * the start offset based on the source ID. Also, we can't validate
|
|
|
+ * the source ID, as it is stored inside the HEST table.
|
|
|
+ */
|
|
|
+
|
|
|
+ cpu_physical_memory_read(ghes_addr, cper_addr,
|
|
|
+ sizeof(*cper_addr));
|
|
|
+
|
|
|
+ *cper_addr = le64_to_cpu(*cper_addr);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * As the current version supports only one source, the ack offset is
|
|
|
+ * just sizeof(uint64_t).
|
|
|
+ */
|
|
|
+ *read_ack_register_addr = ghes_addr +
|
|
|
+ ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t);
|
|
|
+}
|
|
|
+
|
|
|
void ghes_record_cper_errors(const void *cper, size_t len,
|
|
|
uint16_t source_id, Error **errp)
|
|
|
{
|
|
|
- uint64_t error_block_addr, read_ack_register_addr, read_ack_register = 0;
|
|
|
+ uint64_t cper_addr = 0, read_ack_register_addr = 0, read_ack_register;
|
|
|
uint64_t start_addr;
|
|
|
AcpiGedState *acpi_ged_state;
|
|
|
AcpiGhesState *ags;
|
|
@@ -389,18 +416,13 @@ void ghes_record_cper_errors(const void *cper, size_t len,
|
|
|
|
|
|
start_addr += source_id * sizeof(uint64_t);
|
|
|
|
|
|
- cpu_physical_memory_read(start_addr, &error_block_addr,
|
|
|
- sizeof(error_block_addr));
|
|
|
+ get_hw_error_offsets(start_addr, &cper_addr, &read_ack_register_addr);
|
|
|
|
|
|
- error_block_addr = le64_to_cpu(error_block_addr);
|
|
|
- if (!error_block_addr) {
|
|
|
+ if (!cper_addr) {
|
|
|
error_setg(errp, "can not find Generic Error Status Block");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- 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));
|
|
|
|
|
@@ -421,7 +443,7 @@ void ghes_record_cper_errors(const void *cper, size_t len,
|
|
|
&read_ack_register, sizeof(uint64_t));
|
|
|
|
|
|
/* Write the generic error data entry into guest memory */
|
|
|
- cpu_physical_memory_write(error_block_addr, cper, len);
|
|
|
+ cpu_physical_memory_write(cper_addr, cper, len);
|
|
|
|
|
|
return;
|
|
|
}
|