On Fri, 16 Aug 2024 09:37:38 +0200 Mauro Carvalho Chehab <mchehab+hua...@kernel.org> wrote:
> 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.came...@huawei.com> > Co-authored-by: Shiju Jose <shiju.j...@huawei.com> > Co-authored-by: Mauro Carvalho Chehab <mchehab+hua...@kernel.org> > Signed-off-by: Jonathan Cameron <jonathan.came...@huawei.com> > Signed-off-by: Shiju Jose <shiju.j...@huawei.com> > Signed-off-by: Mauro Carvalho Chehab <mchehab+hua...@kernel.org> > --- > hw/acpi/ghes.c | 57 +++++++++++++++++++++++++++++++++++++++++++++ > hw/acpi/ghes_cper.c | 2 +- > 2 files changed, 58 insertions(+), 1 deletion(-) > > diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c > index 7870f51e2a9e..a3ae710dcf81 100644 > --- a/hw/acpi/ghes.c > +++ b/hw/acpi/ghes.c > @@ -500,6 +500,63 @@ int acpi_ghes_record_errors(enum AcpiGhesNotifyType > notify, > NotifierList acpi_generic_error_notifiers = > NOTIFIER_LIST_INITIALIZER(error_device_notifiers); > > +void ghes_record_cper_errors(uint8_t *cper, size_t len, > + enum AcpiGhesNotifyType notify, Error **errp) > +{ > + uint64_t cper_addr, read_ack_start_addr; > + enum AcpiHestSourceId source; > + AcpiGedState *acpi_ged_state; > + AcpiGhesState *ags; > + uint64_t read_ack; > + > + if (ghes_notify_to_source_id(notify, &source)) { > + error_setg(errp, > + "GHES: Invalid error block/ack address(es) for notify %d", > + notify); > + return; > + } > + > + acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED, > + NULL)); > + g_assert(acpi_ged_state); > + ags = &acpi_ged_state->ghes_state; > + > + cper_addr = le64_to_cpu(ags->ghes_addr_le); ^^^ suggest to rename to error_block_address that way reader can easily match it with spec. > + cper_addr += ACPI_HEST_SRC_ID_COUNT * sizeof(uint64_t); and it would be better to merge this with previous line to be more clear + to avoid shifting meaning of variable between lines. > + read_ack_start_addr = cper_addr + source * sizeof(uint64_t); > + cper_addr += ACPI_HEST_SRC_ID_COUNT * sizeof(uint64_t); > + cper_addr += source * ACPI_GHES_MAX_RAW_DATA_LENGTH; I'd avoid changing meaning of variable, it adds up to confusion. Anyway, what the point of of above math? > + > + cpu_physical_memory_read(read_ack_start_addr, > + &read_ack, sizeof(uint64_t)); s/sizeof(uint64_t)/sizeof(read_ack)/ ditto elsewhere > + > + /* 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, (uint64_t)); we don't do this for SEV so, why are you setting it to 1 here? > + return; > + } > + > + read_ack = cpu_to_le64(0); > + cpu_physical_memory_write(read_ack_start_addr, > + &read_ack, sizeof(uint64_t)); > + > + /* Build CPER record */ > + > + if (len > ACPI_GHES_MAX_RAW_DATA_LENGTH) { > + error_setg(errp, "GHES CPER record is too big: %ld", len); > + } move check at start of function? > + > + /* Write the generic error data entry into guest memory */ > + cpu_physical_memory_write(cper_addr, cper, len); > + > + notifier_list_notify(&acpi_generic_error_notifiers, NULL); > +} > + > bool acpi_ghes_present(void) > { > AcpiGedState *acpi_ged_state; > diff --git a/hw/acpi/ghes_cper.c b/hw/acpi/ghes_cper.c > index 92ca84d738de..2328dbff7012 100644 > --- a/hw/acpi/ghes_cper.c > +++ b/hw/acpi/ghes_cper.c > @@ -29,5 +29,5 @@ void qmp_ghes_cper(const char *qmp_cper, > return; > } > > - /* TODO: call a function at ghes */ > + ghes_record_cper_errors(cper, len, ACPI_GHES_NOTIFY_GPIO, errp); > }