<p>Marshall Dawson has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/28477">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">amd/stoneyridge: Construct BERT region from machine check<br><br>Add functions to build a Boot Error Record Table region based on<br>settings found in the MCA registers.<br><br>Two entries are reported for each error due to the nature of the ACPI<br>driver.  The first is a Generic Processor Error, which the OS recognizes<br>and parses.  Generic errors cannot convey much error description or<br>processor context.  Therefore an IA32/X64 Processor Error is also added,<br>which allows reporting the values found in the MCA MSR registers.<br><br>Follow-on work could decode the MC errors more precisely, and better<br>completing the Generic Error and the Check structure.  The current<br>level of support is sufficient to identify a (i.e., human readable)<br>problem in dmesg, and provides adequate context information for<br>analysis.<br><br>BUG=b:65446699<br>TEST=inspect BERT region, and dmesg, on full patch stack.  Use test<br>     data plus a failing Grunt system.<br><br>Change-Id: I4d4ce29ddefa22aa29e6d3184f1adeaea1d5f837<br>Signed-off-by: Marshall Dawson <marshalldawson3rd@gmail.com><br>---<br>M src/soc/amd/stoneyridge/mca.c<br>1 file changed, 135 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/77/28477/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/soc/amd/stoneyridge/mca.c b/src/soc/amd/stoneyridge/mca.c</span><br><span>index bcaa927..81d95fb 100644</span><br><span>--- a/src/soc/amd/stoneyridge/mca.c</span><br><span>+++ b/src/soc/amd/stoneyridge/mca.c</span><br><span>@@ -19,8 +19,11 @@</span><br><span> #include <soc/cpu.h></span><br><span> #include <soc/northbridge.h></span><br><span> #include <console/console.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <arch/bert_storage.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <cper.h></span><br><span> </span><br><span> struct mca_bank {</span><br><span style="color: hsl(120, 100%, 40%);">+     int bank;</span><br><span>    msr_t ctl;</span><br><span>   msr_t sts;</span><br><span>   msr_t addr;</span><br><span>@@ -28,6 +31,135 @@</span><br><span>    msr_t cmask;</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static inline size_t mca_report_size_reqd(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    size_t size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        size = sizeof(acpi_generic_error_status_t);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ size += sizeof(acpi_hest_generic_data_v300_t);</span><br><span style="color: hsl(120, 100%, 40%);">+        size += sizeof(cper_proc_generic_error_section_t);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  size += sizeof(acpi_hest_generic_data_v300_t);</span><br><span style="color: hsl(120, 100%, 40%);">+        size += sizeof(cper_ia32x64_proc_error_section_t);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Check Error */</span><br><span style="color: hsl(120, 100%, 40%);">+     size += 1 * cper_ia32x64_check_sz();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Context of MCG_CAP, MCG_STAT, MCG_CTL */</span><br><span style="color: hsl(120, 100%, 40%);">+   size += cper_ia32x64_ctx_sz_bytype(CPER_IA32X64_CTX_MSR, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Context of MCi_CTL, MCi_STATUS, MCi_ADDR, MCi_MISC */</span><br><span style="color: hsl(120, 100%, 40%);">+      size += cper_ia32x64_ctx_sz_bytype(CPER_IA32X64_CTX_MSR, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Context of CTL_MASK */</span><br><span style="color: hsl(120, 100%, 40%);">+     size += cper_ia32x64_ctx_sz_bytype(CPER_IA32X64_CTX_MSR, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return size;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static enum cper_x86_check_type error_to_chktype(struct mca_bank *mci)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  int error = mca_err_type(mci->sts);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (error == MCA_ERRTYPE_BUS)</span><br><span style="color: hsl(120, 100%, 40%);">+         return X86_PROCESSOR_BUS_CHK;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (error == MCA_ERRTYPE_INT)</span><br><span style="color: hsl(120, 100%, 40%);">+         return X86_PROCESSOR_MS_CHK;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (error == MCA_ERRTYPE_MEM)</span><br><span style="color: hsl(120, 100%, 40%);">+         return X86_PROCESSOR_CACHE_CHK;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (error == MCA_ERRTYPE_TLB)</span><br><span style="color: hsl(120, 100%, 40%);">+         return X86_PROCESSOR_TLB_CHK;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return X86_PROCESSOR_MS_CHK; /* MCA_ERRTYPE_INT and unrecognized */</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Fill additional information in the Generic Processor Error Section. */</span><br><span style="color: hsl(120, 100%, 40%);">+static void fill_generic_section(cper_proc_generic_error_section_t *sec,</span><br><span style="color: hsl(120, 100%, 40%);">+         struct mca_bank *mci)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      int type = mca_err_type(mci->sts);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (type == MCA_ERRTYPE_BUS) /* try to map MCA errors to CPER types */</span><br><span style="color: hsl(120, 100%, 40%);">+                sec->error_type = GENPROC_ERRTYPE_BUS;</span><br><span style="color: hsl(120, 100%, 40%);">+     else if (type == MCA_ERRTYPE_INT)</span><br><span style="color: hsl(120, 100%, 40%);">+             sec->error_type = GENPROC_ERRTYPE_UARCH;</span><br><span style="color: hsl(120, 100%, 40%);">+   else if (type == MCA_ERRTYPE_MEM)</span><br><span style="color: hsl(120, 100%, 40%);">+             sec->error_type = GENPROC_ERRTYPE_CACHE;</span><br><span style="color: hsl(120, 100%, 40%);">+   else if (type == MCA_ERRTYPE_TLB)</span><br><span style="color: hsl(120, 100%, 40%);">+             sec->error_type = GENPROC_ERRTYPE_TLB;</span><br><span style="color: hsl(120, 100%, 40%);">+     else</span><br><span style="color: hsl(120, 100%, 40%);">+          sec->error_type = GENPROC_ERRTYPE_UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+ sec->validation |= GENPROC_VALID_PROC_ERR_TYPE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Potentially also try to decode and add the type of operation, target</span><br><span style="color: hsl(120, 100%, 40%);">+        * address, requestor and responder identifiers, and instruction</span><br><span style="color: hsl(120, 100%, 40%);">+       * pointer.</span><br><span style="color: hsl(120, 100%, 40%);">+    */</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Convert an error reported by an MCA bank into BERT information to be reported</span><br><span style="color: hsl(120, 100%, 40%);">+ * by the OS.  The ACPI driver doesn't recognize/parse the IA32/X64 structure,</span><br><span style="color: hsl(120, 100%, 40%);">+ * which is the best method to report MSR context.  As a result, add two</span><br><span style="color: hsl(120, 100%, 40%);">+ * structures:  A "processor generic error" that is parsed, and an IA32/X64 one</span><br><span style="color: hsl(120, 100%, 40%);">+ * to capture complete information.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void build_bert_mca_error(struct mca_bank *mci)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      acpi_generic_error_status_t *status;</span><br><span style="color: hsl(120, 100%, 40%);">+  acpi_hest_generic_data_v300_t *gen_entry;</span><br><span style="color: hsl(120, 100%, 40%);">+     acpi_hest_generic_data_v300_t *x86_entry;</span><br><span style="color: hsl(120, 100%, 40%);">+     cper_proc_generic_error_section_t *gen_sec;</span><br><span style="color: hsl(120, 100%, 40%);">+   cper_ia32x64_proc_error_section_t *x86_sec;</span><br><span style="color: hsl(120, 100%, 40%);">+   cper_ia32x64_proc_error_info_t *chk;</span><br><span style="color: hsl(120, 100%, 40%);">+  cper_ia32x64_context_t *ctx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!IS_ENABLED(CONFIG_ACPI_BERT))</span><br><span style="color: hsl(120, 100%, 40%);">+            return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (mca_report_size_reqd() > bert_storage_remaining())</span><br><span style="color: hsl(120, 100%, 40%);">+             goto failed;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        status = bert_new_event(&CPER_SEC_PROC_GENERIC_GUID);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!status)</span><br><span style="color: hsl(120, 100%, 40%);">+          goto failed;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        gen_entry = acpi_hest_generic_data3(status);</span><br><span style="color: hsl(120, 100%, 40%);">+  gen_sec = section_of_acpientry(gen_sec, gen_entry);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fill_generic_section(gen_sec, mci);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ x86_entry = bert_append_ia32x64(status);</span><br><span style="color: hsl(120, 100%, 40%);">+      x86_sec = section_of_acpientry(x86_sec, x86_entry);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ chk = new_cper_ia32x64_check(status, x86_sec, error_to_chktype(mci));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!chk)</span><br><span style="color: hsl(120, 100%, 40%);">+             goto failed;</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Future work may interpret the specific Family 15h error symptoms</span><br><span style="color: hsl(120, 100%, 40%);">+    * in the MCA registers and enhance the fields reported within the</span><br><span style="color: hsl(120, 100%, 40%);">+     * Error Check just created.  The level of reporting by the ACPI</span><br><span style="color: hsl(120, 100%, 40%);">+       * driver doesn't currently reward that level of detail.</span><br><span style="color: hsl(120, 100%, 40%);">+   */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ctx = cper_new_ia32x64_context_msr(status, x86_sec, MCG_CAP, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!ctx)</span><br><span style="color: hsl(120, 100%, 40%);">+             goto failed;</span><br><span style="color: hsl(120, 100%, 40%);">+  ctx = cper_new_ia32x64_context_msr(status, x86_sec,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   MC0_CTL + (mci->bank * 4), 4);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!ctx)</span><br><span style="color: hsl(120, 100%, 40%);">+             goto failed;</span><br><span style="color: hsl(120, 100%, 40%);">+  ctx = cper_new_ia32x64_context_msr(status, x86_sec,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   MC0_CTL_MASK + mci->bank, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!ctx)</span><br><span style="color: hsl(120, 100%, 40%);">+             goto failed;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+failed:</span><br><span style="color: hsl(120, 100%, 40%);">+    /* We're here because of a hardware error, don't break something else */</span><br><span style="color: hsl(120, 100%, 40%);">+      printk(BIOS_ERR, "Error, not enough room in reserved BERT region for #MC error\n");</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static const char *const mca_bank_name[] = {</span><br><span>   "Load-store unit",</span><br><span>         "Instruction fetch unit",</span><br><span>@@ -74,6 +206,9 @@</span><br><span>                             mci.cmask = rdmsr(MC0_CTL_MASK + i);</span><br><span>                                 printk(BIOS_WARNING, "   MC%d_CTL_MASK = %08x_%08x\n",</span><br><span>                                             i, mci.cmask.hi, mci.cmask.lo);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                             mci.bank = i;</span><br><span style="color: hsl(120, 100%, 40%);">+                         build_bert_mca_error(&mci);</span><br><span>                      }</span><br><span>            }</span><br><span>    }</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/28477">change 28477</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/28477"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I4d4ce29ddefa22aa29e6d3184f1adeaea1d5f837 </div>
<div style="display:none"> Gerrit-Change-Number: 28477 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Marshall Dawson <marshalldawson3rd@gmail.com> </div>