Пример #1
0
/**
 * @brief Enable and disable special wakeup for SCOM operations
 *   FSP:  Call the Host interface wakeup function for all core
 *         targets under the specified target, HOST wakeup bit is used
 *   BMC:  Call the wakeup HWP for the target type specified (EQ/EX/CORE),
 *         Proc type calls the HWP for all cores, FSP wakeup bit is used
 */
errlHndl_t handleSpecialWakeup(TARGETING::Target* i_target, bool i_enable)
{
    errlHndl_t l_errl = NULL;

    TARGETING::TYPE l_type = i_target->getAttr<TARGETING::ATTR_TYPE>();

    // FSP
    if(INITSERVICE::spBaseServicesEnabled())
    {
        // Check for valid interface function
        if( g_hostInterfaces == NULL ||
            g_hostInterfaces->wakeup == NULL )
        {
            TRACFCOMP( g_trac_scom,
                       ERR_MRK"Hypervisor wakeup interface not linked");

            /*@
             * @errortype
             * @moduleid     SCOM_HANDLE_SPECIAL_WAKEUP
             * @reasoncode   SCOM_RUNTIME_INTERFACE_ERR
             * @userdata1    Target HUID
             * @userdata2    Wakeup Enable
             * @devdesc      Wakeup runtime interface not linked.
             */
            l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_INFORMATIONAL,
                                             SCOM_HANDLE_SPECIAL_WAKEUP,
                                             SCOM_RUNTIME_INTERFACE_ERR,
                                             get_huid(i_target),
                                             i_enable);

            l_errl->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
                                        HWAS::SRCI_PRIORITY_HIGH);

            return l_errl;
        }

        TargetHandleList pCoreList;

        // If the target is already a core just push it on the list
        if(l_type == TARGETING::TYPE_CORE)
        {
            pCoreList.clear();
            pCoreList.push_back(i_target);
        }
        else
        {
            getChildChiplets( pCoreList, i_target, TARGETING::TYPE_CORE );
        }

        // Call wakeup on all core targets
        // Wakeup may be called twice for fused cores
        for ( auto pCore_it = pCoreList.begin();
              pCore_it != pCoreList.end();
              ++pCore_it )
        {
            // Runtime target id
            RT_TARG::rtChipId_t rtTargetId = 0;
            l_errl = RT_TARG::getRtTarget(*pCore_it, rtTargetId);
            if(l_errl)
            {
                break;
            }

            uint32_t mode;
            if(i_enable)
            {
                mode = HBRT_WKUP_FORCE_AWAKE;
            }
            else
            {
                mode = HBRT_WKUP_CLEAR_FORCE;
            }

            // Do the special wakeup
            int l_rc = g_hostInterfaces->wakeup(rtTargetId,mode);

            if(l_rc)
            {
                TRACFCOMP( g_trac_scom,ERR_MRK
                    "Hypervisor wakeup failed. "
                    "rc 0x%X target_huid 0x%llX rt_target_id 0x%llX mode %d",
                    l_rc, get_huid(*pCore_it), rtTargetId, mode );

                // convert rc to error log
                /*@
                 * @errortype
                 * @moduleid         SCOM_HANDLE_SPECIAL_WAKEUP
                 * @reasoncode       SCOM_RUNTIME_WAKEUP_ERR
                 * @userdata1        Hypervisor return code
                 * @userdata2[0:31]  Runtime Target ID
                 * @userdata2[32:63] Wakeup Mode
                 * @devdesc          Hypervisor wakeup failed.
                 */
                l_errl = new ERRORLOG::ErrlEntry(
                                            ERRORLOG::ERRL_SEV_INFORMATIONAL,
                                            SCOM_HANDLE_SPECIAL_WAKEUP,
                                            SCOM_RUNTIME_WAKEUP_ERR,
                                            l_rc,
                                            TWO_UINT32_TO_UINT64(
                                                        rtTargetId, mode));

                l_errl->addHwCallout(i_target,
                                     HWAS::SRCI_PRIORITY_LOW,
                                     HWAS::NO_DECONFIG,
                                     HWAS::GARD_NULL);

                break;
            }
        }
    }

    // BMC
    else
    {
        if(l_type == TARGETING::TYPE_PROC)
        {
            // Call wakeup on all core targets
            TargetHandleList pCoreList;
            getChildChiplets( pCoreList, i_target, TARGETING::TYPE_CORE );

            for ( auto pCore_it = pCoreList.begin();
                  pCore_it != pCoreList.end();
                  ++pCore_it )
            {
                // To simplify, just call recursively with the core target
                l_errl = handleSpecialWakeup(*pCore_it, i_enable);
                if(l_errl)
                {
                    break;
                }
            }
            return l_errl;
        }

        // Need to handle multiple calls to enable special wakeup
        // Count attribute will keep track and disable when zero
        // Assume HBRT is single-threaded, so no issues with concurrency
        uint32_t l_count = (i_target)->getAttr<ATTR_SPCWKUP_COUNT>();

        if((l_count==0) && !i_enable)
        {
            TRACFCOMP( g_trac_scom,ERR_MRK
                "Disabling special wakeup on target with SPCWKUP_COUNT=0");

            /*@
             * @errortype
             * @moduleid         SCOM_HANDLE_SPECIAL_WAKEUP
             * @reasoncode       SCOM_RUNTIME_SPCWKUP_COUNT_ERR
             * @userdata1        Target HUID
             * @userdata2[0:31]  Wakeup Enable
             * @userdata2[32:63] Wakeup Count
             * @devdesc          Disabling special wakeup when not enabled.
             */
            l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_INFORMATIONAL,
                                             SCOM_HANDLE_SPECIAL_WAKEUP,
                                             SCOM_RUNTIME_SPCWKUP_COUNT_ERR,
                                             get_huid(i_target),
                                             TWO_UINT32_TO_UINT64(
                                                        i_enable, l_count));

            l_errl->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
                                        HWAS::SRCI_PRIORITY_LOW);

            errlCommit( l_errl, RUNTIME_COMP_ID );
        }

        // Only call the HWP if 0-->1 or 1-->0
        if( ((l_count==0) &&  i_enable) ||
            ((l_count==1) && !i_enable) )
        {
            // NOTE Regarding the entity type passed to the HWP:
            // There are 3 independent registers used to trigger a
            // special wakeup (FSP,HOST,OCC), we are using the FSP
            // bit because HOST/OCC are already in use.

            p9specialWakeup::PROC_SPCWKUP_OPS l_spcwkupType;
            if(i_enable)
            {
                l_spcwkupType = p9specialWakeup::SPCWKUP_ENABLE;
            }
            else
            {
                l_spcwkupType = p9specialWakeup::SPCWKUP_DISABLE;
            }

            if(l_type == TARGETING::TYPE_EQ)
            {
                fapi2::Target<fapi2::TARGET_TYPE_EQ>
                    l_fapi_target(const_cast<TARGETING::Target*>(i_target));

                FAPI_INVOKE_HWP( l_errl,
                                p9_cpu_special_wakeup_eq,
                                l_fapi_target,
                                l_spcwkupType,
                                p9specialWakeup::FSP );
            }
            else if(l_type == TARGETING::TYPE_EX)
            {
                fapi2::Target<fapi2::TARGET_TYPE_EX_CHIPLET>
                    l_fapi_target(const_cast<TARGETING::Target*>(i_target));

                FAPI_INVOKE_HWP( l_errl,
                                p9_cpu_special_wakeup_ex,
                                l_fapi_target,
                                l_spcwkupType,
                                p9specialWakeup::FSP );
            }
            else if(l_type == TARGETING::TYPE_CORE)
            {
                fapi2::Target<fapi2::TARGET_TYPE_CORE>
                    l_fapi_target(const_cast<TARGETING::Target*>(i_target));

                FAPI_INVOKE_HWP( l_errl,
                                p9_cpu_special_wakeup_core,
                                l_fapi_target,
                                l_spcwkupType,
                                p9specialWakeup::FSP );
            }

            if(l_errl)
            {
                TRACFCOMP( g_trac_scom,
                        "p9_cpu_special_wakeup ERROR :"
                        " Returning errorlog, reason=0x%x",
                        l_errl->reasonCode() );

                // Capture the target data in the elog
                ERRORLOG::ErrlUserDetailsTarget(i_target).addToLog( l_errl );
            }
        }

        // Update the counter
        if(!l_errl)
        {
            if(i_enable)
            {
                l_count++;
            }
            else
            {
                l_count--;
            }
            i_target->setAttr<ATTR_SPCWKUP_COUNT>(l_count);
        }
    }

    return l_errl;
}
Пример #2
0
/** @func GetCheckstopInfo
 *  To be called from the fabric domain to gather Checkstop information.  This
 *  information is used in a sorting algorithm.
 *
 *  This is a plugin function: GetCheckstopInfo
 *
 *  @param i_chip - The chip.
 *  @param o_wasInternal - True if this chip has an internal checkstop.
 *  @param o_externalChips - List of external fabrics driving checkstop.
 *  @param o_wofValue - Current WOF value (unused for now).
 */
