Пример #1
0
/**
 * @brief Get the Virtual Address of the XSCOM space for the processor
 *  associated with this thread (the source chip)
 *
 * @param[out] o_mmioAddr  Physical mmio address that was mapped in
 * @return uint64_t* virtualAddress
 */
uint64_t* getCpuIdVirtualAddress( XSComBase_t& o_mmioAddr )
{
    uint64_t* o_virtAddr = 0;

    // Read the MMIO setup by the SBE
    o_mmioAddr = g_BlToHbDataManager.getXscomBAR();

    // Target's virtual address
    o_virtAddr = static_cast<uint64_t*>
      (mmio_dev_map(reinterpret_cast<void*>(o_mmioAddr),
                    THIRTYTWO_GB));

    TRACDCOMP(g_trac_xscom, "getCpuIdVirtualAddress: o_Virtual Address   =  0x%llX\n",o_virtAddr);

    return o_virtAddr;

}
Пример #2
0
/**
 * @brief Get the Virtual Address of the XSCOM space for the processor
 *  associated with this thread (the source chip)
 *
 * @return uint64_t* virtualAddress
 */
uint64_t* getCpuIdVirtualAddress()
{
    uint64_t* o_virtAddr = 0;

    // Get the CPU core this thread is running on
    uint32_t cpuid = task_getcpuid();

    //NNNCCCPPPPTTT format fot the cpuid..
    //  N = node, C = chip, P = proc, T = thread
    uint32_t chipId = (cpuid & 0x0380)>>7;
    uint32_t nodeId = (cpuid & 0x1C00)>>10;

    // Can change the above hardcoded values to either a macro or use
    // the info below to do the masking and shifting.
    // uint64_t max_threads = cpu_thread_count();
    // for the number of Chips  - use  g_xscomMaxChipsPerNode instead..
    // For the number of Procs.. MAX_PROCS_RSV = P8_MAX_PROCS*2
    // P8_MAX_PROCS = 8 -- space left for 2* that.

    XSComBase_t l_systemBaseAddr = MASTER_PROC_XSCOM_BASE_ADDR;

    // Target's XSCOM Base address
    XSComBase_t l_XSComBaseAddr = l_systemBaseAddr +
      ( ( (g_xscomMaxChipsPerNode * nodeId) +
          chipId ) * THIRTYTWO_GB);

    // Target's virtual address
    o_virtAddr = static_cast<uint64_t*>
      (mmio_dev_map(reinterpret_cast<void*>(l_XSComBaseAddr),
                    THIRTYTWO_GB));

    TRACDCOMP(g_trac_xscom, "getCpuIdVirtualAddress: o_Virtual Address   =  0x%llX\n",o_virtAddr);

    return o_virtAddr;

}
Пример #3
0
/**
 * @brief Get the virtual address of the input target
 *        for an XSCOM access.
 *
 * Logic:
 *
 * If sentinel:
 *      If never XSCOM to sentinel
 *          Calculate virtual addr for sentinel
 *          Save it to g_masterProcVirtAddr for future XSCOM to sentinel
 *      Else
 *          Use virtual addr stored in g_masterProcVirtAddr
 *      End if
 * Else (not sentinel)
 *      If never XSCOM to this chip:
 *          If this is a master processor object
 *              Use virtual addr stored for sentinel (g_masterProcVirtAddr)
 *          Else
 *              Call mmio_dev_map() to get virtual addr for this slave proc
 *          End if
 *          Save virtual addr used to this chip's attribute
 *      Else
 *          Use virtual address stored in this chip's attributes.
 *      End if
 * End if
 *
 * @param[in]   i_target        XSCom target
 * @param[out]  o_virtAddr      Target's virtual address
 *
 * @return errlHndl_t
 */
