Skip to content

Commit 48b0dcd

Browse files
mchehabmstsirkin
authored andcommitted
acpi/ghes: make the GHES record generation more generic
Split the code into separate functions to allow using the common CPER filling code by different error sources. The generic code was moved to ghes_record_cper_errors(), and ghes_gen_err_data_uncorrectable_recoverable() now contains only a logic to fill the Generic Error Data part of the record, as described at: ACPI 6.2: 18.3.2.7.1 Generic Error Data The remaining code to generate a memory error now belongs to acpi_ghes_record_errors() function. A further patch will give it a better name. Signed-off-by: Mauro Carvalho Chehab <[email protected]> Reviewed-by: Igor Mammedov <[email protected]> Reviewed-by: Jonathan Cameron <[email protected]> Message-Id: <68d9f787d8c4fc8d1dbc227d6902fe801e42dea9.1736945236.git.mchehab+huawei@kernel.org> Reviewed-by: Michael S. Tsirkin <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent 2e223c5 commit 48b0dcd

File tree

2 files changed

+71
-50
lines changed

2 files changed

+71
-50
lines changed

hw/acpi/ghes.c

Lines changed: 68 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -181,51 +181,24 @@ static void acpi_ghes_build_append_mem_cper(GArray *table,
181181
build_append_int_noprefix(table, 0, 7);
182182
}
183183

184-
static int acpi_ghes_record_mem_error(uint64_t error_block_address,
185-
uint64_t error_physical_addr)
184+
static void
185+
ghes_gen_err_data_uncorrectable_recoverable(GArray *block,
186+
const uint8_t *section_type,
187+
int data_length)
186188
{
187-
GArray *block;
188-
189-
/* Memory Error Section Type */
190-
const uint8_t uefi_cper_mem_sec[] =
191-
UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \
192-
0xED, 0x7C, 0x83, 0xB1);
193-
194189
/* invalid fru id: ACPI 4.0: 17.3.2.6.1 Generic Error Data,
195190
* Table 17-13 Generic Error Data Entry
196191
*/
197192
QemuUUID fru_id = {};
198-
uint32_t data_length;
199-
200-
block = g_array_new(false, true /* clear */, 1);
201-
202-
/* This is the length if adding a new generic error data entry*/
203-
data_length = ACPI_GHES_DATA_LENGTH + ACPI_GHES_MEM_CPER_LENGTH;
204-
/*
205-
* It should not run out of the preallocated memory if adding a new generic
206-
* error data entry
207-
*/
208-
assert((data_length + ACPI_GHES_GESB_SIZE) <=
209-
ACPI_GHES_MAX_RAW_DATA_LENGTH);
210193

211194
/* Build the new generic error status block header */
212195
acpi_ghes_generic_error_status(block, ACPI_GEBS_UNCORRECTABLE,
213196
0, 0, data_length, ACPI_CPER_SEV_RECOVERABLE);
214197

215198
/* Build this new generic error data entry header */
216-
acpi_ghes_generic_error_data(block, uefi_cper_mem_sec,
199+
acpi_ghes_generic_error_data(block, section_type,
217200
ACPI_CPER_SEV_RECOVERABLE, 0, 0,
218201
ACPI_GHES_MEM_CPER_LENGTH, fru_id, 0);
219-
220-
/* Build the memory section CPER for above new generic error data entry */
221-
acpi_ghes_build_append_mem_cper(block, error_physical_addr);
222-
223-
/* Write the generic error data entry into guest memory */
224-
cpu_physical_memory_write(error_block_address, block->data, block->len);
225-
226-
g_array_free(block, true);
227-
228-
return 0;
229202
}
230203

