summaryrefslogtreecommitdiffstats
path: root/src/usr/dump
diff options
context:
space:
mode:
authorRaja Das <rajadas2@in.ibm.com>2018-10-25 11:26:25 +0530
committerDaniel M. Crowell <dcrowell@us.ibm.com>2019-03-21 13:11:36 -0500
commitb8f4e5009a347a0201fbe09b3701ceeb6edd9bf2 (patch)
tree943d5166fc775006987ecf7a6c57b5f91dbc0bc7 /src/usr/dump
parentd09e67a0a55418f2878d016f372bc751b549d535 (diff)
downloadtalos-hostboot-b8f4e5009a347a0201fbe09b3701ceeb6edd9bf2.tar.gz
talos-hostboot-b8f4e5009a347a0201fbe09b3701ceeb6edd9bf2.zip
OPAL/MPIPL: Processor Dump Area Table interfaces
This patch adds support to collect processor architected register data. SBE <--> Hostboot : ------------------- During first boot, hostboot reserves memory to copy architected register data by SBE and sends address to each SBE (see commit 9f49d11b). During MPIPL SBE collects architected register data and copies to reserved memory. Hostboot <--> Hypervisor : -------------------------- HDAT/SPIRAH has new ntuple (Processor Dump Area) to pass various architected register data. During IPL/runtime hypervisor reserves memory for architected register data and updates SPIRAH. During MPIPL (istep 14.8), hostboot converts SBE formated architected registers data to HDAT format and copies to hypervisor reserved memory. It uses NACA/SPIRAH pointers to get hypervisor reserved memory details. Hostboot has to update SPIRAH ntuple after loading new LID to memory. Hence this patch introdues below new attributes: - PDA_CAPTURED_THREAD_REG_ARRAY_ADDR - PDA_CAPTURED_THREAD_REG_ARRAY_SIZE - PDA_THREAD_REG_ENTRY_SIZE - PDA_THREAD_REG_STATE_ENTRY_FORMAT Change-Id: Idc7489e8cf6fc68fe80f028ba6deb97aa72486bf CC: Sampa Misra <sampmisr@in.ibm.com> CC: Daniel M. Crowell <dcrowell@us.ibm.com> Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com> Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/61627 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/dump')
-rw-r--r--src/usr/dump/dumpCollect.C318
1 files changed, 315 insertions, 3 deletions
diff --git a/src/usr/dump/dumpCollect.C b/src/usr/dump/dumpCollect.C
index 41b7d68e2..8e186c311 100644
--- a/src/usr/dump/dumpCollect.C
+++ b/src/usr/dump/dumpCollect.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2012,2018 */
+/* Contributors Listed Below - COPYRIGHT 2012,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -34,20 +34,23 @@
#include <errl/errlentry.H>
#include <errl/errlmanager.H>
#include <targeting/common/commontargeting.H>
+#include <targeting/common/utilFilter.H>
#include <runtime/runtime.H>
#include <util/align.H>
#include <sys/mm.h>
#include <dump/dumpif.H>
#include <util/utiltce.H>
+#include <isteps/mem_utils.H>
-#include <sys/msg.h> // message Q's
-#include <mbox/mbox_queues.H> //
+#include <sys/msg.h> // message Q's
+#include <mbox/mbox_queues.H> //
#include <kernel/vmmmgr.H>
// Trace definition
trace_desc_t* g_trac_dump = NULL;
TRAC_INIT(&g_trac_dump, "DUMP", 4*KILOBYTE);
+#define SBE_FFDC_SIZE 128
namespace DUMP
{
@@ -133,6 +136,315 @@ void* getPhysAddr( uint64_t i_phypAddr )
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
+errlHndl_t copyArchitectedRegs(void)
+{
+ TRACFCOMP(g_trac_dump, "copyArchitectedRegs - start ");
+ errlHndl_t l_err = nullptr;
+ int rc;
+ // Processor dump area address and size from HDAT
+ uint64_t procTableAddr = 0;
+ uint64_t procTableSize = 0;
+ // Pointer to architected register reserved memory
+ void *pSrcAddrBase = nullptr;
+ void *vMapSrcAddrBase = nullptr;
+ // Pointers to Hypervisor allocated memory for register data content
+ void *pDstAddrBase = nullptr;
+ void *vMapDstAddrBase = nullptr;
+ // Architected Reg Dump table struct pointers
+ procDumpAreaEntry *procTableEntry = nullptr;
+
+ do
+ {
+ // Get the PROC_DUMP_AREA_TBL address from SPIRAH
+ l_err = RUNTIME::get_host_data_section(RUNTIME::PROC_DUMP_AREA_TBL,
+ 0,
+ procTableAddr,
+ procTableSize);
+ if (l_err)
+ {
+ // Got an errorlog back from get_host_data_sections
+ TRACFCOMP(g_trac_dump, "copyArchitectedRegs get_host_data_sections "
+ "for PDAT failed");
+ break;
+ }
+
+ // If the address or size is zero - error out
+ if ((procTableAddr == 0) || (procTableSize == 0))
+ {
+ // Invalid address or size
+ TRACFCOMP(g_trac_dump, "copyArchitectedRegs address or size invalid"
+ " for PDAT: addr =0x%X, size =0x%X,",
+ procTableAddr, procTableSize);
+ /*@
+ * @errortype
+ * @moduleid DUMP::DUMP_ARCH_REGS
+ * @reasoncode DUMP::DUMP_PDAT_INVALID_ADDR
+ * @userdata1 Table address returned
+ * @userdata2 Table size returned
+ * @devdesc Invalid address and size returned from HDAT
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ DUMP_ARCH_REGS,
+ DUMP_PDAT_INVALID_ADDR,
+ procTableAddr,
+ procTableSize,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ break;
+ }
+
+ // Map processor dump area destination address to VA addresses
+ procTableEntry = reinterpret_cast<procDumpAreaEntry *>(procTableAddr);
+ pDstAddrBase = getPhysAddr(procTableEntry->dstArrayAddr);
+ vMapDstAddrBase = mm_block_map(pDstAddrBase,
+ procTableEntry->dstArraySize);
+
+ // Map architected register reserved memory to VA addresses
+ uint64_t srcAddr = ISTEP::get_top_mem_addr() -
+ VMM_ARCH_REG_DATA_SIZE_ALL_PROC -
+ VMM_ALL_HOMER_OCC_MEMORY_SIZE;
+ pSrcAddrBase = reinterpret_cast<void * const>(srcAddr);
+ vMapSrcAddrBase = mm_block_map(pSrcAddrBase,
+ VMM_ARCH_REG_DATA_SIZE_ALL_PROC);
+
+ // Get list of functional processor chips, in MPIPL path we
+ // don't expect any deconfiguration
+ TARGETING::TargetHandleList procChips;
+ TARGETING::getAllChips( procChips, TARGETING::TYPE_PROC, true);
+
+
+ uint64_t dstTempAddr = reinterpret_cast<uint64_t>(vMapDstAddrBase);
+ procTableEntry->capArraySize = 0;
+ for (const auto & procChip: procChips)
+ {
+ uint8_t procNum = procChip->getAttr<TARGETING::ATTR_POSITION>();
+ // Base addresses w.r.t PROC positions. This is static here
+ // and used for reference below to calculate all other addresses
+ uint64_t procSrcAddr = (reinterpret_cast<uint64_t>(vMapSrcAddrBase)+
+ procNum * VMM_ARCH_REG_DATA_PER_PROC_SIZE);
+
+ sbeArchRegDumpProcHdr_t *sbeProcHdr =
+ reinterpret_cast<sbeArchRegDumpProcHdr_t *>(procSrcAddr);
+ uint16_t threadCount = sbeProcHdr->thread_cnt;
+ uint16_t regCount = sbeProcHdr->reg_cnt;
+
+ //Validate the structure versions used by SBE and HB for sharing the
+ //data
+ if( sbeProcHdr->version != REG_DUMP_SBE_HB_STRUCT_VER )
+ {
+ /*@
+ * @errortype
+ * @moduleid DUMP::DUMP_ARCH_REGS
+ * @reasoncode DUMP::DUMP_PDAT_VERSION_MISMATCH
+ * @userdata1 Structure version obtained from SBE
+ * @userdata2 Structure version supported by HB
+ * @devdesc Mismatch between the version of structure
+ * supported by both SBE and HB.
+ *
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ DUMP_ARCH_REGS,
+ DUMP_PDAT_VERSION_MISMATCH,
+ sbeProcHdr->version,
+ REG_DUMP_SBE_HB_STRUCT_VER,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ errlCommit(l_err, DUMP_COMP_ID);
+ break;
+ }
+
+ //Update the data source address to point to the thread specific
+ //header data obtained by SBE
+ procSrcAddr = reinterpret_cast<uint64_t>(procSrcAddr +
+ sizeof(sbeArchRegDumpProcHdr_t));
+
+ procTableEntry->threadRegSize = sizeof(hostArchRegDataHdr)+
+ (regCount * sizeof(hostArchRegDataEntry));
+ procTableEntry->capArraySize = procTableEntry->capArraySize +
+ (procTableEntry->threadRegSize
+ * threadCount);
+ if (procTableEntry->dstArraySize < procTableEntry->capArraySize)
+ {
+ /*@
+ * @errortype
+ * @moduleid DUMP::DUMP_ARCH_REGS
+ * @reasoncode DUMP::DUMP_PDAT_INSUFFICIENT_SPACE
+ * @userdata1 Hypervisor reserved memory size
+ * @userdata2 Memory needed to copy architected
+ * register data
+ * @devdesc Insufficient space to copy architected
+ * registers
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ DUMP_ARCH_REGS,
+ DUMP_PDAT_INSUFFICIENT_SPACE,
+ procTableEntry->dstArraySize,
+ procTableEntry->capArraySize,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ errlCommit(l_err, DUMP_COMP_ID);
+ break;
+ }
+
+ // Total Number of Threads possible in one Proc
+ for(uint32_t idx = 0; idx < threadCount; idx++)
+ {
+ sbeArchRegDumpThreadHdr_t *sbeTdHdr =
+ reinterpret_cast<sbeArchRegDumpThreadHdr_t *>(procSrcAddr);
+
+ hostArchRegDataHdr *hostHdr =
+ reinterpret_cast<hostArchRegDataHdr *>(dstTempAddr);
+
+ // Fill thread header info
+ hostHdr->pir = sbeTdHdr->pir;
+ hostHdr->coreState = sbeTdHdr->coreState;
+ hostHdr->iv_regArrayHdr.hdatOffset =
+ sizeof(HDAT::hdatHDIFDataArray_t);
+ hostHdr->iv_regArrayHdr.hdatArrayCnt = regCount;
+ hostHdr->iv_regArrayHdr.hdatAllocSize =
+ sizeof(hostArchRegDataEntry);
+ hostHdr->iv_regArrayHdr.hdatActSize =
+ sizeof(hostArchRegDataEntry);
+
+ dstTempAddr = reinterpret_cast<uint64_t>(dstTempAddr +
+ sizeof(hostArchRegDataHdr));
+ //Update SBE data source address to point to the register data
+ //related to the current thread.
+ procSrcAddr = reinterpret_cast<uint64_t>(procSrcAddr +
+ sizeof(sbeArchRegDumpThreadHdr_t));
+
+ //Validate the CoreState to find if the buffer has register data
+ if (sbeTdHdr->coreState != 0)
+ {
+ //Bump up the destination address to skip the memory
+ //required to store the register details.
+ dstTempAddr = reinterpret_cast<uint64_t>(dstTempAddr +
+ (regCount * sizeof(hostArchRegDataEntry)));
+ continue;
+ }
+
+
+ // Fill register data
+ for(uint8_t cnt = 0; cnt < regCount; cnt++)
+ {
+ sbeArchRegDumpEntries_t *sbeRegData =
+ reinterpret_cast<sbeArchRegDumpEntries_t *>(procSrcAddr);
+ hostArchRegDataEntry *hostRegData =
+ reinterpret_cast<hostArchRegDataEntry *>(dstTempAddr);
+
+ hostRegData->regType = sbeRegData->regType;
+ hostRegData->regNum = sbeRegData->regNum;
+ hostRegData->regVal = sbeRegData->regVal;
+
+ dstTempAddr = reinterpret_cast<uint64_t>(dstTempAddr +
+ sizeof(hostArchRegDataEntry));
+ //Update the SBE data source address to point to the
+ //next register data related to the same thread.
+ procSrcAddr = reinterpret_cast<uint64_t>(procSrcAddr +
+ sizeof(sbeArchRegDumpEntries_t));
+ if( sbeRegData->isLastReg )
+ {
+ //Skip the FFDC for now
+ if(sbeRegData->isFfdcPresent)
+ {
+ //Move the source address to skip theFFDC
+ procSrcAddr = procSrcAddr + (sizeof(uint32_t)*SBE_FFDC_SIZE);
+ //Adjust the destination address accordingly to skip
+ //the mememory required for remaining registers
+ uint32_t remaingRegCount = regCount - (cnt+1);
+ if(remaingRegCount)
+ {
+ dstTempAddr = reinterpret_cast<uint64_t>(
+ dstTempAddr + (remaingRegCount *
+ sizeof(hostArchRegDataEntry)));
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ // Update Process Dump Area tuple
+ procTableEntry->threadRegVersion = REG_DUMP_HDAT_STRUCT_VER;
+ procTableEntry->capArrayAddr = procTableEntry->dstArrayAddr;
+
+ // Update the PDA Table Entries to Attribute to be fetched in istep 21
+ TARGETING::TargetService& targetService = TARGETING::targetService();
+ TARGETING::Target* l_sys = NULL;
+ targetService.getTopLevelTarget(l_sys);
+ l_sys->setAttr<TARGETING::ATTR_PDA_THREAD_REG_STATE_ENTRY_FORMAT>(
+ procTableEntry->threadRegVersion);
+ l_sys->setAttr<TARGETING::ATTR_PDA_THREAD_REG_ENTRY_SIZE>(
+ procTableEntry->threadRegSize);
+ l_sys->setAttr<TARGETING::ATTR_PDA_CAPTURED_THREAD_REG_ARRAY_ADDR>(
+ procTableEntry->capArrayAddr);
+ l_sys->setAttr<TARGETING::ATTR_PDA_CAPTURED_THREAD_REG_ARRAY_SIZE>(
+ procTableEntry->capArraySize);
+
+ } while (0);
+
+ // Unmap destination memory
+ if (vMapDstAddrBase)
+ {
+ rc = mm_block_unmap(vMapDstAddrBase);
+ if (rc != 0)
+ {
+ /*@
+ * @errortype
+ * @moduleid DUMP::DUMP_ARCH_REGS
+ * @reasoncode DUMP::DUMP_PDAT_CANNOT_UNMAP_DST_ADDR
+ * @userdata1 VA of Destination Array Address for PDAT
+ * @userdata2 rc value from unmap
+ * @devdesc Cannot unmap the PDAT Destinatin Array Addr
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ DUMP_ARCH_REGS,
+ DUMP_PDAT_CANNOT_UNMAP_DST_ADDR,
+ (uint64_t)vMapDstAddrBase,
+ rc,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+
+ // Commit the error and continue.
+ // Leave the devices unmapped?
+ errlCommit(l_err, DUMP_COMP_ID);
+ l_err = NULL;
+ }
+ }
+
+ // Unmap source memory
+ if(vMapSrcAddrBase)
+ {
+ rc = mm_block_unmap(vMapSrcAddrBase);
+ if (rc != 0)
+ {
+ /*@
+ * @errortype
+ * @moduleid DUMP::DUMP_ARCH_REGS
+ * @reasoncode DUMP::DUMP_PDAT_CANNOT_UNMAP_SRC_ADDR
+ * @userdata1 VA address of Source Array Address for PDAT
+ * @userdata2 rc value from unmap
+ * @devdesc Cannot unmap the PDAT Source Array Address
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ DUMP_ARCH_REGS,
+ DUMP_PDAT_CANNOT_UNMAP_SRC_ADDR,
+ (uint64_t)vMapSrcAddrBase,
+ rc,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+
+ // Commit the error and continue.
+ // Leave the devices unmapped?
+ errlCommit(l_err, DUMP_COMP_ID);
+ l_err = NULL;
+ }
+ }
+ TRACFCOMP(g_trac_dump, "copyArchitectedRegs - end ");
+ return (l_err);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
errlHndl_t copySrcToDest(dumpEntry *srcTableEntry,
uint64_t srcTableSize,
OpenPOWER on IntegriCloud