errlHndl_t getTargetVirtualAddress(TARGETING::Target* i_target,
                                   uint64_t*& o_virtAddr)
{
    errlHndl_t l_err = NULL;
    o_virtAddr = NULL;
    XSComBase_t l_XSComBaseAddr = 0;

    do
    {

        // Find out if the target pointer is the master processor chip
        bool l_isMasterProcChip = false;

        if (i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL)
        {
            // Sentinel pointer representing the master processor chip
            l_isMasterProcChip = true;
        }
        else
        {
            TARGETING::Target* l_pMasterProcChip = NULL;
            TARGETING::targetService().
                masterProcChipTargetHandle(l_pMasterProcChip);

            if (i_target == l_pMasterProcChip)
            {
                // Target Service reports that this is the master processor chip
                l_isMasterProcChip = true;
            }
        }


        // If the target is the master processor chip sentinel
        if (l_isMasterProcChip)
        {

            // This is the master processor chip. The virtual address is
            // g_masterProcVirtAddr. If this is NULL then initialize it

            // Use atomic update instructions here to avoid
            // race condition between different threads.
            // Keep in mind that the mutex used in XSCOM is hardware mutex,
            // not a mutex for the whole XSCOM logic.
            if (__sync_bool_compare_and_swap(&g_masterProcVirtAddr,
                                     NULL, NULL))
            {
                // Note: can't call TARGETING code prior to PNOR being
                // brought up.
                uint64_t* l_tempVirtAddr = getCpuIdVirtualAddress();
                if (!__sync_bool_compare_and_swap(&g_masterProcVirtAddr,
                                         NULL, l_tempVirtAddr))
                {
                    // If g_masterProcVirtAddr has already been updated by
                    // another thread, we need to unmap the dev_map we just
                    // called above.
                    int rc = 0;
                    rc =  mmio_dev_unmap(reinterpret_cast<void*>
                                        (l_tempVirtAddr));
                    if (rc != 0)
                    {
                        /*@
                         * @errortype
                         * @moduleid     XSCOM_GET_TARGET_VIRT_ADDR
                         * @reasoncode   XSCOM_MMIO_UNMAP_ERR
                         * @userdata1    Return Code
                         * @userdata2    Unmap address
                         * @devdesc      mmio_dev_unmap() returns error
                         * @custdesc     A problem occurred during the IPL
                         *               of the system.
                         */
                        l_err = new ERRORLOG::ErrlEntry(
                                ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                                XSCOM_GET_TARGET_VIRT_ADDR,
                                XSCOM_MMIO_UNMAP_ERR,
                                rc,
                                reinterpret_cast<uint64_t>(l_tempVirtAddr),
                                true /*Add HB Software Callout*/);
                        break;
                    }
                }
            }

            // Set virtual address to sentinel's value
            o_virtAddr = g_masterProcVirtAddr;
        }
        else // This is not the master sentinel
        {

            // Get the virtual addr value of the chip from the virtual address
            // attribute
            o_virtAddr =
              reinterpret_cast<uint64_t*>(
                i_target->getAttr<TARGETING::ATTR_XSCOM_VIRTUAL_ADDR>());


            // If the virtual address equals NULL(default) then this is the
            // first XSCOM to this target so we need to calculate
            // the virtual address and save it in the xscom address attribute.
            if (o_virtAddr == NULL)
            {
                uint64_t  xscomNodeId = 0;
                uint64_t  xscomChipId = 0;

                // Get the target Node Id
                xscomNodeId =
                  i_target->getAttr<TARGETING::ATTR_FABRIC_NODE_ID>();

                // Get the target Chip Id
                xscomChipId =
                  i_target->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>();

                // Get system XSCOM base address
                TARGETING::TargetService& l_targetService =
                                        TARGETING::targetService();
                TARGETING::Target* l_pTopLevel = NULL;
                (void) l_targetService.getTopLevelTarget(l_pTopLevel);
                assert(l_pTopLevel != NULL);
                XSComBase_t l_systemBaseAddr =
                    l_pTopLevel->getAttr<TARGETING::ATTR_XSCOM_BASE_ADDRESS>();

                // Target's XSCOM Base address
                l_XSComBaseAddr = l_systemBaseAddr +
                    ( ( (g_xscomMaxChipsPerNode * xscomNodeId) +
                            xscomChipId ) * THIRTYTWO_GB);

                TRACFCOMP(g_trac_xscom,
                          "Target %.8X :: Node:%d Chip:%d :: XscomBase:0x%llX",
                          TARGETING::get_huid(i_target),
                          xscomNodeId,
                          xscomChipId,
                          l_XSComBaseAddr);

                // Target's virtual address
                o_virtAddr = static_cast<uint64_t*>
                    (mmio_dev_map(reinterpret_cast<void*>(l_XSComBaseAddr),
                      THIRTYTWO_GB));

                TRACDCOMP(g_trac_xscom, "xscomPerformOp: o_Virtual Address   =  0x%llX\n",o_virtAddr);

                // Implemented the virtual address attribute..

                // Leaving the comments as a discussion point...
                // Technically there is a race condition here. The mutex is
                // a per-hardware thread mutex, not a mutex for the whole XSCOM
                // logic. So there is possibility that this same thread is running
                // on another thread at the exact same time. We can use atomic
                // update instructions here.
                // Comment for Nick: This is a good candidate for having a way
                // to return a reference to the attribute instead of requiring
                // to call setAttr. We currently have no way to SMP-safely update
                // this attribute, where as if we had a reference to it we could use
                // the atomic update functions (_sync_bool_compare_and_swap in
                // this case.

                // Save the virtual address attribute.
                i_target->setAttr<TARGETING::ATTR_XSCOM_VIRTUAL_ADDR>(
                                        reinterpret_cast<uint64_t>(o_virtAddr));

            }
        }

    } while (0);

    return l_err;
}