int32_t GetCheckstopInfo( ExtensibleChip * i_chip,
                          bool & o_wasInternal,
                          TargetHandleList & o_externalChips,
                          uint64_t & o_wofValue )
{
    // Clear parameters.
    o_wasInternal = false;
    o_externalChips.clear();
    o_wofValue = 0;

    SCAN_COMM_REGISTER_CLASS * l_globalFir =
      i_chip->getRegister("GLOBAL_CS_FIR");

    SCAN_COMM_REGISTER_CLASS * l_pbXstpFir =
      i_chip->getRegister("N3_CHIPLET_CS_FIR");

    SCAN_COMM_REGISTER_CLASS * l_extXstpFir =
      i_chip->getRegister("PBEXTFIR");

    int32_t o_rc = SUCCESS;
    o_rc |= l_globalFir->Read();
    o_rc |= l_pbXstpFir->Read();
    o_rc |= l_extXstpFir->Read();

    if(o_rc)
    {
        PRDF_ERR( "[GetCheckstopInfo] SCOM fail on 0x%08x rc=%x",
                  i_chip->GetId(), o_rc);
        return o_rc;
    }

    uint8_t l_connectedXstps = l_extXstpFir->GetBitFieldJustified(0,7);

    bool pbXstpFromOtherChip = l_pbXstpFir->IsBitSet(2);

    if ((0 != l_globalFir->GetBitFieldJustified(0,56)) &&
        (!l_globalFir->IsBitSet(5) || !pbXstpFromOtherChip))
        o_wasInternal = true;

    // Get connected chips.
    uint32_t l_positions[] =
    {
        0, // bit 0 - XBUS 0
        1, // bit 1 - XBUS 1
        2, // bit 2 - XBUS 2
        0, // bit 3 - OBUS 0
        1, // bit 4 - OBUS 1
        2, // bit 5 - OBUS 2
        3  // bit 6 - OBUS 3
    };

    for (uint8_t i = 0, j = 0x40; i < 7; i++, j >>= 1)
    {
        if (0 != (j & l_connectedXstps))
        {
            TargetHandle_t l_connectedFab =
              getConnectedPeerProc(i_chip->GetChipHandle(),
                                   i<3 ? TYPE_XBUS : TYPE_OBUS,
                                   l_positions[i]);

            if (NULL != l_connectedFab)
            {
                o_externalChips.push_back(l_connectedFab);
            }
        }
    }

    // Read WOF value.
    SCAN_COMM_REGISTER_CLASS * l_wof = i_chip->getRegister("TODWOF");
    o_rc |= l_wof->Read();

    if(o_rc)
    {
        PRDF_ERR( "[GetCheckstopInfo] SCOM fail on 0x%08x rc=%x",
                  i_chip->GetId(), o_rc);
        return o_rc;
    }

    o_wofValue = l_wof->GetBitFieldJustified(0,64);

    return SUCCESS;

}