acpi: Add support for reporting CrashLog in BERT table
Crash Data are collected and sent to the OS via the ACPI BERT. BUG=None TEST=Built, and BERT successfully generated in the crashLog flow. Signed-off-by: Francois Toguo <francois.toguo.fotso@intel.com> Change-Id: I00e390d735d61beac2e89a726e39119d9b06b3df Signed-off-by: Nikunj A. Dadhania <nikunj.dadhania@intel.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/49799 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
This commit is contained in:
parent
5f30ae3714
commit
522e0dbdaa
|
@ -1331,6 +1331,14 @@ unsigned long acpi_create_lpi_desc_ncst(acpi_lpi_desc_ncst_t *lpi_desc, uint16_t
|
||||||
return lpi_desc->header.length;
|
return lpi_desc->header.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* BERT helpers */
|
||||||
|
bool __weak acpi_is_boot_error_src_present(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
__weak void acpi_soc_fill_bert(acpi_bert_t *bert, void **region, size_t *length) {}
|
||||||
|
|
||||||
unsigned long __weak fw_cfg_acpi_tables(unsigned long start)
|
unsigned long __weak fw_cfg_acpi_tables(unsigned long start)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1352,6 +1360,7 @@ unsigned long write_acpi_tables(unsigned long start)
|
||||||
acpi_tpm2_t *tpm2;
|
acpi_tpm2_t *tpm2;
|
||||||
acpi_madt_t *madt;
|
acpi_madt_t *madt;
|
||||||
acpi_lpit_t *lpit;
|
acpi_lpit_t *lpit;
|
||||||
|
acpi_bert_t *bert;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
unsigned long fw;
|
unsigned long fw;
|
||||||
size_t slic_size, dsdt_size;
|
size_t slic_size, dsdt_size;
|
||||||
|
@ -1573,6 +1582,20 @@ unsigned long write_acpi_tables(unsigned long start)
|
||||||
|
|
||||||
current = acpi_align_current(current);
|
current = acpi_align_current(current);
|
||||||
|
|
||||||
|
if (acpi_is_boot_error_src_present()) {
|
||||||
|
void *region;
|
||||||
|
size_t size;
|
||||||
|
printk(BIOS_DEBUG, "ACPI: * BERT\n");
|
||||||
|
bert = (acpi_bert_t *) current;
|
||||||
|
acpi_soc_fill_bert(bert, ®ion, &size);
|
||||||
|
acpi_write_bert(bert, (uintptr_t)region, size);
|
||||||
|
if (bert->header.length >= sizeof(acpi_bert_t)) {
|
||||||
|
current += bert->header.length;
|
||||||
|
acpi_add_table(rsdp, bert);
|
||||||
|
}
|
||||||
|
current = acpi_align_current(current);
|
||||||
|
}
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "current = %lx\n", current);
|
printk(BIOS_DEBUG, "current = %lx\n", current);
|
||||||
|
|
||||||
for (dev = all_devices; dev; dev = dev->next) {
|
for (dev = all_devices; dev; dev = dev->next) {
|
||||||
|
|
|
@ -106,6 +106,7 @@ static void revise_error_sizes(acpi_generic_error_status_t *status, size_t size)
|
||||||
entries = bert_entry_count(status);
|
entries = bert_entry_count(status);
|
||||||
entry = acpi_hest_generic_data_nth(status, entries);
|
entry = acpi_hest_generic_data_nth(status, entries);
|
||||||
status->data_length += size;
|
status->data_length += size;
|
||||||
|
status->raw_data_length += size;
|
||||||
if (entry)
|
if (entry)
|
||||||
entry->data_length += size;
|
entry->data_length += size;
|
||||||
}
|
}
|
||||||
|
@ -174,6 +175,7 @@ static acpi_hest_generic_data_v300_t *new_generic_error_entry(
|
||||||
entry->validation_bits |= ACPI_GENERROR_VALID_TIMESTAMP;
|
entry->validation_bits |= ACPI_GENERROR_VALID_TIMESTAMP;
|
||||||
|
|
||||||
status->data_length += sizeof(*entry);
|
status->data_length += sizeof(*entry);
|
||||||
|
status->raw_data_length += sizeof(*entry);
|
||||||
bert_bump_entry_count(status);
|
bert_bump_entry_count(status);
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
|
@ -186,12 +188,52 @@ static size_t sizeof_error_section(guid_t *guid)
|
||||||
return sizeof(cper_proc_generic_error_section_t);
|
return sizeof(cper_proc_generic_error_section_t);
|
||||||
else if (!guidcmp(guid, &CPER_SEC_PROC_IA32X64_GUID))
|
else if (!guidcmp(guid, &CPER_SEC_PROC_IA32X64_GUID))
|
||||||
return sizeof(cper_ia32x64_proc_error_section_t);
|
return sizeof(cper_ia32x64_proc_error_section_t);
|
||||||
|
else if (!guidcmp(guid, &CPER_SEC_FW_ERR_REC_REF_GUID))
|
||||||
|
return sizeof(cper_fw_err_rec_section_t);
|
||||||
/* else if ... sizeof(structures not yet defined) */
|
/* else if ... sizeof(structures not yet defined) */
|
||||||
|
|
||||||
printk(BIOS_ERR, "Error: Requested size of unrecognized CPER GUID\n");
|
printk(BIOS_ERR, "Error: Requested size of unrecognized CPER GUID\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *new_cper_fw_error_crashlog(acpi_generic_error_status_t *status, size_t cl_size)
|
||||||
|
{
|
||||||
|
void *cl_data = bert_allocate_storage(cl_size);
|
||||||
|
if (!cl_data) {
|
||||||
|
printk(BIOS_ERR, "Error: Crashlog entry (size %lu) would exceed available region\n",
|
||||||
|
cl_size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
revise_error_sizes(status, cl_size);
|
||||||
|
|
||||||
|
return cl_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helper to append an ACPI Generic Error Data Entry per crashlog data */
|
||||||
|
acpi_hest_generic_data_v300_t *bert_append_fw_err(acpi_generic_error_status_t *status)
|
||||||
|
{
|
||||||
|
acpi_hest_generic_data_v300_t *entry;
|
||||||
|
cper_fw_err_rec_section_t *fw_err;
|
||||||
|
|
||||||
|
entry = bert_append_error_datasection(status, &CPER_SEC_FW_ERR_REC_REF_GUID);
|
||||||
|
if (!entry)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
status->block_status |= GENERIC_ERR_STS_UNCORRECTABLE_VALID;
|
||||||
|
status->error_severity = ACPI_GENERROR_SEV_FATAL;
|
||||||
|
entry->error_severity = ACPI_GENERROR_SEV_FATAL;
|
||||||
|
|
||||||
|
fw_err = section_of_acpientry(fw_err, entry);
|
||||||
|
|
||||||
|
fw_err->record_type = CRASHLOG_RECORD_TYPE;
|
||||||
|
fw_err->revision = CRASHLOG_FW_ERR_REV;
|
||||||
|
fw_err->record_id = 0;
|
||||||
|
guidcpy(&fw_err->record_guid, &FW_ERR_RECORD_ID_CRASHLOG_GUID);
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
/* Append a new ACPI Generic Error Data Entry plus CPER Error Section to an
|
/* Append a new ACPI Generic Error Data Entry plus CPER Error Section to an
|
||||||
* existing ACPI Generic Error Status Block. The caller is responsible for
|
* existing ACPI Generic Error Status Block. The caller is responsible for
|
||||||
* the setting the status and entry severity, as well as populating all fields
|
* the setting the status and entry severity, as well as populating all fields
|
||||||
|
@ -486,10 +528,14 @@ acpi_generic_error_status_t *bert_new_event(guid_t *guid)
|
||||||
if (!status)
|
if (!status)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
status->raw_data_length = sizeof(*status);
|
||||||
|
|
||||||
if (!guidcmp(guid, &CPER_SEC_PROC_GENERIC_GUID))
|
if (!guidcmp(guid, &CPER_SEC_PROC_GENERIC_GUID))
|
||||||
r = bert_append_genproc(status);
|
r = bert_append_genproc(status);
|
||||||
else if (!guidcmp(guid, &CPER_SEC_PROC_GENERIC_GUID))
|
else if (!guidcmp(guid, &CPER_SEC_PROC_GENERIC_GUID))
|
||||||
r = bert_append_ia32x64(status);
|
r = bert_append_ia32x64(status);
|
||||||
|
if (!guidcmp(guid, &CPER_SEC_FW_ERR_REC_REF_GUID))
|
||||||
|
r = bert_append_fw_err(status);
|
||||||
/* else if other types not implemented */
|
/* else if other types not implemented */
|
||||||
else
|
else
|
||||||
r = NULL;
|
r = NULL;
|
||||||
|
|
|
@ -41,6 +41,9 @@
|
||||||
* +--------------------------------------------------------------------+
|
* +--------------------------------------------------------------------+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define CRASHLOG_RECORD_TYPE 0x2
|
||||||
|
#define CRASHLOG_FW_ERR_REV 0x2
|
||||||
|
|
||||||
/* Get implementation-specific reserved area for generating BERT info */
|
/* Get implementation-specific reserved area for generating BERT info */
|
||||||
void bert_reserved_region(void **start, size_t *size);
|
void bert_reserved_region(void **start, size_t *size);
|
||||||
|
|
||||||
|
@ -120,6 +123,9 @@ acpi_hest_generic_data_v300_t *bert_append_genproc(
|
||||||
acpi_hest_generic_data_v300_t *bert_append_ia32x64(
|
acpi_hest_generic_data_v300_t *bert_append_ia32x64(
|
||||||
acpi_generic_error_status_t *status);
|
acpi_generic_error_status_t *status);
|
||||||
|
|
||||||
|
void *new_cper_fw_error_crashlog(acpi_generic_error_status_t *status, size_t cl_size);
|
||||||
|
acpi_hest_generic_data_v300_t *bert_append_fw_err(acpi_generic_error_status_t *status);
|
||||||
|
|
||||||
/* Add a new event to the BERT region. An event consists of an ACPI Error
|
/* Add a new event to the BERT region. An event consists of an ACPI Error
|
||||||
* Status Block, a Generic Error Data Entry, and an associated CPER Error
|
* Status Block, a Generic Error Data Entry, and an associated CPER Error
|
||||||
* Section.
|
* Section.
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#define _CBMEM_ID_H_
|
#define _CBMEM_ID_H_
|
||||||
|
|
||||||
#define CBMEM_ID_ACPI 0x41435049
|
#define CBMEM_ID_ACPI 0x41435049
|
||||||
|
#define CBMEM_ID_ACPI_BERT 0x42455254
|
||||||
#define CBMEM_ID_ACPI_GNVS 0x474e5653
|
#define CBMEM_ID_ACPI_GNVS 0x474e5653
|
||||||
#define CBMEM_ID_ACPI_UCSI 0x55435349
|
#define CBMEM_ID_ACPI_UCSI 0x55435349
|
||||||
#define CBMEM_ID_AFTER_CAR 0xc4787a93
|
#define CBMEM_ID_AFTER_CAR 0xc4787a93
|
||||||
|
@ -14,6 +15,7 @@
|
||||||
#define CBMEM_ID_CBTABLE_FWD 0x43425443
|
#define CBMEM_ID_CBTABLE_FWD 0x43425443
|
||||||
#define CBMEM_ID_CB_EARLY_DRAM 0x4544524D
|
#define CBMEM_ID_CB_EARLY_DRAM 0x4544524D
|
||||||
#define CBMEM_ID_CONSOLE 0x434f4e53
|
#define CBMEM_ID_CONSOLE 0x434f4e53
|
||||||
|
#define CBMEM_ID_CPU_CRASHLOG 0x4350555f
|
||||||
#define CBMEM_ID_COVERAGE 0x47434f56
|
#define CBMEM_ID_COVERAGE 0x47434f56
|
||||||
#define CBMEM_ID_EHCI_DEBUG 0xe4c1deb9
|
#define CBMEM_ID_EHCI_DEBUG 0xe4c1deb9
|
||||||
#define CBMEM_ID_ELOG 0x454c4f47
|
#define CBMEM_ID_ELOG 0x454c4f47
|
||||||
|
@ -31,6 +33,7 @@
|
||||||
#define CBMEM_ID_MMC_STATUS 0x4d4d4353
|
#define CBMEM_ID_MMC_STATUS 0x4d4d4353
|
||||||
#define CBMEM_ID_MPTABLE 0x534d5054
|
#define CBMEM_ID_MPTABLE 0x534d5054
|
||||||
#define CBMEM_ID_MRCDATA 0x4d524344
|
#define CBMEM_ID_MRCDATA 0x4d524344
|
||||||
|
#define CBMEM_ID_PMC_CRASHLOG 0x504d435f
|
||||||
#define CBMEM_ID_VAR_MRCDATA 0x4d524345
|
#define CBMEM_ID_VAR_MRCDATA 0x4d524345
|
||||||
#define CBMEM_ID_MTC 0xcb31d31c
|
#define CBMEM_ID_MTC 0xcb31d31c
|
||||||
#define CBMEM_ID_NONE 0x00000000
|
#define CBMEM_ID_NONE 0x00000000
|
||||||
|
@ -76,6 +79,7 @@
|
||||||
|
|
||||||
#define CBMEM_ID_TO_NAME_TABLE \
|
#define CBMEM_ID_TO_NAME_TABLE \
|
||||||
{ CBMEM_ID_ACPI, "ACPI " }, \
|
{ CBMEM_ID_ACPI, "ACPI " }, \
|
||||||
|
{ CBMEM_ID_ACPI_BERT, "ACPI BERT " }, \
|
||||||
{ CBMEM_ID_ACPI_GNVS, "ACPI GNVS " }, \
|
{ CBMEM_ID_ACPI_GNVS, "ACPI GNVS " }, \
|
||||||
{ CBMEM_ID_ACPI_UCSI, "ACPI UCSI " }, \
|
{ CBMEM_ID_ACPI_UCSI, "ACPI UCSI " }, \
|
||||||
{ CBMEM_ID_AGESA_RUNTIME, "AGESA RSVD " }, \
|
{ CBMEM_ID_AGESA_RUNTIME, "AGESA RSVD " }, \
|
||||||
|
@ -87,6 +91,7 @@
|
||||||
{ CBMEM_ID_CB_EARLY_DRAM, "EARLY DRAM USAGE" }, \
|
{ CBMEM_ID_CB_EARLY_DRAM, "EARLY DRAM USAGE" }, \
|
||||||
{ CBMEM_ID_CONSOLE, "CONSOLE " }, \
|
{ CBMEM_ID_CONSOLE, "CONSOLE " }, \
|
||||||
{ CBMEM_ID_COVERAGE, "COVERAGE " }, \
|
{ CBMEM_ID_COVERAGE, "COVERAGE " }, \
|
||||||
|
{ CBMEM_ID_CPU_CRASHLOG, "CPU CRASHLOG"}, \
|
||||||
{ CBMEM_ID_EHCI_DEBUG, "USBDEBUG " }, \
|
{ CBMEM_ID_EHCI_DEBUG, "USBDEBUG " }, \
|
||||||
{ CBMEM_ID_ELOG, "ELOG " }, \
|
{ CBMEM_ID_ELOG, "ELOG " }, \
|
||||||
{ CBMEM_ID_FREESPACE, "FREE SPACE " }, \
|
{ CBMEM_ID_FREESPACE, "FREE SPACE " }, \
|
||||||
|
@ -101,6 +106,7 @@
|
||||||
{ CBMEM_ID_MMC_STATUS, "MMC STATUS " }, \
|
{ CBMEM_ID_MMC_STATUS, "MMC STATUS " }, \
|
||||||
{ CBMEM_ID_MPTABLE, "SMP TABLE " }, \
|
{ CBMEM_ID_MPTABLE, "SMP TABLE " }, \
|
||||||
{ CBMEM_ID_MRCDATA, "MRC DATA " }, \
|
{ CBMEM_ID_MRCDATA, "MRC DATA " }, \
|
||||||
|
{ CBMEM_ID_PMC_CRASHLOG, "PMC CRASHLOG"}, \
|
||||||
{ CBMEM_ID_VAR_MRCDATA, "VARMRC DATA" }, \
|
{ CBMEM_ID_VAR_MRCDATA, "VARMRC DATA" }, \
|
||||||
{ CBMEM_ID_MTC, "MTC " }, \
|
{ CBMEM_ID_MTC, "MTC " }, \
|
||||||
{ CBMEM_ID_PIRQ, "IRQ TABLE " }, \
|
{ CBMEM_ID_PIRQ, "IRQ TABLE " }, \
|
||||||
|
|
|
@ -1075,6 +1075,10 @@ unsigned long acpi_create_hest_error_source(acpi_hest_t *hest,
|
||||||
void acpi_create_lpit(acpi_lpit_t *lpit);
|
void acpi_create_lpit(acpi_lpit_t *lpit);
|
||||||
unsigned long acpi_create_lpi_desc_ncst(acpi_lpi_desc_ncst_t *lpi_desc, uint16_t uid);
|
unsigned long acpi_create_lpi_desc_ncst(acpi_lpi_desc_ncst_t *lpi_desc, uint16_t uid);
|
||||||
|
|
||||||
|
/* For crashlog. */
|
||||||
|
bool acpi_is_boot_error_src_present(void);
|
||||||
|
void acpi_soc_fill_bert(acpi_bert_t *bert, void **region, size_t *length);
|
||||||
|
|
||||||
/* For ACPI S3 support. */
|
/* For ACPI S3 support. */
|
||||||
void __noreturn acpi_resume(void *wake_vec);
|
void __noreturn acpi_resume(void *wake_vec);
|
||||||
void mainboard_suspend_resume(void);
|
void mainboard_suspend_resume(void);
|
||||||
|
|
|
@ -370,6 +370,19 @@ typedef struct cper_ia32x64_ctx_x64state {
|
||||||
u16 tr;
|
u16 tr;
|
||||||
} cper_ia32x64_ctx_x64state_t;
|
} cper_ia32x64_ctx_x64state_t;
|
||||||
|
|
||||||
|
#define FW_ERR_RECORD_ID_CRASHLOG_GUID \
|
||||||
|
GUID_INIT(0x8f87f311, 0xc998, 0x4d9e, \
|
||||||
|
0xa0, 0xc4, 0x60, 0x65, 0x51, 0x8c, 0x4f, 0x6d)
|
||||||
|
|
||||||
|
/* Firmware Error Record Reference, UEFI v2.8 sec N.2.10 */
|
||||||
|
typedef struct cper_fw_err_rec_section {
|
||||||
|
u8 record_type;
|
||||||
|
u8 revision;
|
||||||
|
u8 reserved[6];
|
||||||
|
u64 record_id;
|
||||||
|
guid_t record_guid;
|
||||||
|
} cper_fw_err_rec_section_t;
|
||||||
|
|
||||||
static inline cper_timestamp_t cper_timestamp(int precise)
|
static inline cper_timestamp_t cper_timestamp(int precise)
|
||||||
{
|
{
|
||||||
cper_timestamp_t ts;
|
cper_timestamp_t ts;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <cpu/x86/smm.h>
|
#include <cpu/x86/smm.h>
|
||||||
#include <intelblocks/fast_spi.h>
|
#include <intelblocks/fast_spi.h>
|
||||||
#include <intelblocks/systemagent.h>
|
#include <intelblocks/systemagent.h>
|
||||||
|
#include <arch/bert_storage.h>
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -49,12 +50,22 @@
|
||||||
* +---------------------------+ 0
|
* +---------------------------+ 0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define BERT_REGION_MAX_SIZE 0x10000
|
||||||
|
|
||||||
void smm_region(uintptr_t *start, size_t *size)
|
void smm_region(uintptr_t *start, size_t *size)
|
||||||
{
|
{
|
||||||
*start = sa_get_tseg_base();
|
*start = sa_get_tseg_base();
|
||||||
*size = sa_get_tseg_size();
|
*size = sa_get_tseg_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bert_reserved_region(void **start, size_t *size)
|
||||||
|
{
|
||||||
|
*start = cbmem_add(CBMEM_ID_ACPI_BERT, BERT_REGION_MAX_SIZE);
|
||||||
|
*size = BERT_REGION_MAX_SIZE;
|
||||||
|
|
||||||
|
printk(BIOS_DEBUG, "Reserving BERT start %lx, size %lx\n", (uintptr_t)*start, *size);
|
||||||
|
}
|
||||||
|
|
||||||
void fill_postcar_frame(struct postcar_frame *pcf)
|
void fill_postcar_frame(struct postcar_frame *pcf)
|
||||||
{
|
{
|
||||||
/* FSP does not seem to bother w.r.t. alignment when asked to place cbmem_top() */
|
/* FSP does not seem to bother w.r.t. alignment when asked to place cbmem_top() */
|
||||||
|
|
Loading…
Reference in New Issue