diff options
author | Marty Gloff <mgloff@us.ibm.com> | 2015-06-10 15:23:20 -0500 |
---|---|---|
committer | Patrick Williams <iawillia@us.ibm.com> | 2015-12-11 13:56:27 -0600 |
commit | 9627b4c4bc588981f2d9c76d6fc36b03ee26c800 (patch) | |
tree | f8beb54f7d708dff60a0abcdeec2ea7fa4c5a90d /src/usr | |
parent | 5d33811c6f265463f502c19dd2a3173e1bbc38bc (diff) | |
download | talos-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.C | 645 | ||||
-rw-r--r-- | src/usr/hwas/test/hwas1test.H | 826 | ||||
-rw-r--r-- | src/usr/hwas/test/hwasGardTest.H | 20 |
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]) && |