summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
authorMarty Gloff <mgloff@us.ibm.com>2015-06-10 15:23:20 -0500
committerPatrick Williams <iawillia@us.ibm.com>2015-12-11 13:56:27 -0600
commit9627b4c4bc588981f2d9c76d6fc36b03ee26c800 (patch)
treef8beb54f7d708dff60a0abcdeec2ea7fa4c5a90d /src/usr
parent5d33811c6f265463f502c19dd2a3173e1bbc38bc (diff)
downloadtalos-hostboot-9627b4c4bc588981f2d9c76d6fc36b03ee26c800.tar.gz
talos-hostboot-9627b4c4bc588981f2d9c76d6fc36b03ee26c800.zip
P9 - PG partial good keywords
Processing of PG Keyword version x'02' Partial Good Vectors Change-Id: I7d239495c237f09edaa2addc538ced5e389009d6 RTC:127213 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/18349 Tested-by: Jenkins Server Reviewed-by: Corey V. Swenson <cswenson@us.ibm.com> Reviewed-by: Christian Geddes <crgeddes@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr')
-rw-r--r--src/usr/hwas/common/hwas.C645
-rw-r--r--src/usr/hwas/test/hwas1test.H826
-rw-r--r--src/usr/hwas/test/hwasGardTest.H20
3 files changed, 1366 insertions, 125 deletions
diff --git a/src/usr/hwas/common/hwas.C b/src/usr/hwas/common/hwas.C
index c4f63126c..2e6445415 100644
--- a/src/usr/hwas/common/hwas.C
+++ b/src/usr/hwas/common/hwas.C
@@ -52,6 +52,7 @@
#include <hwas/common/hwas_reasoncodes.H>
#include <targeting/common/utilFilter.H>
+
namespace HWAS
{
@@ -117,6 +118,82 @@ void enableHwasState(Target *i_target,
}
+/**
+ * @brief simple helper fn to check IOX/PBIOX pairs in PG XBUS data
+ *
+ * @param[in] i_pgData XBUS data from PG keyword VPD
+ *
+ * @return bool pairs are valid
+ *
+ */
+bool areIoxPairsValid(uint16_t i_pgData)
+{
+ bool l_valid = true;
+
+ // Check that pairs are valid, that is, both good or both bad
+ for (uint8_t l_pair = 0;
+ l_pair <= 2;
+ l_pair++)
+ {
+ // Check if both are good in the pair
+ if ((i_pgData & VPD_CP00_PG_XBUS_IOX_PAIR[l_pair]) == 0)
+ {
+ continue;
+ }
+
+ // Check if both are bad in the pair
+ if ((i_pgData & VPD_CP00_PG_XBUS_IOX_PAIR[l_pair]) ==
+ VPD_CP00_PG_XBUS_IOX_PAIR[l_pair])
+ {
+ continue;
+ }
+
+ l_valid = false;
+ break;
+ }
+
+ return l_valid;
+}
+
+
+/**
+ * @brief simple helper fn to check L3/L2/REFR triplets in PG EPx data
+ *
+ * @param[in] i_pgData EPx data from PG keyword VPD
+ *
+ * @return bool triplets are valid
+ *
+ */
+bool areL3L2REFRtripletsValid(uint16_t i_pgData)
+{
+ bool l_valid = true;
+
+ // Check that triplets are valid, that is, all good or all bad
+ for (uint8_t l_triplet = 0;
+ l_triplet <= 1;
+ l_triplet++)
+ {
+ // Check if all are good in the triplet
+ if ((i_pgData & VPD_CP00_PG_EPx_L3L2REFR[l_triplet]) == 0)
+ {
+ continue;
+ }
+
+ // Check if all are bad in the triplet
+ if ((i_pgData & VPD_CP00_PG_EPx_L3L2REFR[l_triplet]) ==
+ VPD_CP00_PG_EPx_L3L2REFR[l_triplet])
+ {
+ continue;
+ }
+
+ l_valid = false;
+ break;
+ }
+
+ return l_valid;
+}
+
+
errlHndl_t discoverTargets()
{
HWAS_DBG("discoverTargets entry");
@@ -251,40 +328,13 @@ errlHndl_t discoverTargets()
// errl is now NULL
}
else
- // look at the 'nest' logic to override the functionality
- // of this proc
- if (pgData[VPD_CP00_PG_PIB_INDEX] !=
- VPD_CP00_PG_PIB_GOOD)
- {
- HWAS_INF("pTarget %.8X - PIB pgPdata[%d]: expected 0x%04X - bad",
- pTarget->getAttr<ATTR_HUID>(),
- VPD_CP00_PG_PIB_INDEX,
- VPD_CP00_PG_PIB_GOOD);
- chipFunctional = false;
- }
- else
- if (pgData[VPD_CP00_PG_PERVASIVE_INDEX] !=
- VPD_CP00_PG_PERVASIVE_GOOD)
- {
- HWAS_INF("pTarget %.8X - Pervasive pgPdata[%d]: expected 0x%04X - bad",
- pTarget->getAttr<ATTR_HUID>(),
- VPD_CP00_PG_PERVASIVE_INDEX,
- VPD_CP00_PG_PERVASIVE_GOOD);
- chipFunctional = false;
- }
- else
- if ((pgData[VPD_CP00_PG_POWERBUS_INDEX] &
- VPD_CP00_PG_POWERBUS_BASE) !=
- VPD_CP00_PG_POWERBUS_BASE)
- {
- HWAS_INF("pTarget %.8X - PowerBus pgPdata[%d]: expected 0x%04X - bad",
- pTarget->getAttr<ATTR_HUID>(),
- VPD_CP00_PG_POWERBUS_INDEX,
- VPD_CP00_PG_POWERBUS_BASE);
- chipFunctional = false;
- }
- else
{
+ // look at the 'nest' logic to override the functionality
+ // of this proc
+ chipFunctional = isChipFunctional(pTarget, pgData);
+
+ if (chipFunctional)
+ {
// read the PR keywords that we need, so that if
// we have errors, we can handle them as approprite.
uint8_t prData[VPD_VINI_PR_DATA_LENGTH/sizeof(uint8_t)];
@@ -324,6 +374,7 @@ errlHndl_t discoverTargets()
pTarget->getAttr<ATTR_HUID>());
}
}
+ }
}
} // TYPE_PROC
} // CLASS_CHIP
@@ -346,87 +397,11 @@ errlHndl_t discoverTargets()
bool descFunctional = chipFunctional;
if (chipFunctional)
- { // if the chip is functional, the look through the
+ { // if the chip is functional, then look through the
// partialGood vector to see if its chiplets
// are functional
- if ((pDesc->getAttr<ATTR_TYPE>() == TYPE_XBUS) &&
- (pgData[VPD_CP00_PG_XBUS_INDEX] !=
- VPD_CP00_PG_XBUS_GOOD))
- {
- HWAS_INF("pDesc %.8X - XBUS pgPdata[%d]: expected 0x%04X - bad",
- pDesc->getAttr<ATTR_HUID>(),
- VPD_CP00_PG_XBUS_INDEX,
- VPD_CP00_PG_XBUS_GOOD);
- descFunctional = false;
- }
- else
- if ((pDesc->getAttr<ATTR_TYPE>() == TYPE_ABUS) &&
- (pgData[VPD_CP00_PG_ABUS_INDEX] !=
- VPD_CP00_PG_ABUS_GOOD))
- {
- HWAS_INF("pDesc %.8X - ABUS pgPdata[%d]: expected 0x%04X - bad",
- pDesc->getAttr<ATTR_HUID>(),
- VPD_CP00_PG_ABUS_INDEX,
- VPD_CP00_PG_ABUS_GOOD);
- descFunctional = false;
- }
- else
- if ((pDesc->getAttr<ATTR_TYPE>() == TYPE_PCI) &&
- (pgData[VPD_CP00_PG_PCIE_INDEX] !=
- VPD_CP00_PG_PCIE_GOOD))
- {
- HWAS_INF("pDesc %.8X - PCIe pgPdata[%d]: expected 0x%04X - bad",
- pDesc->getAttr<ATTR_HUID>(),
- VPD_CP00_PG_PCIE_INDEX,
- VPD_CP00_PG_PCIE_GOOD);
- descFunctional = false;
- }
- else
- if ((pDesc->getAttr<ATTR_TYPE>() == TYPE_EX) ||
- (pDesc->getAttr<ATTR_TYPE>() == TYPE_CORE)
- )
- {
- ATTR_CHIP_UNIT_type indexEX =
- pDesc->getAttr<ATTR_CHIP_UNIT>();
- if (pgData[VPD_CP00_PG_EX0_INDEX + indexEX] !=
- VPD_CP00_PG_EX0_GOOD)
- {
- HWAS_INF("pDesc %.8X - CORE/EX%d pgPdata[%d]: expected 0x%04X - bad",
- pDesc->getAttr<ATTR_HUID>(), indexEX,
- VPD_CP00_PG_EX0_INDEX + indexEX,
- VPD_CP00_PG_EX0_GOOD);
- descFunctional = false;
- }
- }
- else
- if (pDesc->getAttr<ATTR_TYPE>() == TYPE_MCS)
- {
- ATTR_CHIP_UNIT_type indexMCS =
- pDesc->getAttr<ATTR_CHIP_UNIT>();
- // check: MCS 0..3 in MCL, MCS 4..7 in MCR
- if (((indexMCS >=0) && (indexMCS <=3)) &&
- ((pgData[VPD_CP00_PG_POWERBUS_INDEX] &
- VPD_CP00_PG_POWERBUS_MCL) == 0))
- {
- HWAS_INF("pDesc %.8X - MCS%d pgPdata[%d]: MCL expected 0x%04X - bad",
- pDesc->getAttr<ATTR_HUID>(), indexMCS,
- VPD_CP00_PG_POWERBUS_INDEX,
- VPD_CP00_PG_POWERBUS_MCL);
- descFunctional = false;
- }
- else
- if (((indexMCS >=4) && (indexMCS <=7)) &&
- ((pgData[VPD_CP00_PG_POWERBUS_INDEX] &
- VPD_CP00_PG_POWERBUS_MCR) == 0))
- {
- HWAS_INF("pDesc %.8X - MCS%d pgPdata[%d]: MCR expected 0x%04X - bad",
- pDesc->getAttr<ATTR_HUID>(), indexMCS,
- VPD_CP00_PG_POWERBUS_INDEX,
- VPD_CP00_PG_POWERBUS_MCR);
- descFunctional = false;
- }
- }
- } // chipFunctional
+ descFunctional = isDescFunctional(pDesc, pgData);
+ }
// for sub-parts, if it's not functional, it's not present.
enableHwasState(pDesc, descFunctional, descFunctional,
@@ -500,6 +475,450 @@ errlHndl_t discoverTargets()
} // discoverTargets
+bool isChipFunctional(const TARGETING::TargetHandle_t &i_target,
+ const uint16_t i_pgData[])
+{
+ bool l_chipFunctional = true;
+
+ // Check all bits in FSI entry
+ if (i_pgData[VPD_CP00_PG_FSI_INDEX] !=
+ VPD_CP00_PG_FSI_GOOD)
+ {
+ HWAS_INF("pTarget %.8X - FSI pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_target->getAttr<ATTR_HUID>(),
+ VPD_CP00_PG_FSI_INDEX,
+ i_pgData[VPD_CP00_PG_FSI_INDEX],
+ VPD_CP00_PG_FSI_GOOD);
+ l_chipFunctional = false;
+ }
+ else
+ // Check all bits in PRV entry
+ if (i_pgData[VPD_CP00_PG_PERVASIVE_INDEX] !=
+ VPD_CP00_PG_PERVASIVE_GOOD)
+ {
+ HWAS_INF("pTarget %.8X - Pervasive pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_target->getAttr<ATTR_HUID>(),
+ VPD_CP00_PG_PERVASIVE_INDEX,
+ i_pgData[VPD_CP00_PG_PERVASIVE_INDEX],
+ VPD_CP00_PG_PERVASIVE_GOOD);
+ l_chipFunctional = false;
+ }
+ else
+ // Check all bits in N0 entry
+ if (i_pgData[VPD_CP00_PG_N0_INDEX] != VPD_CP00_PG_N0_GOOD)
+ {
+ HWAS_INF("pTarget %.8X - N0 pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_target->getAttr<ATTR_HUID>(),
+ VPD_CP00_PG_N0_INDEX,
+ i_pgData[VPD_CP00_PG_N0_INDEX],
+ VPD_CP00_PG_N0_GOOD);
+ l_chipFunctional = false;
+ }
+ else
+ // Check bits in N1 entry except those in partial good region
+ if ((i_pgData[VPD_CP00_PG_N1_INDEX] &
+ ~VPD_CP00_PG_N1_PG_MASK) != VPD_CP00_PG_N1_GOOD)
+ {
+ HWAS_INF("pTarget %.8X - N1 pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_target->getAttr<ATTR_HUID>(),
+ VPD_CP00_PG_N1_INDEX,
+ i_pgData[VPD_CP00_PG_N1_INDEX],
+ VPD_CP00_PG_N1_GOOD);
+ l_chipFunctional = false;
+ }
+ else
+ // Check all bits in N2 entry
+ if (i_pgData[VPD_CP00_PG_N2_INDEX] != VPD_CP00_PG_N2_GOOD)
+ {
+ HWAS_INF("pTarget %.8X - N2 pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_target->getAttr<ATTR_HUID>(),
+ VPD_CP00_PG_N2_INDEX,
+ i_pgData[VPD_CP00_PG_N2_INDEX],
+ VPD_CP00_PG_N2_GOOD);
+ l_chipFunctional = false;
+ }
+ else
+ // Check bits in N3 entry except those in partial good region
+ if ((i_pgData[VPD_CP00_PG_N3_INDEX] &
+ ~VPD_CP00_PG_N3_PG_MASK) != VPD_CP00_PG_N3_GOOD)
+ {
+ HWAS_INF("pTarget %.8X - N3 pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_target->getAttr<ATTR_HUID>(),
+ VPD_CP00_PG_N3_INDEX,
+ i_pgData[VPD_CP00_PG_N3_INDEX],
+ VPD_CP00_PG_N3_GOOD);
+ l_chipFunctional = false;
+ }
+ else
+ // Check bits in XBUS entry, validating pairs in partial good region
+ if (((i_pgData[VPD_CP00_PG_XBUS_INDEX] &
+ ~VPD_CP00_PG_XBUS_PG_MASK) != VPD_CP00_PG_XBUS_GOOD)
+ ||
+ (!areIoxPairsValid(i_pgData[VPD_CP00_PG_XBUS_INDEX])))
+ {
+ HWAS_INF("pTarget %.8X - XBUS pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_target->getAttr<ATTR_HUID>(),
+ VPD_CP00_PG_XBUS_INDEX,
+ i_pgData[VPD_CP00_PG_XBUS_INDEX],
+ VPD_CP00_PG_XBUS_GOOD);
+ l_chipFunctional = false;
+ }
+
+ return l_chipFunctional;
+} // isChipFunctional
+
+
+bool isDescFunctional(const TARGETING::TargetHandle_t &i_desc,
+ const uint16_t i_pgData[])
+{
+ bool l_descFunctional = true;
+
+ if (i_desc->getAttr<ATTR_TYPE>() == TYPE_XBUS)
+ {
+ ATTR_CHIP_UNIT_type indexXB =
+ i_desc->getAttr<ATTR_CHIP_UNIT>();
+ // Check pair of bits in XBUS entry
+ if ((i_pgData[VPD_CP00_PG_XBUS_INDEX] &
+ VPD_CP00_PG_XBUS_IOX_PAIR[indexXB]) != 0)
+ {
+ HWAS_INF("pDesc %.8X - XBUS%d pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(), indexXB,
+ VPD_CP00_PG_XBUS_INDEX,
+ i_pgData[VPD_CP00_PG_XBUS_INDEX],
+ (i_pgData[VPD_CP00_PG_XBUS_INDEX] &
+ ~VPD_CP00_PG_XBUS_IOX_PAIR[indexXB]));
+ l_descFunctional = false;
+ }
+ }
+ else
+ if (i_desc->getAttr<ATTR_TYPE>() == TYPE_OBUS)
+ {
+ ATTR_CHIP_UNIT_type indexOB =
+ i_desc->getAttr<ATTR_CHIP_UNIT>();
+ // Check all bits in OBUSx entry
+ if (i_pgData[VPD_CP00_PG_OB0_INDEX + indexOB] !=
+ VPD_CP00_PG_OBUS_GOOD)
+ {
+ HWAS_INF("pDesc %.8X - OB%d pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(), indexOB,
+ VPD_CP00_PG_OB0_INDEX + indexOB,
+ i_pgData[VPD_CP00_PG_OB0_INDEX + indexOB],
+ VPD_CP00_PG_OBUS_GOOD);
+ l_descFunctional = false;
+ }
+ else
+ // Check PBIOO0 bit in N1 entry
+ // @TODO RTC:134608 PBIOO0 seems to be good with Nimbus and Cumulus
+ // except Nimbus Sforza (without optics and NVLINK)
+ // so is it associated with all OBUS entries or just
+ // with OBUS0 and OBUS3 -- verify this
+ if ((i_pgData[VPD_CP00_PG_N1_INDEX] &
+ VPD_CP00_PG_N1_PBIOO0) != 0)
+ {
+ HWAS_INF("pDesc %.8X - OB%d pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(), indexOB,
+ VPD_CP00_PG_N1_INDEX,
+ i_pgData[VPD_CP00_PG_N1_INDEX],
+ (i_pgData[VPD_CP00_PG_N1_INDEX] &
+ ~VPD_CP00_PG_N1_PBIOO0));
+ l_descFunctional = false;
+ }
+ else
+ // Check PBIOO1 bit in N1 entry if second or third OBUS
+ // @TODO RTC:134608 PBIOO1 seems to be associated with OBUS1 and OBUS2
+ // which only are valid on a Cumulus -- verify this
+ if (((1 == indexOB) || (2 == indexOB)) &&
+ ((i_pgData[VPD_CP00_PG_N1_INDEX] &
+ VPD_CP00_PG_N1_PBIOO1) != 0))
+ {
+ HWAS_INF("pDesc %.8X - OB%d pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(), indexOB,
+ VPD_CP00_PG_N1_INDEX,
+ i_pgData[VPD_CP00_PG_N1_INDEX],
+ (i_pgData[VPD_CP00_PG_N1_INDEX] &
+ ~VPD_CP00_PG_N1_PBIOO1));
+ l_descFunctional = false;
+ }
+ }
+ else
+ if (i_desc->getAttr<ATTR_TYPE>() == TYPE_PEC)
+ {
+ ATTR_CHIP_UNIT_type indexPCI =
+ i_desc->getAttr<ATTR_CHIP_UNIT>();
+ // Check all bits in PCIx entry
+ if (i_pgData[VPD_CP00_PG_PCI0_INDEX + indexPCI] !=
+ VPD_CP00_PG_PCIx_GOOD[indexPCI])
+ {
+ HWAS_INF("pDesc %.8X - PCI%d pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(), indexPCI,
+ VPD_CP00_PG_PCI0_INDEX + indexPCI,
+ i_pgData[VPD_CP00_PG_PCI0_INDEX + indexPCI],
+ VPD_CP00_PG_PCIx_GOOD[indexPCI]);
+ l_descFunctional = false;
+ }
+ }
+ else
+ if (i_desc->getAttr<ATTR_TYPE>() == TYPE_EQ)
+ {
+ ATTR_CHIP_UNIT_type indexEP =
+ i_desc->getAttr<ATTR_CHIP_UNIT>();
+ // Check bits in EPx entry, validating triplets in partial good region
+ if (((i_pgData[VPD_CP00_PG_EP0_INDEX + indexEP]
+ & ~VPD_CP00_PG_EPx_PG_MASK) !=
+ VPD_CP00_PG_EPx_GOOD) ||
+ (!areL3L2REFRtripletsValid(i_pgData[VPD_CP00_PG_EP0_INDEX +
+ indexEP])))
+ {
+ HWAS_INF("pDesc %.8X - EQ%d pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(), indexEP,
+ VPD_CP00_PG_EP0_INDEX + indexEP,
+ i_pgData[VPD_CP00_PG_EP0_INDEX + indexEP],
+ VPD_CP00_PG_EPx_GOOD);
+ l_descFunctional = false;
+ }
+ }
+ else
+ if (i_desc->getAttr<ATTR_TYPE>() == TYPE_EX)
+ {
+ ATTR_CHIP_UNIT_type indexEX =
+ i_desc->getAttr<ATTR_CHIP_UNIT>();
+ // 2 EX chiplets per EP/EQ chiplet
+ size_t indexEP = indexEX / 2;
+ // 2 L3/L2/REFR triplets per EX chiplet
+ size_t indexL3L2REFR = indexEX % 2;
+ // Check triplet of bits in EPx entry
+ if ((i_pgData[VPD_CP00_PG_EP0_INDEX + indexEP] &
+ VPD_CP00_PG_EPx_L3L2REFR[indexL3L2REFR]) != 0)
+ {
+ HWAS_INF("pDesc %.8X - EX%d pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(), indexEX,
+ VPD_CP00_PG_EP0_INDEX + indexEP,
+ i_pgData[VPD_CP00_PG_EP0_INDEX + indexEP],
+ (i_pgData[VPD_CP00_PG_EP0_INDEX + indexEP] &
+ ~VPD_CP00_PG_EPx_L3L2REFR[indexL3L2REFR]));
+ l_descFunctional = false;
+ }
+ }
+ else
+ if (i_desc->getAttr<ATTR_TYPE>() == TYPE_CORE)
+ {
+ ATTR_CHIP_UNIT_type indexEC =
+ i_desc->getAttr<ATTR_CHIP_UNIT>();
+ // Check all bits in ECxx entry
+ if (i_pgData[VPD_CP00_PG_EC00_INDEX + indexEC] !=
+ VPD_CP00_PG_ECxx_GOOD)
+ {
+ HWAS_INF("pDesc %.8X - CORE/EC%2.2d pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(), indexEC,
+ VPD_CP00_PG_EC00_INDEX + indexEC,
+ i_pgData[VPD_CP00_PG_EC00_INDEX + indexEC],
+ VPD_CP00_PG_ECxx_GOOD);
+ l_descFunctional = false;
+ }
+ }
+ else
+ if (i_desc->getAttr<ATTR_TYPE>() == TYPE_MCBIST)
+ {
+ ATTR_CHIP_UNIT_type indexMCBIST =
+ i_desc->getAttr<ATTR_CHIP_UNIT>();
+ // 2 MCS chiplets per MCBIST / MCU
+ size_t indexMCS = indexMCBIST * 2;
+ // Check MCS01 bit in N3 entry if first MCBIST / MCU
+ if ((0 == indexMCBIST) &&
+ ((i_pgData[VPD_CP00_PG_N3_INDEX] &
+ VPD_CP00_PG_N3_MCS01) != 0))
+ {
+ HWAS_INF("pDesc %.8X - MCBIST%d pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(), indexMCBIST,
+ VPD_CP00_PG_N3_INDEX,
+ i_pgData[VPD_CP00_PG_N3_INDEX],
+ (i_pgData[VPD_CP00_PG_N3_INDEX] &
+ ~VPD_CP00_PG_N3_MCS01));
+ l_descFunctional = false;
+ }
+ else
+ // Check MCS23 bit in N1 entry if second MCBIST / MCU
+ if ((1 == indexMCBIST) &&
+ ((i_pgData[VPD_CP00_PG_N1_INDEX] &
+ VPD_CP00_PG_N1_MCS23) != 0))
+ {
+ HWAS_INF("pDesc %.8X - MCBIST%d pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(), indexMCBIST,
+ VPD_CP00_PG_N1_INDEX,
+ i_pgData[VPD_CP00_PG_N1_INDEX],
+ (i_pgData[VPD_CP00_PG_N1_INDEX] &
+ ~VPD_CP00_PG_N1_MCS23));
+ l_descFunctional = false;
+ }
+ else
+ // Check bits in MCxx entry except those in partial good region
+ if ((i_pgData[VPD_CP00_PG_MCxx_INDEX[indexMCS]]
+ & ~VPD_CP00_PG_MCxx_PG_MASK) !=
+ VPD_CP00_PG_MCxx_GOOD)
+ {
+ HWAS_INF("pDesc %.8X - MCBIST%d pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(), indexMCBIST,
+ VPD_CP00_PG_MCxx_INDEX[indexMCS],
+ i_pgData[VPD_CP00_PG_MCxx_INDEX[indexMCS]],
+ VPD_CP00_PG_MCxx_GOOD);
+ l_descFunctional = false;
+ }
+ }
+ else
+ if (i_desc->getAttr<ATTR_TYPE>() == TYPE_MCS)
+ {
+ ATTR_CHIP_UNIT_type indexMCS =
+ i_desc->getAttr<ATTR_CHIP_UNIT>();
+ // Check MCS01 bit in N3 entry if first or second MCS
+ if (((0 == indexMCS) || (1 == indexMCS)) &&
+ ((i_pgData[VPD_CP00_PG_N3_INDEX] &
+ VPD_CP00_PG_N3_MCS01) != 0))
+ {
+ HWAS_INF("pDesc %.8X - MCS%d pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(), indexMCS,
+ VPD_CP00_PG_N3_INDEX,
+ i_pgData[VPD_CP00_PG_N3_INDEX],
+ (i_pgData[VPD_CP00_PG_N3_INDEX] &
+ ~VPD_CP00_PG_N3_MCS01));
+ l_descFunctional = false;
+ }
+ else
+ // Check MCS23 bit in N1 entry if third or fourth MCS
+ if (((2 == indexMCS) || (3 == indexMCS)) &&
+ ((i_pgData[VPD_CP00_PG_N1_INDEX] &
+ VPD_CP00_PG_N1_MCS23) != 0))
+ {
+ HWAS_INF("pDesc %.8X - MCS%d pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(), indexMCS,
+ VPD_CP00_PG_N1_INDEX,
+ i_pgData[VPD_CP00_PG_N1_INDEX],
+ (i_pgData[VPD_CP00_PG_N1_INDEX] &
+ ~VPD_CP00_PG_N1_MCS23));
+ l_descFunctional = false;
+ }
+ else
+ // Check bits in MCxx entry including specific IOM bit,
+ // but not other bits in partial good region
+ if ((i_pgData[VPD_CP00_PG_MCxx_INDEX[indexMCS]]
+ & ~(VPD_CP00_PG_MCxx_PG_MASK
+ & ~VPD_CP00_PG_MCxx_IOMyy[indexMCS])) !=
+ VPD_CP00_PG_MCxx_GOOD)
+ {
+ HWAS_INF("pDesc %.8X - MCS%d pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(), indexMCS,
+ VPD_CP00_PG_MCxx_INDEX[indexMCS],
+ i_pgData[VPD_CP00_PG_MCxx_INDEX[indexMCS]],
+ (i_pgData[VPD_CP00_PG_MCxx_INDEX[indexMCS]] &
+ ~VPD_CP00_PG_MCxx_IOMyy[indexMCS]));
+ l_descFunctional = false;
+ }
+ }
+ else
+ if (i_desc->getAttr<ATTR_TYPE>() == TYPE_MCA)
+ {
+ ATTR_CHIP_UNIT_type indexMCA =
+ i_desc->getAttr<ATTR_CHIP_UNIT>();
+ // 2 MCA chiplets per MCS
+ size_t indexMCS = indexMCA / 2;
+ // Check IOM bit in MCxx entry
+ if ((i_pgData[VPD_CP00_PG_MCxx_INDEX[indexMCS]]
+ & VPD_CP00_PG_MCxx_IOMyy[indexMCS]) != 0)
+ {
+ HWAS_INF("pDesc %.8X - MCA%d pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(), indexMCA,
+ VPD_CP00_PG_MCxx_INDEX[indexMCS],
+ i_pgData[VPD_CP00_PG_MCxx_INDEX[indexMCS]],
+ (i_pgData[VPD_CP00_PG_MCxx_INDEX[indexMCS]] &
+ ~VPD_CP00_PG_MCxx_IOMyy[indexMCS]));
+ l_descFunctional = false;
+ }
+ }
+ else
+ if (i_desc->getAttr<ATTR_TYPE>() == TYPE_NVBUS)
+ {
+ // Check NPU bit in N3 entry
+ if ((i_pgData[VPD_CP00_PG_N3_INDEX] &
+ VPD_CP00_PG_N3_NPU) != 0)
+ {
+ HWAS_INF("pDesc %.8X - NVBUS pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(),
+ VPD_CP00_PG_N3_INDEX,
+ i_pgData[VPD_CP00_PG_N3_INDEX],
+ (i_pgData[VPD_CP00_PG_N3_INDEX] &
+ ~VPD_CP00_PG_N3_NPU));
+ l_descFunctional = false;
+ }
+ }
+ else
+ if (i_desc->getAttr<ATTR_TYPE>() == TYPE_PERV)
+ {
+ // Loop through PG entries from PRV entry to last used entry
+ for (uint8_t l_pgDataIndex =
+ VPD_CP00_PG_PERVASIVE_INDEX;
+ l_pgDataIndex <= VPD_CP00_PG_MAX_USED_INDEX;
+ ++l_pgDataIndex)
+ {
+ // Skip reserved entries between EP5 entry and EC00 entry
+ if ((l_pgDataIndex > VPD_CP00_PG_EP5_INDEX) &&
+ (l_pgDataIndex < VPD_CP00_PG_EC00_INDEX))
+ {
+ continue;
+ }
+
+ // Skip OB1 and OB2 entries on NIMBUS (region doesn't exist)
+ if ((i_desc->getAttr<ATTR_MODEL>() ==
+ MODEL_NIMBUS) &&
+ (l_pgDataIndex > VPD_CP00_PG_OB0_INDEX) &&
+ (l_pgDataIndex < VPD_CP00_PG_OB3_INDEX))
+ {
+ continue;
+ }
+
+ // Check PERV bit in the entry
+ if ((i_pgData[l_pgDataIndex]
+ & VPD_CP00_PG_xxx_PERV) != 0)
+ {
+ HWAS_INF("pDesc %.8X - PERV pgData[%d]: "
+ "actual 0x%04X, expected 0x%04X - bad",
+ i_desc->getAttr<ATTR_HUID>(),
+ l_pgDataIndex,
+ i_pgData[l_pgDataIndex],
+ (i_pgData[l_pgDataIndex] &
+ ~VPD_CP00_PG_xxx_PERV));
+ l_descFunctional = false;
+ break;
+ }
+ }
+ }
+
+ return l_descFunctional;
+} // isDescFunctional
+
+
+
errlHndl_t restrictEXunits(
std::vector <procRestrict_t> &i_procList,
const bool i_present,
@@ -998,7 +1417,7 @@ errlHndl_t checkMinimumHardware(const TARGETING::ConstTargetHandle_t i_nodeOrSys
if (l_dimms.empty())
{
HWAS_ERR( "Insufficient hardware to continue IPL (func DIMM)");
-
+
if(o_bootable)
{
*o_bootable = false;
diff --git a/src/usr/hwas/test/hwas1test.H b/src/usr/hwas/test/hwas1test.H
index f1d5cf2a2..cb102e3f3 100644
--- a/src/usr/hwas/test/hwas1test.H
+++ b/src/usr/hwas/test/hwas1test.H
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2011,2014 */
+/* Contributors Listed Below - COPYRIGHT 2011,2015 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -48,6 +50,75 @@
#include <hwas/common/hwas.H>
#include <hwas/common/hwasCommon.H>
#include <targeting/common/commontargeting.H>
+#include <targeting/common/utilFilter.H>
+
+
+// Buffer with all good data (CUMULUS chip)
+const uint16_t pgDataAllGood[HWAS::VPD_CP00_PG_DATA_ENTRIES] =
+ {(uint16_t)HWAS::VPD_CP00_PG_FSI_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_PERVASIVE_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_N0_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_N1_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_N2_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_N3_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_XBUS_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_MCxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_MCxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_OBUS_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_OBUS_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_OBUS_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_OBUS_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_PCIx_GOOD[0],
+ (uint16_t)HWAS::VPD_CP00_PG_PCIx_GOOD[1],
+ (uint16_t)HWAS::VPD_CP00_PG_PCIx_GOOD[2],
+ (uint16_t)HWAS::VPD_CP00_PG_EPx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_EPx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_EPx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_EPx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_EPx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_EPx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_ECxx_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD,
+ (uint16_t)HWAS::VPD_CP00_PG_RESERVED_GOOD};
class HWAS1test: public CxxTest::TestSuite
{
@@ -189,7 +260,7 @@ public:
Target* pSys;
targetService().getTopLevelTarget(pSys);
- uint8_t pgData[64];
+ uint8_t pgData[HWAS::VPD_CP00_PG_DATA_LENGTH];
l_errl = HWAS::platReadPartialGood(pSys, pgData);
@@ -207,6 +278,757 @@ public:
TS_TRACE( "testHWASplatReadPartialGood exit" );
}
+ /**
+ * @brief test isChipFunctional
+ */
+ void testHWASisChipFunctional()
+ {
+ using namespace HWAS;
+ using namespace TARGETING;
+
+ TS_TRACE( "testHWASisChipFunctional entry" );
+
+ // Get list of all targets with type PROC
+ TargetHandleList allProcs;
+ getAllChips( allProcs, TYPE_PROC, false );
+
+ for (TargetHandleList::const_iterator pTarget_it = allProcs.begin();
+ pTarget_it != allProcs.end();
+ ++pTarget_it
+ )
+ {
+ TargetHandle_t pTarget = *pTarget_it;
+ ATTR_MODEL_type l_model = pTarget->getAttr<ATTR_MODEL>();
+ uint16_t l_xbus = (MODEL_NIMBUS == l_model)
+ ? (uint16_t)(VPD_CP00_PG_XBUS_GOOD |
+ VPD_CP00_PG_XBUS_IOX_PAIR[0])
+ : (uint16_t)VPD_CP00_PG_XBUS_GOOD;
+ uint16_t l_obus12 = (MODEL_NIMBUS == l_model)
+ ? (uint16_t)VPD_CP00_PG_RESERVED_GOOD
+ : (uint16_t)VPD_CP00_PG_OBUS_GOOD;
+ uint16_t pgData[VPD_CP00_PG_DATA_ENTRIES];
+ memcpy(pgData,
+ pgDataAllGood,
+ VPD_CP00_PG_DATA_LENGTH);
+ pgData[VPD_CP00_PG_XBUS_INDEX] = l_xbus;
+ pgData[VPD_CP00_PG_OB0_INDEX + 1] = l_obus12;
+ pgData[VPD_CP00_PG_OB0_INDEX + 2] = l_obus12;
+ uint16_t l_mask = 0x8000;
+
+ TS_TRACE( "testHWASisChipFunctional: chip is functional");
+ if (!isChipFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisChipFunctional>"
+ "functional = 0x%x, should be true.",
+ isChipFunctional(pTarget, pgData));
+ }
+
+ TS_TRACE( "testHWASisChipFunctional: partial good all bad");
+ pgData[VPD_CP00_PG_N1_INDEX] |= VPD_CP00_PG_N1_PG_MASK;
+ pgData[VPD_CP00_PG_N3_INDEX] |= VPD_CP00_PG_N3_PG_MASK;
+ pgData[VPD_CP00_PG_XBUS_INDEX] |= VPD_CP00_PG_XBUS_PG_MASK;
+
+ if (!isChipFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisChipFunctional>"
+ "functional = 0x%x, should be true.",
+ isChipFunctional(pTarget, pgData));
+ }
+
+ pgData[VPD_CP00_PG_N1_INDEX] &= ~VPD_CP00_PG_N1_PG_MASK;
+ pgData[VPD_CP00_PG_N3_INDEX] &= ~VPD_CP00_PG_N3_PG_MASK;
+ pgData[VPD_CP00_PG_XBUS_INDEX] = l_xbus;
+
+ TS_TRACE( "testHWASisChipFunctional: FSI is not functional");
+ for (l_mask = 0x8000;
+ l_mask > 0;
+ l_mask >>= 1)
+ {
+ if (pgData[VPD_CP00_PG_FSI_INDEX] & l_mask)
+ {
+ // Turn off a bit that should be on
+ pgData[VPD_CP00_PG_FSI_INDEX] &= ~l_mask;
+ }
+ else
+ {
+ // Turn on a bit that should be off
+ pgData[VPD_CP00_PG_FSI_INDEX] |= l_mask;
+ }
+
+ if (isChipFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisChipFunctional>"
+ "functional = 0x%x, should be false.",
+ isChipFunctional(pTarget, pgData));
+ }
+
+ // Restore the "all good" data
+ pgData[VPD_CP00_PG_FSI_INDEX] =
+ (uint16_t)VPD_CP00_PG_FSI_GOOD;
+ }
+
+ TS_TRACE( "testHWASisChipFunctional: PRV is not functional");
+ for (l_mask = 0x8000;
+ l_mask > 0;
+ l_mask >>= 1)
+ {
+ if (pgData[VPD_CP00_PG_PERVASIVE_INDEX] & l_mask)
+ {
+ // Turn off a bit that should be on
+ pgData[VPD_CP00_PG_PERVASIVE_INDEX] &= ~l_mask;
+ }
+ else
+ {
+ // Turn on a bit that should be off
+ pgData[VPD_CP00_PG_PERVASIVE_INDEX] |= l_mask;
+ }
+
+ if (isChipFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisChipFunctional>"
+ "functional = 0x%x, should be false.",
+ isChipFunctional(pTarget, pgData));
+ }
+
+ // Restore the "all good" data
+ pgData[VPD_CP00_PG_PERVASIVE_INDEX] =
+ (uint16_t)VPD_CP00_PG_PERVASIVE_GOOD;
+ }
+
+ TS_TRACE( "testHWASisChipFunctional: N0 is not functional");
+ for (l_mask = 0x8000;
+ l_mask > 0;
+ l_mask >>= 1)
+ {
+ if (pgData[VPD_CP00_PG_N0_INDEX] & l_mask)
+ {
+ // Turn off a bit that should be on
+ pgData[VPD_CP00_PG_N0_INDEX] &= ~l_mask;
+ }
+ else
+ {
+ // Turn on a bit that should be off
+ pgData[VPD_CP00_PG_N0_INDEX] |= l_mask;
+ }
+
+ if (isChipFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisChipFunctional>"
+ "functional = 0x%x, should be false.",
+ isChipFunctional(pTarget, pgData));
+ }
+
+ // Restore the "all good" data
+ pgData[VPD_CP00_PG_N0_INDEX] =
+ (uint16_t)VPD_CP00_PG_N0_GOOD;
+ }
+
+ TS_TRACE( "testHWASisChipFunctional: N1 is not functional");
+ for (l_mask = 0x8000;
+ l_mask > 0;
+ l_mask >>= 1)
+ {
+ if ((uint16_t)VPD_CP00_PG_N1_PG_MASK & l_mask)
+ {
+ // Ignore partial good region
+ continue;
+ }
+ else
+ if (pgData[VPD_CP00_PG_N1_INDEX] & l_mask)
+ {
+ // Turn off a bit that should be on
+ pgData[VPD_CP00_PG_N1_INDEX] &= ~l_mask;
+ }
+ else
+ {
+ // Turn on a bit that should be off
+ pgData[VPD_CP00_PG_N1_INDEX] |= l_mask;
+ }
+
+ if (isChipFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisChipFunctional>"
+ "functional = 0x%x, should be false.",
+ isChipFunctional(pTarget, pgData));
+ }
+
+ // Restore the "all good" data
+ pgData[VPD_CP00_PG_N1_INDEX] =
+ (uint16_t)VPD_CP00_PG_N1_GOOD;
+ }
+
+ TS_TRACE( "testHWASisChipFunctional: N2 is not functional");
+ for (l_mask = 0x8000;
+ l_mask > 0;
+ l_mask >>= 1)
+ {
+ if (pgData[VPD_CP00_PG_N2_INDEX] & l_mask)
+ {
+ // Turn off a bit that should be on
+ pgData[VPD_CP00_PG_N2_INDEX] &= ~l_mask;
+ }
+ else
+ {
+ // Turn on a bit that should be off
+ pgData[VPD_CP00_PG_N2_INDEX] |= l_mask;
+ }
+
+ if (isChipFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisChipFunctional>"
+ "functional = 0x%x, should be false.",
+ isChipFunctional(pTarget, pgData));
+ }
+
+ // Restore the "all good" data
+ pgData[VPD_CP00_PG_N2_INDEX] =
+ (uint16_t)VPD_CP00_PG_N2_GOOD;
+ }
+
+ TS_TRACE( "testHWASisChipFunctional: N3 is not functional");
+ for (l_mask = 0x8000;
+ l_mask > 0;
+ l_mask >>= 1)
+ {
+ if ((uint16_t)VPD_CP00_PG_N3_PG_MASK & l_mask)
+ {
+ // Ignore partial good region
+ continue;
+ }
+ else
+ if (pgData[VPD_CP00_PG_N3_INDEX] & l_mask)
+ {
+ // Turn off a bit that should be on
+ pgData[VPD_CP00_PG_N3_INDEX] &= ~l_mask;
+ }
+ else
+ {
+ // Turn on a bit that should be off
+ pgData[VPD_CP00_PG_N3_INDEX] |= l_mask;
+ }
+
+ if (isChipFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisChipFunctional>"
+ "functional = 0x%x, should be false.",
+ isChipFunctional(pTarget, pgData));
+ }
+
+ // Restore the "all good" data
+ pgData[VPD_CP00_PG_N3_INDEX] =
+ (uint16_t)VPD_CP00_PG_N3_GOOD;
+ }
+
+ TS_TRACE( "testHWASisChipFunctional: XBUS is not functional");
+ for (l_mask = 0x8000;
+ l_mask > 0;
+ l_mask >>= 1)
+ {
+ // NOTE: Single bits of XBUS matched pairs will be turned
+ // on or off individually while going through loop,
+ // thus creating and testing mismatched pairs.
+ if (pgData[VPD_CP00_PG_XBUS_INDEX] & l_mask)
+ {
+ // Turn off a bit that should be on
+ pgData[VPD_CP00_PG_XBUS_INDEX] &= ~l_mask;
+ }
+ else
+ {
+ // Turn on a bit that should be off
+ pgData[VPD_CP00_PG_XBUS_INDEX] |= l_mask;
+ }
+
+ if (isChipFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisChipFunctional>"
+ "functional = 0x%x, should be false.",
+ isChipFunctional(pTarget, pgData));
+ }
+
+ // Restore the "all good" data
+ pgData[VPD_CP00_PG_XBUS_INDEX] = l_xbus;
+ }
+ }
+
+ TS_TRACE( "testHWASisChipFunctional exit" );
+ }
+
+ /**
+ * @brief test isDescFunctional
+ */
+ void testHWASisDescFunctional()
+ {
+ using namespace HWAS;
+ using namespace TARGETING;
+
+ // Get list of present targets with type PROC
+ TargetHandleList pCheckPres;
+ getAllChips( pCheckPres, TYPE_PROC, true );
+
+ for (TargetHandleList::const_iterator pTarget_it = pCheckPres.begin();
+ pTarget_it != pCheckPres.end();
+ ++pTarget_it
+ )
+ {
+ TargetHandle_t pTarget = *pTarget_it;
+ ATTR_MODEL_type l_model = pTarget->getAttr<ATTR_MODEL>();
+ uint16_t l_xbus = (MODEL_NIMBUS == l_model)
+ ? (uint16_t)(VPD_CP00_PG_XBUS_GOOD |
+ VPD_CP00_PG_XBUS_IOX_PAIR[0])
+ : (uint16_t)VPD_CP00_PG_XBUS_GOOD;
+ uint16_t l_obus12 = (MODEL_NIMBUS == l_model)
+ ? (uint16_t)VPD_CP00_PG_RESERVED_GOOD
+ : (uint16_t)VPD_CP00_PG_OBUS_GOOD;
+ uint16_t pgData[VPD_CP00_PG_DATA_ENTRIES];
+ memcpy(pgData,
+ pgDataAllGood,
+ VPD_CP00_PG_DATA_LENGTH);
+ uint16_t l_mask = 0x8000;
+ uint32_t l_index = VPD_CP00_PG_PERVASIVE_INDEX;
+
+ TargetHandleList pDescList;
+ targetService().getAssociated( pDescList, pTarget,
+ TargetService::CHILD, TargetService::ALL);
+ for (TargetHandleList::const_iterator pDesc_it = pDescList.begin();
+ pDesc_it != pDescList.end();
+ ++pDesc_it)
+ {
+ TargetHandle_t pDesc = *pDesc_it;
+ ATTR_TYPE_type l_type = pDesc->getAttr<ATTR_TYPE>();
+ ATTR_CHIP_UNIT_type l_chipUnit =
+ pDesc->getAttr<ATTR_CHIP_UNIT>();
+
+ TS_TRACE( "testHWASisDescFunctional: descendant functional");
+ if (!isDescFunctional(pDesc, pgData))
+ {
+ TS_FAIL("testHWASisDescFunctional>"
+ "functional = 0x%x, should be true.",
+ isDescFunctional(pTarget, pgData));
+ }
+
+ if ((TYPE_XBUS == l_type) && (0 == l_chipUnit))
+ {
+ pgData[VPD_CP00_PG_XBUS_INDEX] = l_xbus;
+ }
+
+ if ((TYPE_OBUS == l_type) &&
+ ((1 == l_chipUnit) || (2 == l_chipUnit)))
+ {
+ pgData[VPD_CP00_PG_OB0_INDEX + l_chipUnit] = l_obus12;
+ }
+
+ switch(l_type)
+ {
+ case TYPE_XBUS:
+ TS_TRACE( "testHWASisDescFunctional: "
+ "XBUS%d is not functional", l_chipUnit);
+ pgData[VPD_CP00_PG_XBUS_INDEX] |=
+ (uint16_t)VPD_CP00_PG_XBUS_IOX_PAIR[l_chipUnit];
+
+ if (isDescFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisDescFunctional>"
+ "functional = 0x%x, should be false.",
+ isDescFunctional(pTarget, pgData));
+ }
+
+ pgData[VPD_CP00_PG_XBUS_INDEX] = l_xbus;
+ break;
+
+ case TYPE_OBUS:
+ TS_TRACE( "testHWASisDescFunctional: "
+ "OBUS%d is not functional", l_chipUnit);
+ if ((1 == l_chipUnit) || (2 == l_chipUnit))
+ {
+ pgData[VPD_CP00_PG_N1_INDEX] |=
+ (uint16_t)VPD_CP00_PG_N1_PBIOO0;
+ }
+ else
+ {
+ pgData[VPD_CP00_PG_N1_INDEX] |=
+ (uint16_t)VPD_CP00_PG_N1_PBIOO1;
+ }
+
+ if (isDescFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisDescFunctional>"
+ "functional = 0x%x, should be false.",
+ isDescFunctional(pTarget, pgData));
+ }
+
+ pgData[VPD_CP00_PG_N1_INDEX] =
+ (uint16_t)VPD_CP00_PG_N1_GOOD;
+
+ for (l_mask = 0x8000;
+ l_mask > 0;
+ l_mask >>= 1)
+ {
+ if (pgData[VPD_CP00_PG_OB0_INDEX + l_chipUnit] &
+ l_mask)
+ {
+ // Turn off a bit that should be on
+ pgData[VPD_CP00_PG_OB0_INDEX + l_chipUnit] &=
+ ~l_mask;
+ }
+ else
+ {
+ // Turn on a bit that should be off
+ pgData[VPD_CP00_PG_OB0_INDEX + l_chipUnit] |=
+ l_mask;
+ }
+
+ if (isDescFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisDescFunctional>"
+ "functional = 0x%x, should be false.",
+ isDescFunctional(pTarget, pgData));
+ }
+
+ // Restore the "all good" data
+ pgData[VPD_CP00_PG_OB0_INDEX + l_chipUnit]
+ = ((1 == l_chipUnit) || (2 == l_chipUnit))
+ ? l_obus12
+ : (uint16_t)VPD_CP00_PG_OBUS_GOOD;
+ }
+ break;
+
+ case TYPE_PEC:
+ TS_TRACE( "testHWASisDescFunctional: "
+ "PCI%d is not functional", l_chipUnit);
+ for (l_mask = 0x8000;
+ l_mask > 0;
+ l_mask >>= 1)
+ {
+ if (pgData[VPD_CP00_PG_PCI0_INDEX + l_chipUnit] &
+ l_mask)
+ {
+ // Turn off a bit that should be on
+ pgData[VPD_CP00_PG_PCI0_INDEX + l_chipUnit] &=
+ ~l_mask;
+ }
+ else
+ {
+ // Turn on a bit that should be off
+ pgData[VPD_CP00_PG_PCI0_INDEX + l_chipUnit] |=
+ l_mask;
+ }
+
+ if (isDescFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisDescFunctional>"
+ "functional = 0x%x, should be false.",
+ isDescFunctional(pTarget, pgData));
+ }
+
+ // Restore the "all good" data
+ pgData[VPD_CP00_PG_PCI0_INDEX + l_chipUnit] =
+ (uint16_t)VPD_CP00_PG_PCIx_GOOD[l_chipUnit];
+ }
+ break;
+
+ case TYPE_EQ:
+ TS_TRACE( "testHWASisDescFunctional: "
+ "EQ%d is not functional", l_chipUnit);
+ for (l_mask = 0x8000;
+ l_mask > 0;
+ l_mask >>= 1)
+ {
+ // NOTE: Single bits of L2 / L3 matched pairs will
+ // be turned on or off individually while
+ // going through loop, thus creating and
+ // testing mismatched pairs.
+ if (pgData[VPD_CP00_PG_EP0_INDEX + l_chipUnit] &
+ l_mask)
+ {
+ // Turn off a bit that should be on
+ pgData[VPD_CP00_PG_EP0_INDEX + l_chipUnit] &=
+ ~l_mask;
+ }
+ else
+ {
+ // Turn on a bit that should be off
+ pgData[VPD_CP00_PG_EP0_INDEX + l_chipUnit] |=
+ l_mask;
+ }
+
+ if (isDescFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisDescFunctional>"
+ "functional = 0x%x, should be false.",
+ isDescFunctional(pTarget, pgData));
+ }
+
+ // Restore the "all good" data
+ pgData[VPD_CP00_PG_EP0_INDEX + l_chipUnit] =
+ (uint16_t)VPD_CP00_PG_EPx_GOOD;
+ }
+ break;
+
+ case TYPE_EX:
+ TS_TRACE( "testHWASisDescFunctional: "
+ "EX%d is not functional", l_chipUnit);
+ pgData[VPD_CP00_PG_EP0_INDEX + (l_chipUnit / 2)] |=
+ (uint16_t)VPD_CP00_PG_EPx_L3L2REFR[l_chipUnit % 2];
+
+ if (isDescFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisDescFunctional>"
+ "functional = 0x%x, should be false.",
+ isDescFunctional(pTarget, pgData));
+ }
+
+ pgData[VPD_CP00_PG_EP0_INDEX + (l_chipUnit / 2)] =
+ (uint16_t)VPD_CP00_PG_EPx_GOOD;
+ break;
+
+ case TYPE_CORE:
+ TS_TRACE( "testHWASisDescFunctional: "
+ "CORE%d is not functional", l_chipUnit);
+ for (l_mask = 0x8000;
+ l_mask > 0;
+ l_mask >>= 1)
+ {
+ if (pgData[VPD_CP00_PG_EC00_INDEX + l_chipUnit] &
+ l_mask)
+ {
+ // Turn off a bit that should be on
+ pgData[VPD_CP00_PG_EC00_INDEX + l_chipUnit] &=
+ ~l_mask;
+ }
+ else
+ {
+ // Turn on a bit that should be off
+ pgData[VPD_CP00_PG_EC00_INDEX + l_chipUnit] |=
+ l_mask;
+ }
+
+ if (isDescFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisDescFunctional>"
+ "functional = 0x%x, should be false.",
+ isDescFunctional(pTarget, pgData));
+ }
+
+ // Restore the "all good" data
+ pgData[VPD_CP00_PG_EC00_INDEX + l_chipUnit] =
+ VPD_CP00_PG_ECxx_GOOD;
+ }
+ break;
+
+ case TYPE_MCBIST:
+ TS_TRACE( "testHWASisDescFunctional: "
+ "MCBIST%d is not functional", l_chipUnit);
+ if (l_chipUnit)
+ {
+ pgData[VPD_CP00_PG_N1_INDEX] |=
+ (uint16_t)VPD_CP00_PG_N1_MCS23;
+ }
+ else
+ {
+ pgData[VPD_CP00_PG_N3_INDEX] |=
+ (uint16_t)VPD_CP00_PG_N3_MCS01;
+ }
+
+ if (isDescFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisDescFunctional>"
+ "functional = 0x%x, should be false.",
+ isDescFunctional(pTarget, pgData));
+ }
+
+ if (l_chipUnit)
+ {
+ pgData[VPD_CP00_PG_N1_INDEX] =
+ (uint16_t)VPD_CP00_PG_N1_GOOD;
+ }
+ else
+ {
+ pgData[VPD_CP00_PG_N3_INDEX] =
+ (uint16_t)VPD_CP00_PG_N3_GOOD;
+ }
+
+ for (l_mask = 0x8000;
+ l_mask > 0;
+ l_mask >>= 1)
+ {
+ if ((uint16_t)VPD_CP00_PG_MCxx_PG_MASK & l_mask)
+ {
+ // Ignore partial good region
+ continue;
+ }
+ else
+ if (pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit * 2]]
+ & l_mask)
+ {
+ // Turn off a bit that should be on
+ pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit * 2]]
+ &= ~l_mask;
+ }
+ else
+ {
+ // Turn on a bit that should be off
+ pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit * 2]]
+ |= l_mask;
+ }
+
+ if (isDescFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisDescFunctional>"
+ "functional = 0x%x, should be false.",
+ isDescFunctional(pTarget, pgData));
+ }
+
+ // Restore the "all good" data
+ pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit * 2]] =
+ (uint16_t)VPD_CP00_PG_MCxx_GOOD;
+ }
+ break;
+
+ case TYPE_MCS:
+ TS_TRACE( "testHWASisDescFunctional: "
+ "MCS%d is not functional", l_chipUnit);
+ if (l_chipUnit >= 2)
+ {
+ pgData[VPD_CP00_PG_N1_INDEX] |=
+ (uint16_t)VPD_CP00_PG_N1_MCS23;
+ }
+ else
+ {
+ pgData[VPD_CP00_PG_N3_INDEX] |=
+ (uint16_t)VPD_CP00_PG_N3_MCS01;
+ }
+
+ if (isDescFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisDescFunctional>"
+ "functional = 0x%x, should be false.",
+ isDescFunctional(pTarget, pgData));
+ }
+
+ if (l_chipUnit >= 2)
+ {
+ pgData[VPD_CP00_PG_N1_INDEX] =
+ (uint16_t)VPD_CP00_PG_N1_GOOD;
+ }
+ else
+ {
+ pgData[VPD_CP00_PG_N3_INDEX] =
+ (uint16_t)VPD_CP00_PG_N3_GOOD;
+ }
+
+ for (l_mask = 0x8000;
+ l_mask > 0;
+ l_mask >>= 1)
+ {
+ if ((uint16_t)(VPD_CP00_PG_MCxx_PG_MASK &
+ ~VPD_CP00_PG_MCxx_IOMyy[l_chipUnit]) & l_mask)
+ {
+ // Ignore partial good region
+ continue;
+ }
+ else
+ if (pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit]] &
+ l_mask)
+ {
+ // Turn off a bit that should be on
+ pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit]] &=
+ ~l_mask;
+ }
+ else
+ {
+ // Turn on a bit that should be off
+ pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit]] |=
+ l_mask;
+ }
+
+ if (isDescFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisDescFunctional>"
+ "functional = 0x%x, should be false.",
+ isDescFunctional(pTarget, pgData));
+ }
+
+ // Restore the "all good" data
+ pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit]] =
+ (uint16_t)VPD_CP00_PG_MCxx_GOOD;
+ }
+ break;
+
+ case TYPE_MCA:
+ TS_TRACE( "testHWASisDescFunctional: "
+ "MCA%d is not functional", l_chipUnit);
+ pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit / 2]] |=
+ (uint16_t)VPD_CP00_PG_MCxx_IOMyy[l_chipUnit / 2];
+
+ if (isDescFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisDescFunctional>"
+ "functional = 0x%x, should be false.",
+ isDescFunctional(pTarget, pgData));
+ }
+
+ pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit / 2]] =
+ (uint16_t)VPD_CP00_PG_MCxx_GOOD;
+ break;
+
+ case TYPE_NVBUS:
+ TS_TRACE( "testHWASisDescFunctional: "
+ "NVBUS is not functional");
+ pgData[VPD_CP00_PG_N3_INDEX] |=
+ (uint16_t)VPD_CP00_PG_N3_NPU;
+
+ if (isDescFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisDescFunctional>"
+ "functional = 0x%x, should be false.",
+ isDescFunctional(pTarget, pgData));
+ }
+
+ pgData[VPD_CP00_PG_N3_INDEX] =
+ (uint16_t)VPD_CP00_PG_N3_GOOD;
+ break;
+
+ case TYPE_PERV:
+ TS_TRACE( "testHWASisDescFunctional: "
+ "PERV is not functional");
+ for (l_index = VPD_CP00_PG_PERVASIVE_INDEX;
+ l_index < VPD_CP00_PG_DATA_ENTRIES;
+ l_index++)
+ {
+ if (pgData[l_index] &
+ (uint16_t)VPD_CP00_PG_xxx_PERV)
+ {
+ // Ignore chiplet lines where PERV is "1"
+ continue;
+ }
+ else
+ {
+ // Turn on PERV bit that should be off / good
+ pgData[l_index] |=
+ (uint16_t)VPD_CP00_PG_xxx_PERV;
+ }
+
+ if (isDescFunctional(pTarget, pgData))
+ {
+ TS_FAIL("testHWASisDescFunctional>"
+ "functional = 0x%x, should be false.",
+ isDescFunctional(pTarget, pgData));
+ }
+
+ // Restore the "all good" data
+ pgData[l_index] &= ~VPD_CP00_PG_xxx_PERV;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } // for pDesc_it
+ } // for pTarget_it
+
+ TS_TRACE( "testHWASisDescFunctional exit" );
+ }
+
};
#endif //
diff --git a/src/usr/hwas/test/hwasGardTest.H b/src/usr/hwas/test/hwasGardTest.H
index 5576a289b..f25a67ee3 100644
--- a/src/usr/hwas/test/hwasGardTest.H
+++ b/src/usr/hwas/test/hwasGardTest.H
@@ -46,7 +46,7 @@
using namespace HWAS;
using namespace TARGETING;
-bool compareAffinity(const TargetInfo t1, const TargetInfo t2)
+bool compareAffinityCXX(const TargetInfo t1, const TargetInfo t2)
{
return t1.affinityPath < t2.affinityPath;
}
@@ -3434,7 +3434,7 @@ public:
// Check result
std::sort(l_targToDeconfig.begin(), l_targToDeconfig.end(),
- compareAffinity);
+ compareAffinityCXX);
if ((l_targToDeconfig.size() == 4) &&
(l_targToDeconfig[0].affinityPath == l_ep[0]) &&
(l_targToDeconfig[1].affinityPath == l_ep[1]) &&
@@ -3517,7 +3517,7 @@ public:
// Check result
std::sort(l_targToDeconfig.begin(), l_targToDeconfig.end(),
- compareAffinity);
+ compareAffinityCXX);
if ((l_targToDeconfig.size() == 1) &&
(l_targToDeconfig[0].affinityPath == l_ep[0]) )
{
@@ -3615,7 +3615,7 @@ public:
// Check result
std::sort(l_targToDeconfig.begin(), l_targToDeconfig.end(),
- compareAffinity);
+ compareAffinityCXX);
if ((l_targToDeconfig.size() == 3) &&
(l_targToDeconfig[0].affinityPath == l_ep[4]) && // 10 MEMBUF
(l_targToDeconfig[1].affinityPath == l_ep[3]) && // 100 MBA
@@ -3673,7 +3673,7 @@ public:
// Check result
std::sort(l_targToDeconfig.begin(), l_targToDeconfig.end(),
- compareAffinity);
+ compareAffinityCXX);
if ((l_targToDeconfig.size() == 2) &&
(l_targToDeconfig[0].affinityPath == l_ep[0]) && // 0 MCS
(l_targToDeconfig[1].affinityPath == l_ep[1]) ) // 00 MEMBUF
@@ -3732,7 +3732,7 @@ public:
// Check result
std::sort(l_targToDeconfig.begin(), l_targToDeconfig.end(),
- compareAffinity);
+ compareAffinityCXX);
if ((l_targToDeconfig.size() == 2) &&
(l_targToDeconfig[0].affinityPath == l_ep[0]) && // 00 MEMBUF
(l_targToDeconfig[1].affinityPath == l_ep[1]) ) // 000 MBA
@@ -3793,7 +3793,7 @@ public:
// Check result
std::sort(l_targToDeconfig.begin(), l_targToDeconfig.end(),
- compareAffinity);
+ compareAffinityCXX);
if ((l_targToDeconfig.size() == 2) &&
(l_targToDeconfig[0].affinityPath == l_ep[0]) && // 000 MBA
(l_targToDeconfig[1].affinityPath == l_ep[1]) ) // 0000 DIMM
@@ -3874,7 +3874,7 @@ public:
// Check result
std::sort(l_targToDeconfig.begin(), l_targToDeconfig.end(),
- compareAffinity);
+ compareAffinityCXX);
if ((l_targToDeconfig.size() == 1) &&
(l_targToDeconfig[0].affinityPath == l_ep[4]) ) // 001 MBA
{
@@ -3991,7 +3991,7 @@ public:
// Check result
std::sort(l_targToDeconfig.begin(), l_targToDeconfig.end(),
- compareAffinity);
+ compareAffinityCXX);
if ((l_targToDeconfig.size() == 6) &&
(l_targToDeconfig[0].affinityPath == l_ep[0]) && // 0 MCS
(l_targToDeconfig[1].affinityPath == l_ep[1]) && // 00 MEMBUF
@@ -4089,7 +4089,7 @@ public:
// Check result
std::sort(l_targToDeconfig.begin(), l_targToDeconfig.end(),
- compareAffinity);
+ compareAffinityCXX);
if ((l_targToDeconfig.size() == 6) &&
(l_targToDeconfig[0].affinityPath == l_ep[0]) &&
(l_targToDeconfig[1].affinityPath == l_ep[1]) &&
OpenPOWER on IntegriCloud