@@ -181,51 +181,24 @@ static void acpi_ghes_build_append_mem_cper(GArray *table,
181
181
build_append_int_noprefix (table , 0 , 7 );
182
182
}
183
183
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 )
186
188
{
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
-
194
189
/* invalid fru id: ACPI 4.0: 17.3.2.6.1 Generic Error Data,
195
190
* Table 17-13 Generic Error Data Entry
196
191
*/
197
192
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 );
210
193
211
194
/* Build the new generic error status block header */
212
195
acpi_ghes_generic_error_status (block , ACPI_GEBS_UNCORRECTABLE ,
213
196
0 , 0 , data_length , ACPI_CPER_SEV_RECOVERABLE );
214
197
215
198
/* 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 ,
217
200
ACPI_CPER_SEV_RECOVERABLE , 0 , 0 ,
218
201
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 ;
229
202
}
230
203
231
204
/*
@@ -383,15 +356,18 @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
383
356
ags -> present = true;
384
357
}
385
358
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 )
387
361
{
388
362
uint64_t error_block_addr , read_ack_register_addr , read_ack_register = 0 ;
389
363
uint64_t start_addr ;
390
- bool ret = -1 ;
391
364
AcpiGedState * acpi_ged_state ;
392
365
AcpiGhesState * ags ;
393
366
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
+ }
395
371
396
372
acpi_ged_state = ACPI_GED (object_resolve_path_type ("" , TYPE_ACPI_GED ,
397
373
NULL ));
@@ -406,6 +382,10 @@ int acpi_ghes_record_errors(uint16_t source_id, uint64_t physical_address)
406
382
sizeof (error_block_addr ));
407
383
408
384
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
+ }
409
389
410
390
read_ack_register_addr = start_addr +
411
391
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)
415
395
416
396
/* zero means OSPM does not acknowledge the error */
417
397
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
+ }
428
403
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 ;
433
451
}
434
452
435
- return ret ;
453
+ return 0 ;
436
454
}
437
455
438
456
bool acpi_ghes_present (void )
0 commit comments