231204
/*
@@ -383,15 +356,18 @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
383356
ags->present = true;
384357
}
385358

386-
int acpi_ghes_record_errors(uint16_t source_id, uint64_t physical_address)
359+
void ghes_record_cper_errors(const void *cper, size_t len,
360+
uint16_t source_id, Error **errp)
387361
{
388362
uint64_t error_block_addr, read_ack_register_addr, read_ack_register = 0;
389363
uint64_t start_addr;
390-
bool ret = -1;
391364
AcpiGedState *acpi_ged_state;
392365
AcpiGhesState *ags;
393366

394-
assert(source_id < ACPI_GHES_ERROR_SOURCE_COUNT);
367+
if (len > ACPI_GHES_MAX_RAW_DATA_LENGTH) {
368+
error_setg(errp, "GHES CPER record is too big: %zd", len);
369+
return;
370+
}
395371

396372
acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED,
397373
NULL));
@@ -406,6 +382,10 @@ int acpi_ghes_record_errors(uint16_t source_id, uint64_t physical_address)
406382
sizeof(error_block_addr));
407383

408384
error_block_addr = le64_to_cpu(error_block_addr);
385+
if (!error_block_addr) {
386+
error_setg(errp, "can not find Generic Error Status Block");
387+
return;
388+
}
409389

410390
read_ack_register_addr = start_addr +
411391
ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t);
@@ -415,24 +395,62 @@ int acpi_ghes_record_errors(uint16_t source_id, uint64_t physical_address)
415395

416396
/* zero means OSPM does not acknowledge the error */
417397
if (!read_ack_register) {
418-
error_report("OSPM does not acknowledge previous error,"
419-
" so can not record CPER for current error anymore");
420-
} else if (error_block_addr) {
421-
read_ack_register = cpu_to_le64(0);
422-
/*
423-
* Clear the Read Ack Register, OSPM will write it to 1 when
424-
* it acknowledges this error.
425-
*/
426-
cpu_physical_memory_write(read_ack_register_addr,
427-
&read_ack_register, sizeof(uint64_t));
398+
error_setg(errp,
399+
"OSPM does not acknowledge previous error,"
400+
" so can not record CPER for current error anymore");
401+
return;
402+
}
428403

429-
ret = acpi_ghes_record_mem_error(error_block_addr,
430-
physical_address);
431-
} else {
432-
error_report("can not find Generic Error Status Block");
404+
read_ack_register = cpu_to_le64(0);
405+
/*
406+
* Clear the Read Ack Register, OSPM will write 1 to this register when
407+
* it acknowledges the error.
408+
*/
409+
cpu_physical_memory_write(read_ack_register_addr,
410+
&read_ack_register, sizeof(uint64_t));
411+
412+
/* Write the generic error data entry into guest memory */
413+
cpu_physical_memory_write(error_block_addr, cper, len);
414+
415+
return;
416+
}
417+
418+
int acpi_ghes_record_errors(uint16_t source_id, uint64_t physical_address)
419+
{
420+
/* Memory Error Section Type */
421+
const uint8_t guid[] =
422+
UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \
423+
0xED, 0x7C, 0x83, 0xB1);
424+
Error *errp = NULL;
425+
int data_length;
426+
GArray *block;
427+
428+
block = g_array_new(false, true /* clear */, 1);
429+
430+
data_length = ACPI_GHES_DATA_LENGTH + ACPI_GHES_MEM_CPER_LENGTH;
431+
/*
432+
* It should not run out of the preallocated memory if adding a new generic
433+
* error data entry
434+
*/
435+
assert((data_length + ACPI_GHES_GESB_SIZE) <=
436+
ACPI_GHES_MAX_RAW_DATA_LENGTH);
437+
438+
ghes_gen_err_data_uncorrectable_recoverable(block, guid, data_length);
439+
440+
/* Build the memory section CPER for above new generic error data entry */
441+
acpi_ghes_build_append_mem_cper(block, physical_address);
442+
443+
/* Report the error */
444+
ghes_record_cper_errors(block->data, block->len, source_id, &errp);
445+
446+
g_array_free(block, true);
447+
448+
if (errp) {
449+
error_report_err(errp);
450+
return -1;
433451
}
434452

435-
return ret;
453+
return 0;
436454
}
437455

438456
bool acpi_ghes_present(void)

include/hw/acpi/ghes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#define ACPI_GHES_H
2424

2525
#include "hw/acpi/bios-linker-loader.h"
26+
#include "qapi/error.h"
2627

2728
/*
2829
* Values for Hardware Error Notification Type field
@@ -73,6 +74,8 @@ void acpi_build_hest(GArray *table_data, GArray *hardware_errors,
7374
const char *oem_id, const char *oem_table_id);
7475
void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
7576
GArray *hardware_errors);
77+
void ghes_record_cper_errors(const void *cper, size_t len,
78+
uint16_t source_id, Error **errp);
7679
int acpi_ghes_record_errors(uint16_t source_id, uint64_t error_physical_addr);
7780

7881
/**

0 commit comments

Comments
 (0)