summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/usr/hwas/hwasPlat.H6
-rw-r--r--src/include/usr/hwas/hwasPlatReasonCodes.H2
-rw-r--r--src/usr/hwas/hwasPlat.C208
3 files changed, 196 insertions, 20 deletions
diff --git a/src/include/usr/hwas/hwasPlat.H b/src/include/usr/hwas/hwasPlat.H
index 6beb85aa7..8ccddd588 100644
--- a/src/include/usr/hwas/hwasPlat.H
+++ b/src/include/usr/hwas/hwasPlat.H
@@ -63,6 +63,12 @@ void markTargetChanged(TARGETING::TargetHandle_t i_target)
{};
#endif
+/**
+ * @brief Helper function to check if HB is running
+ * from an NVDIMM and not a regular DIMM
+ */
+errlHndl_t checkForHbOnNvdimm();
+
// default unknown EC level
constexpr TARGETING::ATTR_EC_type INVALID__ATTR_EC = 0xFF;
diff --git a/src/include/usr/hwas/hwasPlatReasonCodes.H b/src/include/usr/hwas/hwasPlatReasonCodes.H
index 6ca33397a..a0ea1f962 100644
--- a/src/include/usr/hwas/hwasPlatReasonCodes.H
+++ b/src/include/usr/hwas/hwasPlatReasonCodes.H
@@ -38,6 +38,7 @@ namespace HWAS
MOD_PLAT_DECONFIG_GARD = 0x81,
MOD_PLAT_READIDEC = 0x82,
MOD_PLAT_READLX = 0x83,
+ MOD_CHECK_HB_NVDIMM = 0x84,
};
enum HwasPlatReasonCode
@@ -52,6 +53,7 @@ namespace HWAS
RC_BAD_MCA = HWAS_COMP_ID | 0x85,
RC_RT_NULL_FIRMWARE_REQUEST_PTR = HWAS_COMP_ID | 0x86,
RC_RT_NULL_FIRMWARE_MSG_PTR = HWAS_COMP_ID | 0x87,
+ RC_HB_PROC_ONLY_NVDIMM = HWAS_COMP_ID | 0x88,
};
};
diff --git a/src/usr/hwas/hwasPlat.C b/src/usr/hwas/hwasPlat.C
index e72d5109e..bea5b4d8f 100644
--- a/src/usr/hwas/hwasPlat.C
+++ b/src/usr/hwas/hwasPlat.C
@@ -40,6 +40,7 @@
#include <vpd/mvpdenums.H>
#include <stdio.h>
#include <sys/mm.h>
+#include <sys/misc.h>
#include <pnor/pnorif.H>
@@ -75,6 +76,7 @@ RegisterHWASFunctions registerHWASFunctions;
using namespace TARGETING;
+
//******************************************************************************
// platReadIDEC function
//******************************************************************************
@@ -696,28 +698,194 @@ void markTargetChanged(TARGETING::TargetHandle_t i_target)
// platCheckMinimumHardware()
//******************************************************************************
void platCheckMinimumHardware(uint32_t & io_plid,
- const TARGETING::ConstTargetHandle_t i_node,
- bool *o_bootable)
+ const TARGETING::ConstTargetHandle_t i_node,
+ bool *o_bootable)
{
- //errlHndl_t l_errl = NULL;
-
- // nothing to do yet...
-
- // if you add something here, don't forget to
- // add a procedure callout
- //l_errl->addProcedureCallout( EPUB_PRC_FIND_DECONFIGURED_PART,
- // SRCI_PRIORITY_HIGH);
-
- // and update the common plid
- //if (io_plid != 0)
- //{
- // l_errl->plid(io_plid) ;
- //}
- //else
- //{
- // io_plid = l_errl->plid();
- //}
+ errlHndl_t l_errl = NULL;
+
+ Target* l_pMasterProcChip = NULL;
+ targetService().masterProcChipTargetHandle(l_pMasterProcChip);
+
+ // NVDIMM only supported on Nimbus
+ ATTR_MODEL_type l_model = l_pMasterProcChip->getAttr<ATTR_MODEL>();
+ if (l_model == MODEL_NIMBUS)
+ {
+ l_errl = checkForHbOnNvdimm();
+ if (l_errl)
+ {
+ HWAS_ERR("platCheckMinimumHardware::checkForHbOnNvdimm() failed.");
+
+ if(o_bootable)
+ {
+ *o_bootable = false;
+ }
+
+ // Add procedure callout, update common plid, commit
+ hwasErrorAddProcedureCallout(l_errl,
+ EPUB_PRC_FIND_DECONFIGURED_PART,
+ SRCI_PRIORITY_HIGH);
+ hwasErrorUpdatePlid(l_errl, io_plid);
+ errlCommit(l_errl, HWAS_COMP_ID);
+ }
+ }
+
}
+//******************************************************************************
+// checkForHbOnNvdimm()
+//******************************************************************************
+errlHndl_t checkForHbOnNvdimm(void)
+{
+ errlHndl_t l_errl = nullptr;
+
+ do
+ {
+ HWAS_DBG("Check if HB is running on a proc with only NVDIMMs.");
+
+ // Get all functional proc chip targets
+ TargetHandleList l_procList;
+ getAllChips(l_procList, TARGETING::TYPE_PROC);
+ assert(l_procList.size() != 0, "Empty proc list returned!");
+
+ // Use the hrmor to find which proc HB is running on
+ const auto l_hbHrmor = cpu_spr_value(CPU_SPR_HRMOR);
+
+ // Use the MemBases and MemSizes to find which group
+ // includes the hrmor
+ ATTR_PROC_MEM_BASES_type l_memBases = {0};
+ ATTR_PROC_MEM_SIZES_type l_memSizes = {0};
+ size_t l_numGroups = sizeof(ATTR_PROC_MEM_SIZES_type)/sizeof(uint64_t);
+
+ // checkMinimumHardware may be called before the groups are set up
+ // If the MemSizes are all zero the groups are not set up yet
+ // Break out of the check
+ bool l_memSizesAllZero = true;
+
+ // Save the HB proc target and group number
+ Target *l_hbProc = nullptr;
+ uint32_t l_hbGroup = 0;
+
+ for (auto l_pProc : l_procList)
+ {
+ // Get the memory group ranges under this proc
+ assert(l_pProc->tryGetAttr<ATTR_PROC_MEM_BASES>(l_memBases),
+ "Unable to get ATTR_PROC_MEM_BASES attribute");
+ assert(l_pProc->tryGetAttr<ATTR_PROC_MEM_SIZES>(l_memSizes),
+ "Unable to get ATTR_PROC_MEM_SIZES attribute");
+
+
+ for (size_t l_grp=0; l_grp < l_numGroups; l_grp++)
+ {
+ // Non-zero size means that there is memory present
+ if (l_memSizes[l_grp])
+ {
+ l_memSizesAllZero = false;
+ // Check if hrmor is in this group's memory range
+ if ( (l_hbHrmor >= l_memBases[l_grp]) &&
+ (l_hbHrmor < (l_memBases[l_grp] +
+ l_memSizes[l_grp])) )
+ {
+ l_hbProc = l_pProc;
+ l_hbGroup = l_grp;
+ break;
+ }
+ }
+ }
+ if (l_hbProc != nullptr)
+ {
+ break;
+ }
+ }
+
+ if (l_memSizesAllZero)
+ {
+ break;
+ }
+
+ if (l_hbProc != nullptr)
+ {
+ // Found the proc/group HB is running in, now check the dimms
+ // If we find a regular dimm then we assume that is where
+ // HB is running
+ bool l_foundNonNvdimm = false;
+
+ // Get the array of mcas/group from the attribute
+ // The attr contains 8 8-bit entries, one entry per group
+ // The bits specify which mcas are included in the group
+ ATTR_MSS_MEM_MC_IN_GROUP_type l_memMcGroup = {0};
+ assert(l_hbProc->tryGetAttr<ATTR_MSS_MEM_MC_IN_GROUP>(l_memMcGroup),
+ "Unable to get ATTR_MSS_MEM_MC_IN_GROUP attribute");
+
+ // Get list of mcas under this proc
+ TargetHandleList l_mcaList;
+ getChildAffinityTargets( l_mcaList,
+ l_hbProc,
+ CLASS_UNIT,
+ TYPE_MCA );
+
+ // Loop through the mcas on this proc
+ for (const auto & l_mcaTarget : l_mcaList)
+ {
+ // Get the chip unit for this mca
+ ATTR_CHIP_UNIT_type l_mcaUnit = 0;
+ l_mcaUnit = l_mcaTarget->getAttr<ATTR_CHIP_UNIT>();
+
+ // Check if this mca is included in the hb memory group
+ const uint8_t l_mcMask = 0x80;
+ if (l_memMcGroup[l_hbGroup] & (l_mcMask >> l_mcaUnit))
+ {
+ // Get the list of dimms under this mca
+ TargetHandleList l_dimmList;
+ getChildAffinityTargets( l_dimmList,
+ l_mcaTarget,
+ CLASS_NA,
+ TYPE_DIMM );
+ for (const auto & l_dimmTarget : l_dimmList)
+ {
+ if (!isNVDIMM(l_dimmTarget))
+ {
+ // Found a regular dimm, exit
+ l_foundNonNvdimm = true;
+ break;
+ }
+ }
+ }
+ if (l_foundNonNvdimm)
+ {
+ break;
+ }
+ }
+
+ // If only nvdimms then error
+ if (!l_foundNonNvdimm)
+ {
+ HWAS_ERR("checkForHbOnNvdimm: HB is running on a proc with only NVDIMMS.");
+ /*@
+ * @errortype ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid HWAS::MOD_CHECK_HB_NVDIMM
+ * @reasoncode HWAS::RC_HB_PROC_ONLY_NVDIMM
+ * @userdata1 Hostboot Proc Target HUID
+ * @userdata2 Hostboot Memory Group
+ * @devdesc Hostboot running on proc with only NVDIMMs
+ * @custdesc Insufficient DIMM resources
+ */
+ l_errl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HWAS::MOD_CHECK_HB_NVDIMM,
+ HWAS::RC_HB_PROC_ONLY_NVDIMM,
+ get_huid(l_hbProc),
+ l_hbGroup);
+ }
+ }
+ else
+ {
+ // Should never get here, would be caught elsewhere
+ HWAS_ERR("checkForHbOnNvdimm: HB execution proc not found.");
+ }
+
+ } while(0);
+
+ return l_errl;
+}
} // namespace HWAS
OpenPOWER on IntegriCloud