diff options
Diffstat (limited to 'src/soc/intel/xeon_sp/ras')
-rw-r--r-- | src/soc/intel/xeon_sp/ras/Kconfig | 20 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/ras/Makefile.inc | 3 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/ras/hest.c | 100 |
3 files changed, 123 insertions, 0 deletions
diff --git a/src/soc/intel/xeon_sp/ras/Kconfig b/src/soc/intel/xeon_sp/ras/Kconfig new file mode 100644 index 0000000000..79c599c2fb --- /dev/null +++ b/src/soc/intel/xeon_sp/ras/Kconfig @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +config SOC_ACPI_HEST + def_bool n + depends on HAVE_ACPI_TABLES + help + This variable provides control for ACPI hardware error source table (HEST) + +config SOC_RAS_ELOG + def_bool n + depends on SOC_ACPI_HEST + help + This variable provides enhanced error logging support used with HEST + +config ERROR_LOG_BUFFER_SIZE + hex + default 0x4000 + depends on SOC_RAS_ELOG + help + This variable allows a configurable error log based on system requirements diff --git a/src/soc/intel/xeon_sp/ras/Makefile.inc b/src/soc/intel/xeon_sp/ras/Makefile.inc new file mode 100644 index 0000000000..93c8705f94 --- /dev/null +++ b/src/soc/intel/xeon_sp/ras/Makefile.inc @@ -0,0 +1,3 @@ +## SPDX-License-Identifier: GPL-2.0-or-later + +ramstage-$(CONFIG_SOC_ACPI_HEST) += hest.c diff --git a/src/soc/intel/xeon_sp/ras/hest.c b/src/soc/intel/xeon_sp/ras/hest.c new file mode 100644 index 0000000000..6164edfe19 --- /dev/null +++ b/src/soc/intel/xeon_sp/ras/hest.c @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <soc/acpi.h> +#include <acpi/acpi_gnvs.h> +#include <cbmem.h> +#include <console/console.h> +#include <soc/hest.h> +#include <intelblocks/nvs.h> + +static u64 hest_get_elog_addr(void) +{ + /* The elog address comes from reserved memory */ + struct global_nvs *gnvs; + gnvs = acpi_get_gnvs(); + if (!gnvs) { + printk(BIOS_ERR, "Unable to get gnvs\n"); + return 0; + } + + /* Runtime logging address */ + printk(BIOS_DEBUG, "\t status blk start addr = %llx\n", gnvs->hest_log_addr); + printk(BIOS_DEBUG, "\t size = %x\n", CONFIG_ERROR_LOG_BUFFER_SIZE); + return gnvs->hest_log_addr; +} + +static u32 acpi_hest_add_ghes(void *current) +{ + ghes_record_t *rec = (ghes_record_t *)current; + u32 size = sizeof(ghes_record_t); + + /* Fill GHES error source descriptor */ + memset(rec, 0, size); + rec->esd.type = HEST_GHES_DESC_TYPE; + rec->esd.source_id = 0; /* 0 for MCE check exception source */ + rec->esd.enabled = 1; + rec->esd.related_src_id = 0xffff; + rec->esd.prealloc_erecords = 1; + rec->esd.max_section_per_record = 0xf; + rec->max_raw_data_length = GHES_MAX_RAW_DATA_LENGTH; + + /* Add error_status_address */ + rec->sts_addr.space_id = 0; + rec->sts_addr.bit_width = 0x40; + rec->sts_addr.bit_offset = 0; + rec->sts_addr.access_size = QWORD_ACCESS; + + /* Add notification structure */ + rec->notify.type = NOTIFY_TYPE_SCI; + rec->notify.length = sizeof(acpi_hest_hen_t); + rec->err_sts_blk_len = GHEST_ERROR_STATUS_BLOCK_LENGTH; + + /* error status block entries start address */ + if (CONFIG(SOC_ACPI_HEST)) + rec->sts_addr.addr = hest_get_elog_addr(); + + return size; +} + +static unsigned long acpi_fill_hest(acpi_hest_t *hest) +{ + acpi_header_t *header = &(hest->header); + void *current; + current = (void *)(hest); + void *next = current; + next = hest + 1; + next += acpi_hest_add_ghes(next); + hest->error_source_count += 1; + header->length += next - current; + return header->length; +} + +unsigned long hest_create(unsigned long current, struct acpi_rsdp *rsdp) +{ + struct global_nvs *gnvs; + acpi_hest_t *hest; + + /* Reserve memory for Enhanced error logging */ + void *mem = cbmem_add(CMBMEM_ID_ACPI_HEST, CONFIG_ERROR_LOG_BUFFER_SIZE); + if (!mem) { + printk(BIOS_ERR, "Unable to allocate HEST memory\n"); + return current; + } + + printk(BIOS_DEBUG, "HEST memory created: %p\n", mem); + gnvs = acpi_get_gnvs(); + if (!gnvs) { + printk(BIOS_ERR, "Unable to get gnvs\n"); + return current; + } + gnvs->hest_log_addr = (uintptr_t)mem; + printk(BIOS_DEBUG, "elog_addr: %llx, size:%x\n", gnvs->hest_log_addr, + CONFIG_ERROR_LOG_BUFFER_SIZE); + + current = ALIGN(current, 8); + hest = (acpi_hest_t *)current; + acpi_write_hest(hest, acpi_fill_hest); + acpi_add_table(rsdp, (void *)current); + current += hest->header.length; + return current; +} |