[coreboot-gerrit] Change in coreboot[master]: NOT_FOR_MERGE: Add code to dump BERT region contents

Marshall Dawson (Code Review) gerrit at coreboot.org
Tue Sep 4 22:07:06 CEST 2018


Marshall Dawson has uploaded this change for review. ( https://review.coreboot.org/28480


Change subject: NOT_FOR_MERGE: Add code to dump BERT region contents
......................................................................

NOT_FOR_MERGE: Add code to dump BERT region contents

Has been useful for development and debug.

Change-Id: I8ecf920499a662db34a332e9df05e4ee2383b6d4
Signed-off-by: Marshall Dawson <marshalldawson3rd at gmail.com>
---
M src/soc/amd/stoneyridge/Makefile.inc
A src/soc/amd/stoneyridge/bertdump.c
M src/soc/amd/stoneyridge/finalize.c
3 files changed, 474 insertions(+), 0 deletions(-)



  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/80/28480/1

diff --git a/src/soc/amd/stoneyridge/Makefile.inc b/src/soc/amd/stoneyridge/Makefile.inc
index a8db2c2..45e8aa3 100644
--- a/src/soc/amd/stoneyridge/Makefile.inc
+++ b/src/soc/amd/stoneyridge/Makefile.inc
@@ -37,6 +37,8 @@
 subdirs-y += ../../../cpu/x86/pae
 subdirs-y += ../../../cpu/x86/smm
 
+ramstage-y += bertdump.c
+
 bootblock-$(CONFIG_STONEYRIDGE_UART) += uart.c
 bootblock-y += BiosCallOuts.c
 bootblock-y += bootblock/bootblock.c
diff --git a/src/soc/amd/stoneyridge/bertdump.c b/src/soc/amd/stoneyridge/bertdump.c
new file mode 100644
index 0000000..187ca24
--- /dev/null
+++ b/src/soc/amd/stoneyridge/bertdump.c
@@ -0,0 +1,465 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2018 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/acpi.h>
+#include <cpu/amd/amdfam15.h>
+#include <soc/cpu.h>
+#include <console/console.h>
+#include <lib.h>
+#include <commonlib/helpers.h>
+#include <arch/bert_storage.h>
+#include <cper.h>
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+//
+//
+// Table checker code
+//
+//
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+static void print_guid(guid_t guid)
+{
+	u8 *g = (u8 *)&guid;
+	printk(0, "{{0x%02x%02x%02x%02x, 0x%02x%02x, 0x%02x%02x, {0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x}}\n",
+			g[3], g[2], g[1], g[0],
+			g[5], g[4],
+			g[7], g[6],
+			g[8], g[9], g[10], g[11], g[12], g[13], g[14], g[15]);
+}
+
+// Status and Error Data structures have idential Error Severity definitions
+static const char *acpi_severity[] = {
+	"Recoverable",
+	"Fatal",
+	"Corrected",
+	"None",
+	"you did something wrong"
+};
+
+static const char *acpi_sev(u32 sev)
+{
+	if (sev > 3)
+		return acpi_severity[4];
+	return acpi_severity[sev];
+}
+
+static void x86_chkprint_with_valid(u64 check, u64 valid)
+{
+
+	if (check & 0xffff & ~valid) /* validation bits are 15:0 */
+		printk(0, "               e   * Invalid bits %llx\n", check & ~valid);
+	if (valid & X86_PROC_CHK_XACT_MASK)
+		printk(0, "               e   Transaction Type    = %llx %s\n", check & X86_PROC_CHK_XACT_MASK >> X86_PROC_CHK_XACT_SH,
+									check & X86_PROC_CHK_XACT_MASK ? "V" : "");
+	if (valid & X86_PROC_CHK_OPERATION_VALID)
+		printk(0, "               e   Operation           = %llx %s\n", check & X86_PROC_CHK_OPER_MASK >> X86_PROC_CHK_OPER_SH,
+									check & X86_PROC_CHK_OPERATION_VALID ? "V" : "");
+	if (valid & X86_PROC_CHK_LEVEL_VALID)
+		printk(0, "               e   Cache Level         = %llx %s\n", check & X86_PROC_CHK_LEVEL_MASK >> X86_PROC_CHK_LEVEL_SH,
+									check & X86_PROC_CHK_LEVEL_VALID ? "V" : "");
+	if (valid & X86_PROC_CHK_CONTEXT_CORPT_VALID)
+		printk(0, "               e   Context Corrupt     = %x %s\n", !!(check & X86_PROC_CHK_CTX_CORRUPT),
+									check & X86_PROC_CHK_CONTEXT_CORPT_VALID ? "V" : "");
+	if (valid & X86_PROC_CHK_UNCORRECTED_VALID)
+		printk(0, "               e   Uncorrected         = %x %s\n", !!(check & X86_PROC_CHK_UNCORRECTED),
+									check & X86_PROC_CHK_UNCORRECTED_VALID ? "V" : "");
+	if (valid & X86_PROC_CHK_PRECISE_IP_VALID)
+		printk(0, "               e   Precise IP          = %x %s\n", !!(check & X86_PROC_CHK_PRECISE_IP),
+									check & X86_PROC_CHK_PRECISE_IP_VALID ? "V" : "");
+	if (valid & X86_PROC_CHK_RESTARTABLE_VALID)
+		printk(0, "               e   Restartable IP      = %x %s\n", !!(check & X86_PROC_CHK_RESTARTABLE_IP),
+									check & X86_PROC_CHK_RESTARTABLE_VALID ? "V" : "");
+	if (valid & X86_PROC_CHK_OVERFLOW_VALID)
+		printk(0, "               e   Overflow            = %x %s\n", !!(check & X86_PROC_CHK_OVERFLOW),
+									check & X86_PROC_CHK_OVERFLOW_VALID ? "V" : "");
+	if (valid & X86_PROC_CHK_PART_TYPE_VALID)
+		printk(0, "               e   Participation Type  = %llx %s\n", check & X86_PROC_CHK_PARTIC_MASK >> X86_PROC_CHK_PARTIC_SH,
+									check & X86_PROC_CHK_PART_TYPE_VALID ? "V" : "");
+	if (valid & X86_PROC_CHK_TIMEOUT)
+		printk(0, "               e   Time Out            = %x %s\n", !!(check & X86_PROC_CHK_OVERFLOW),
+									check & X86_PROC_CHK_TIMEOUT ? "V" : "");
+	if (valid & X86_PROC_CHK_ADDR_SPACE_VALID)
+		printk(0, "               e   Address Space       = %llx %s\n", check & X86_PROC_CHK_PARTIC_MASK >> X86_PROC_CHK_PARTIC_SH,
+									check & X86_PROC_CHK_ADDR_SPACE_VALID ? "V" : "");
+}
+
+static void x86_mschkprint_with_valid(u64 check, u64 valid)
+{
+	if (check & 0xffff & ~valid) /* validation bits are 15:0 */
+		printk(0, "               e   * Invalid bits %llx\n", check & ~valid);
+	if (valid & X86_PROC_CHK_XACT_MASK)
+		printk(0, "               e   Transaction Type    = %llx %s\n", check & X86_PROC_MS_CHK_XACT_MASK >> X86_PROC_MS_CHK_XACT_SH,
+									check & X86_PROC_CHK_XACT_MASK ? "V" : "");
+	if (valid & X86_PROC_CHK_UNCORRECTED_VALID)
+		printk(0, "               e   Uncorrected         = %x %s\n", !!(check & X86_PROC_MS_CHK_UNCORRECTED),
+									check & X86_PROC_CHK_UNCORRECTED_VALID ? "V" : "");
+	if (valid & X86_PROC_CHK_PRECISE_IP_VALID)
+		printk(0, "               e   Precise IP          = %x %s\n", !!(check & X86_PROC_MS_CHK_PRECISE_IP),
+									check & X86_PROC_CHK_PRECISE_IP_VALID ? "V" : "");
+	if (valid & X86_PROC_CHK_RESTARTABLE_VALID)
+		printk(0, "               e   Restartable IP      = %x %s\n", !!(check & X86_PROC_MS_CHK_RESTARTABLE_IP),
+									check & X86_PROC_CHK_RESTARTABLE_VALID ? "V" : "");
+	if (valid & X86_PROC_CHK_OVERFLOW_VALID)
+		printk(0, "               e   Overflow            = %x %s\n", !!(check & X86_PROC_MS_CHK_OVERFLOW),
+									check & X86_PROC_CHK_OVERFLOW_VALID ? "V" : "");
+}
+
+static const char *check_guid_names[] = {
+	"CACHE_CHK_ERROR_GUID",
+	"TLB_CHK_ERROR_GUID",
+	"BUS_CHK_ERROR_GUID",
+	"MS_CHK_ERROR_GUID",
+	"you did something wrong"
+};
+
+static const char *check_guid_name(guid_t type)
+{
+
+	if (!guidcmp(&type, &X86_PROCESSOR_CACHE_CHK_ERROR_GUID))
+		return check_guid_names[0];
+	if (!guidcmp(&type, &X86_PROCESSOR_TLB_CHK_ERROR_GUID))
+		return check_guid_names[1];
+	if (!guidcmp(&type, &X86_PROCESSOR_BUS_CHK_ERROR_GUID))
+		return check_guid_names[2];
+	if (!guidcmp(&type, &X86_PROCESSOR_MS_CHK_ERROR_GUID))
+		return check_guid_names[3];
+
+	return check_guid_names[4];
+}
+
+static size_t parse_x86_error_info(cper_ia32x64_proc_error_info_t *err)
+{
+	printk(0, "               ___ CPER IA32/x64 Processor Error (Check) Information @0x%p - 0x%p (size 0x%zx) ___\n", err, err + 1, sizeof(*err));
+	printk(0, "               e   Structure Type GUID = %s\n", check_guid_name(err->type));
+	printk(0, "               e   Structure Type      = ");
+						print_guid(err->type);
+	printk(0, "               e   Validation Bits     = %llx\n", err->validation);
+	if (!guidcmp(&err->type, &X86_PROCESSOR_CACHE_CHK_ERROR_GUID))
+		x86_chkprint_with_valid(err->check_info, X86_PROC_CHK_XACT_TYPE_VALID | X86_PROC_CHK_OPERATION_VALID
+						| X86_PROC_CHK_LEVEL_VALID | X86_PROC_CHK_CONTEXT_CORPT_VALID
+						| X86_PROC_CHK_UNCORRECTED_VALID | X86_PROC_CHK_PRECISE_IP_VALID
+						| X86_PROC_CHK_RESTARTABLE_VALID | X86_PROC_CHK_OVERFLOW_VALID);
+	else if (!guidcmp(&err->type, &X86_PROCESSOR_TLB_CHK_ERROR_GUID))
+		x86_chkprint_with_valid(err->check_info, X86_PROC_CHK_XACT_TYPE_VALID | X86_PROC_CHK_OPERATION_VALID
+						| X86_PROC_CHK_LEVEL_VALID | X86_PROC_CHK_CONTEXT_CORPT_VALID
+						| X86_PROC_CHK_UNCORRECTED_VALID | X86_PROC_CHK_PRECISE_IP_VALID
+						| X86_PROC_CHK_RESTARTABLE_VALID | X86_PROC_CHK_OVERFLOW_VALID);
+	else if (!guidcmp(&err->type, &X86_PROCESSOR_BUS_CHK_ERROR_GUID))
+		x86_chkprint_with_valid(err->check_info, X86_PROC_CHK_XACT_TYPE_VALID | X86_PROC_CHK_OPERATION_VALID
+						| X86_PROC_CHK_LEVEL_VALID | X86_PROC_CHK_CONTEXT_CORPT_VALID
+						| X86_PROC_CHK_UNCORRECTED_VALID | X86_PROC_CHK_PRECISE_IP_VALID
+						| X86_PROC_CHK_RESTARTABLE_VALID | X86_PROC_CHK_OVERFLOW_VALID
+						| X86_PROC_CHK_PART_TYPE_VALID | X86_PROC_CHK_TIMEOUT_VALID
+						| X86_PROC_CHK_ADDR_SPACE_VALID);
+	else if (!guidcmp(&err->type, &X86_PROCESSOR_MS_CHK_ERROR_GUID))
+		x86_mschkprint_with_valid(err->check_info, X86_PROC_CHK_XACT_TYPE_VALID | X86_PROC_CHK_OPERATION_VALID
+						| X86_PROC_CHK_LEVEL_VALID | X86_PROC_CHK_CONTEXT_CORPT_VALID
+						| X86_PROC_CHK_UNCORRECTED_VALID | X86_PROC_CHK_PRECISE_IP_VALID);
+	else
+		printk(0, "               e   INVALID CHECK TYPE!\n");
+	printk(0, "               eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n");
+	return sizeof(*err);
+}
+
+static const char *context_names[] = {
+	"Unclassified data",
+	"MSR Registers",
+	"32-bit mode execution registers",
+	"64-bit mode execution registers",
+	"FXSAVE context",
+	"32-bit mode debug registers",
+	"64-bit mode debug registers",
+	"Memory mapped registers",
+	"you did something wrong"
+};
+
+static const char *context_name(int type)
+{
+	switch (type) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+		return context_names[type];
+	default:
+		return context_names[8];
+	}
+}
+
+static size_t parse_x86_context_info(cper_ia32x64_context_t *ctx)
+{
+	printk(0, "               ___ CPER IA32/x64 Processor Context Information @0x%p - 0x%p (size 0x%zx) ___\n", ctx,
+							(u8 *)ctx + ALIGN_UP(sizeof(*ctx) + ctx->array_size, 16),
+							ALIGN_UP(sizeof(*ctx) + ctx->array_size, 16));
+	printk(0, "               t   Context Type     = %x %s\n", ctx->type, context_name(ctx->type));
+	printk(0, "               t   Array Size       = %x\n", ctx->array_size);
+	printk(0, "               t   MSR Address      = %x\n", ctx->msr_addr);
+	printk(0, "               t   MM Address       = %llx\n", ctx->mmap_addr);
+
+	int i;
+	u64 *array = (u64 *)(ctx + 1);
+	printk(0, "               t   Data Array\n");
+
+	int array_size = ctx->array_size / sizeof(u64);
+	for (i = 0 ; i < array_size ; i++)
+		printk(0, "               t                      %08x_%08x\n", (u32)(*(array + i) >> 32), (u32)*(array + i));
+
+	printk(0, "               ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt\n");
+	return ALIGN_UP(sizeof(*ctx) + ctx->array_size, 16);
+}
+
+static size_t parse_cper_structure_x86(cper_ia32x64_proc_error_section_t *ia32)
+{
+	int i;
+	int errs = (ia32->validation & I32X64SEC_VALID_ERRNUM_MASK) >> I32X64SEC_VALID_ERRNUM_SH;
+	int ctxs = (ia32->validation & I32X64SEC_VALID_CTXNUM_MASK) >> I32X64SEC_VALID_CTXNUM_SH;
+
+	printk(0, "           ___ CPER IA32/x64 Processor Error @0x%p sizeof(proc error section struct) is 0x%zx/%zd) ___\n", ia32, sizeof(*ia32), sizeof(*ia32));
+	printk(0, "           x   Validation Bits      = %llx\n", ia32->validation);
+	printk(0, "           x     errors             = %d\n", errs);
+	printk(0, "           x     contexts           = %d\n", ctxs);
+	printk(0, "           x   Processor APIC ID    = %llx %s\n",   ia32->apicid, ia32->validation & I32X64SEC_VALID_LAPIC ? "V" : "");
+	printk(0, "           x   Processor CPUID      = EAX = %x %s\n", (u32)ia32->cpuid[0], ia32->validation & I32X64SEC_VALID_CPUID ? "V" : "");
+	printk(0, "           x                          EBX = %x\n", (u32)ia32->cpuid[1]);
+	printk(0, "           x                          ECX = %x\n", (u32)ia32->cpuid[2]);
+	printk(0, "           x                          EDX = %x\n", (u32)ia32->cpuid[3]);
+
+	uintptr_t adder = sizeof(*ia32);
+	for (i = 0 ; i < errs ; i++)
+		adder += parse_x86_error_info((cper_ia32x64_proc_error_info_t *)((u8 *)ia32 + adder));
+
+	for (i = 0 ; i < ctxs ; i++)
+		adder += parse_x86_context_info((cper_ia32x64_context_t *)((u8 *)ia32 + adder));
+
+	return adder;
+}
+
+static size_t parse_cper_structure_generic(cper_proc_generic_error_section_t *gen)
+{
+	printk(0, "           ___ CPER Generic Processor Error @0x%p sizeof(generic error struct) is 0x%zx/%zd\n", gen, sizeof(*gen), sizeof(*gen));
+	printk(0, "           c   Validation Bits      = %llx\n", gen->validation);
+	printk(0, "           c   Processor Type       = %x %s\n",   gen->proc_type, gen->validation & GENPROC_VALID_PROC_TYPE ? "V" : "");
+	printk(0, "           c   Processor ISA        = %x %s\n",   gen->proc_isa, gen->validation & GENPROC_VALID_PROC_ISA ? "V" : "");
+	printk(0, "           c   Processor Error Type = %x %s\n",   gen->error_type, gen->validation & GENPROC_VALID_PROC_ERR_TYPE ? "V" : "");
+	printk(0, "           c   Operation            = %x %s\n",   gen->operation, gen->validation & GENPROC_VALID_OPERATION ? "V" : "");
+	printk(0, "           c   Flags                = %x %s\n",   gen->flags, gen->validation & GENPROC_VALID_FLAGS ? "V" : "");
+	printk(0, "           c   Level                = %x %s\n",   gen->level, gen->validation & GENPROC_VALID_LEVEL ? "V" : "");
+	printk(0, "           c   CPU Version Info     = %llx %s\n", gen->cpu_version, gen->validation & GENPROC_VALID_CPU_VERSION ? "V" : "");
+	printk(0, "           c   CPU Brand String     = %s %s\n",   gen->cpu_brand_string, gen->validation & GENPROC_VALID_CPU_BRAND ? "V" : "");
+	printk(0, "           c   Processor ID         = %llx %s\n", gen->proc_id, gen->validation & GENPROC_VALID_CPU_ID ? "V" : "");
+	printk(0, "           c   Target Address       = %llx %s\n", gen->target_addr, gen->validation & GENPROC_VALID_TGT_ADDR ? "V" : "");
+	printk(0, "           c   Requestor Identifier = %llx %s\n", gen->requestor_id, gen->validation & GENPROC_VALID_REQR_ID ? "V" : "");
+	printk(0, "           c   Responder Identifier = %llx %s\n", gen->responder_id, gen->validation & GENPROC_VALID_RSPR_ID ? "V" : "");
+	printk(0, "           c   Instruction IP       = %llx %s\n", gen->instruction_ip, gen->validation & GENPROC_VALID_INSTR_IP ? "V" : "");
+	printk(0, "           cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\n");
+
+	return sizeof(*gen);
+}
+
+static size_t parse_cper_structure(void *st, guid_t type)
+{
+	if (!guidcmp(&type, &CPER_SEC_PROC_GENERIC_GUID))
+		return parse_cper_structure_generic(st);
+	else if (!guidcmp(&type, &CPER_SEC_PROC_IA32X64_GUID))
+		return parse_cper_structure_x86(st);
+	// else if...
+
+	printk(0, "Error, you asked me to parse type for ");
+	print_guid(type);
+	return 0;
+}
+
+static size_t entry382_size(void *e382)
+{
+	acpi_hest_generic_data_t *entry = (acpi_hest_generic_data_t *)e382;
+
+	if (entry->revision == HEST_GENERIC_ENTRY_V300)
+		return sizeof(acpi_hest_generic_data_v300_t) + entry->data_length;
+	else
+		return sizeof(acpi_hest_generic_data_t) + entry->data_length;
+}
+
+static const char *guids382[] = {
+	"PROCESSOR_GENERIC",
+	"PROCESSOR_SPECIFIC_X86_GUID",
+	"PROCESSOR_SPECIFIC_ARM_GUID",
+	"PLATFORM_MEMORY_GUID",
+	"PLATFORM_MEMORY2_GUID",
+	"PCIE_GUID",
+	"FW_ERROR_RECORD_GUID",
+	"PCI_PCIX_BUS_GUID",
+	"PCI_DEVICE_GUID",
+	"DMAR_GENERIC_GUID",
+	"DIRECTED_IO_DMAR_GUID",
+	"IOMMU_DMAR_GUID",
+	"you did something wrong"
+};
+
+static const char *guid382_name(guid_t guid)
+{
+	if(!guidcmp(&guid, &CPER_SEC_PROC_GENERIC_GUID))
+		return guids382[0];
+	if(!guidcmp(&guid, &CPER_SEC_PROC_IA32X64_GUID))
+		return guids382[1];
+	if(!guidcmp(&guid, &CPER_SEC_PROC_ARM_GUID))
+		return guids382[2];
+	if(!guidcmp(&guid, &CPER_SEC_PLATFORM_MEM_GUID))
+		return guids382[3];
+	if(!guidcmp(&guid, &CPER_SEC_PLATFORM_MEM2_GUID))
+		return guids382[4];
+	if(!guidcmp(&guid, &CPER_SEC_PCIE_GUID))
+		return guids382[5];
+	if(!guidcmp(&guid, &CPER_SEC_FW_ERR_REC_REF_GUID))
+		return guids382[6];
+	if(!guidcmp(&guid, &CPER_SEC_PCI_X_BUS_GUID))
+		return guids382[7];
+	if(!guidcmp(&guid, &CPER_SEC_PCI_DEV_GUID))
+		return guids382[8];
+	if(!guidcmp(&guid, &CPER_SEC_DMAR_GENERIC_GUID))
+		return guids382[9];
+	if(!guidcmp(&guid, &CPER_SEC_DMAR_VT_GUID))
+		return guids382[10];
+	if(!guidcmp(&guid, &CPER_SEC_DMAR_IOMMU_GUID))
+		return guids382[11];
+	return guids382[12];
+}
+
+static void parse_382_data(acpi_hest_generic_data_v300_t *entry, size_t size)
+{
+	size_t offset = 0;
+
+	while (size > offset) {
+		printk(0, "      ___ 382 found @0x%p sizeof(%s) = 0x%zx/%zd ___\n", entry, entry->revision == 0x300 ? "v3" : "old-type",
+				entry->revision == 0x300 ? sizeof(acpi_hest_generic_data_v300_t) : sizeof(acpi_hest_generic_data_t),
+				entry->revision == 0x300 ? sizeof(acpi_hest_generic_data_v300_t) : sizeof(acpi_hest_generic_data_t));
+		printk(0, "      3   Section Type GUID = %s\n", guid382_name(entry->section_type));
+		printk(0, "      3   Section Type      = ");
+						print_guid(entry->section_type);
+		printk(0, "      3   Severity          = %x: %s\n", entry->error_severity, acpi_sev(entry->error_severity));
+		printk(0, "      3   Revision          = %x\n", entry->revision);
+		printk(0, "      3   Validation        = %x\n", entry->validation_bits);
+		printk(0, "      3   Flags             = %x\n", entry->flags);
+		printk(0, "      3   Error Data Length = %x\n", entry->data_length);
+		printk(0, "      3   FRU ID            = <todo> %s\n", entry->validation_bits & ACPI_GENERROR_VALID_FRUID ? "V" : "");
+		printk(0, "      3   FRU text          = <todo> %s\n", entry->validation_bits & ACPI_GENERROR_VALID_FRUID_TEXT ? "V" : "");
+		if (entry->revision == HEST_GENERIC_ENTRY_V300) {
+			/* I can cheat on x300 because I know only diff is timestamp */
+			printk(0, "      3   Timestamp         = %02x, %02x%02x/%02x/%02x %02x:%02x:%02x %s\n",
+				entry->timestamp.precise,
+				entry->timestamp.century, entry->timestamp.year,
+				entry->timestamp.month, entry->timestamp.day,
+				entry->timestamp.hour, entry->timestamp.min, entry->timestamp.sec,
+				entry->validation_bits & ACPI_GENERROR_VALID_TIMESTAMP ? "V" : "");
+		}
+		printk(0, "      333333333333333333333333333333333333333333333333333333333\n");
+
+		/* each table-382 entry should contain 0 or 1 cper structure at its end */
+		if (entry->data_length) {
+			if (entry->revision == HEST_GENERIC_ENTRY_V300)
+				parse_cper_structure((void *)(entry + 1), entry->section_type);
+			else /* maybe I did this right? */
+				parse_cper_structure((void *)((u8 *)entry + sizeof(acpi_hest_generic_data_t)), entry->section_type);
+		}
+
+		offset += entry382_size(entry);
+		entry = (acpi_hest_generic_data_v300_t *)((u8 *)entry + entry382_size(entry));
+	}
+}
+
+static size_t bert_entry_size(acpi_generic_error_status_t *bert_data)
+{
+	size_t size = sizeof(*bert_data);
+
+	if (bert_data->raw_data_length)
+		size += bert_data->raw_data_offset + bert_data->data_length;
+	else
+		size += bert_data->data_length;
+
+	return size;
+}
+
+static acpi_hest_generic_data_v300_t *ptr382_from_bert_entry(acpi_generic_error_status_t *bert_data)
+{
+	if (bert_data->data_length)
+		return (acpi_hest_generic_data_v300_t *)((u8 *)bert_data + sizeof(*bert_data));
+	else
+		return (acpi_hest_generic_data_v300_t *)NULL;
+}
+
+static u8 *ptr_raw_from_bert_entry(acpi_generic_error_status_t *bert_data)
+{
+	if (bert_data->raw_data_length)
+		return (u8 *)bert_data + bert_data->raw_data_offset;
+	else
+		return (u8 *)NULL;
+}
+
+void parse_bert_region(void);
+void parse_bert_region(void)
+{
+	acpi_generic_error_status_t *bert_base;
+	size_t size;
+	bert_errors_region((void **)&bert_base, &size);
+
+	acpi_generic_error_status_t *bert_data = bert_base;
+	size_t offset = 0;
+	acpi_hest_generic_data_v300_t *gen382;
+	u8 *raw;
+	int entries;
+
+	printk(0, "***** BERT storage at 0x%p - 0x%p (%zd) *****\n", bert_base, (u8 *)bert_base + size, size);
+
+	while(offset < size) {
+		entries = (bert_data->block_status & GENERIC_ERR_STS_ENTRY_COUNT_MASK) >> GENERIC_ERR_STS_ENTRY_COUNT_SHIFT;
+		printk(0, " ___ BERT entry @0x%p - (sizeof(status)=0x%zx/%zd) ___\n", bert_data, sizeof(*bert_data), sizeof(*bert_data));
+		printk(0, " b   Block Status    = %x\n", bert_data->block_status);
+		printk(0, " b     severity      =%s%s%s%s\n",
+					bert_data->block_status & BIT(0) ? " uncorrectable" : "",
+					bert_data->block_status & BIT(1) ? " correctable" : "",
+					bert_data->block_status & BIT(2) ? " mult-uncorrected" : "",
+					bert_data->block_status & BIT(3) ? " mult-corrected" : "");
+		printk(0, " b     count         = %x\n", entries);
+		printk(0, " b   Raw Data Offset = %x\n", bert_data->raw_data_offset);
+		printk(0, " b   Raw Data Length = %x\n", bert_data->raw_data_length);
+		printk(0, " b   Data Length     = %x\n", bert_data->data_length);
+		printk(0, " b   Error Severity  = %x: %s\n", bert_data->error_severity, acpi_sev(bert_data->error_severity));
+		if (bert_data->data_length && bert_data->data_length < sizeof(acpi_hest_generic_data_v300_t))
+			printk(0, " b   ERROR: data length not large enough: %d < %zd\n",
+					bert_data->data_length, sizeof(acpi_hest_generic_data_v300_t));
+		if (bert_data->raw_data_length && bert_data->raw_data_offset < sizeof(*bert_data) + bert_data->data_length)
+			printk(0, " b   ERROR: raw data offset is bad: %d < %zd + %d\n",
+					bert_data->raw_data_offset, sizeof(*bert_data), bert_data->data_length);
+		printk(0, " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n");
+
+		/* can have zero or more data entries, of type 382 and/or of raw */
+		gen382 = ptr382_from_bert_entry(bert_data); // todo: this only handles a single 382 entry
+		if (gen382)
+			parse_382_data(gen382, bert_data->data_length);
+
+		raw = ptr_raw_from_bert_entry(bert_data);
+		if (raw)
+			printk(0, "todo: dump raw data\n");
+
+		offset += bert_entry_size(bert_data);
+		bert_data = (acpi_generic_error_status_t *)((u8 *)bert_data + offset);
+	}
+}
diff --git a/src/soc/amd/stoneyridge/finalize.c b/src/soc/amd/stoneyridge/finalize.c
index 21d203c..25cfee9 100644
--- a/src/soc/amd/stoneyridge/finalize.c
+++ b/src/soc/amd/stoneyridge/finalize.c
@@ -49,10 +49,17 @@
 		printk(BIOS_WARNING, "Failed to finalize all cores\n");
 }
 
+void parse_bert_region(void); // todo: remove me
+
 static void soc_finalize(void *unused)
 {
 	finalize_cores();
 
+	/* In the event the region got misplaced and SMM_LOCKed, this is a
+	 * good place to see that.
+	 */
+	parse_bert_region();
+
 	post_code(POST_OS_BOOT);
 }
 

-- 
To view, visit https://review.coreboot.org/28480
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I8ecf920499a662db34a332e9df05e4ee2383b6d4
Gerrit-Change-Number: 28480
Gerrit-PatchSet: 1
Gerrit-Owner: Marshall Dawson <marshalldawson3rd at gmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20180904/53873a2d/attachment-0001.html>


More information about the coreboot-gerrit mailing list