Skip to content
This repository has been archived by the owner on Jul 16, 2024. It is now read-only.

Commit

Permalink
ACPI: APEI: Better fix to avoid spamming the console with old error logs
Browse files Browse the repository at this point in the history
The fix in commit 3f8dec116210 ("ACPI/APEI: Limit printable size of BERT
table data") does not work as intended on systems where the BIOS has a
fixed size block of memory for the BERT table, relying on s/w to quit
when it finds a record with estatus->block_status == 0. On these systems
all errors are suppressed because the check:

	if (region_len < ACPI_BERT_PRINT_MAX_LEN)

always fails.

New scheme skips individual CPER records that are too large, and also
limits the total number of records that will be printed to 5.

Fixes: 3f8dec116210 ("ACPI/APEI: Limit printable size of BERT table data")
Cc: All applicable <[email protected]>
Signed-off-by: Tony Luck <[email protected]>
Signed-off-by: Rafael J. Wysocki <[email protected]>
(cherry picked from commit c3481b6b75b4797657838f44028fd28226ab48e0)
  • Loading branch information
aegl authored and bobolmw committed Sep 1, 2022
1 parent 2d38a08 commit 94d631c
Showing 1 changed file with 23 additions and 8 deletions.
31 changes: 23 additions & 8 deletions drivers/acpi/apei/bert.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,41 +31,53 @@

#undef pr_fmt
#define pr_fmt(fmt) "BERT: " fmt

#define ACPI_BERT_PRINT_MAX_RECORDS 5
#define ACPI_BERT_PRINT_MAX_LEN 1024

static int bert_disable;

/*
* Print "all" the error records in the BERT table, but avoid huge spam to
* the console if the BIOS included oversize records, or too many records.
* Skipping some records here does not lose anything because the full
* data is available to user tools in:
* /sys/firmware/acpi/tables/data/BERT
*/
static void __init bert_print_all(struct acpi_bert_region *region,
unsigned int region_len)
{
struct acpi_hest_generic_status *estatus =
(struct acpi_hest_generic_status *)region;
int remain = region_len;
int printed = 0, skipped = 0;
u32 estatus_len;

while (remain >= sizeof(struct acpi_bert_region)) {
estatus_len = cper_estatus_len(estatus);
if (remain < estatus_len) {
pr_err(FW_BUG "Truncated status block (length: %u).\n",
estatus_len);
return;
break;
}

/* No more error records. */
if (!estatus->block_status)
return;
break;

if (cper_estatus_check(estatus)) {
pr_err(FW_BUG "Invalid error record.\n");
return;
break;
}

pr_info_once("Error records from previous boot:\n");
if (region_len < ACPI_BERT_PRINT_MAX_LEN)
if (estatus_len < ACPI_BERT_PRINT_MAX_LEN &&
printed < ACPI_BERT_PRINT_MAX_RECORDS) {
pr_info_once("Error records from previous boot:\n");
cper_estatus_print(KERN_INFO HW_ERR, estatus);
else
pr_info_once("Max print length exceeded, table data is available at:\n"
"/sys/firmware/acpi/tables/data/BERT");
printed++;
} else {
skipped++;
}

/*
* Because the boot error source is "one-time polled" type,
Expand All @@ -77,6 +89,9 @@ static void __init bert_print_all(struct acpi_bert_region *region,
estatus = (void *)estatus + estatus_len;
remain -= estatus_len;
}

if (skipped)
pr_info(HW_ERR "Skipped %d error records\n", skipped);
}

static int __init setup_bert_disable(char *str)
Expand Down

0 comments on commit 94d631c

Please sign in to comment.