diff options
| author | Dan Crowell <dcrowell@us.ibm.com> | 2016-04-08 21:03:51 -0500 |
|---|---|---|
| committer | Stephen Cprek <smcprek@us.ibm.com> | 2016-04-21 13:51:32 -0500 |
| commit | 76f1c48130a060fbe83c851fce2474c17b2df9b2 (patch) | |
| tree | e258515dcbdab5817603c9d290befe2324df7d59 /src/usr/occ | |
| parent | 3967f43b9478d7e6b58180dd0b331e61412997cd (diff) | |
| download | talos-hostboot-76f1c48130a060fbe83c851fce2474c17b2df9b2.tar.gz talos-hostboot-76f1c48130a060fbe83c851fce2474c17b2df9b2.zip | |
Removing some more old fapi1 and hwp code
Deleted all of the old fapi1 code
Moved potentially reuseable occ code to a new dir
Deleted a variety of p8 hwp files
Change-Id: I8b6ab72fef3f1413d919bdd21bc88f2c4f59c5c3
RTC: 146345
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/23075
Tested-by: Jenkins Server
Tested-by: FSP CI Jenkins
Reviewed-by: Matt Derksen <v2cibmd@us.ibm.com>
Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
Reviewed-by: William G. Hoffa <wghoffa@us.ibm.com>
Diffstat (limited to 'src/usr/occ')
| -rw-r--r-- | src/usr/occ/makefile | 37 | ||||
| -rw-r--r-- | src/usr/occ/occ.C | 572 | ||||
| -rw-r--r-- | src/usr/occ/occ.mk | 84 | ||||
| -rw-r--r-- | src/usr/occ/occAccess.C | 292 | ||||
| -rw-r--r-- | src/usr/occ/occ_common.C | 936 | ||||
| -rw-r--r-- | src/usr/occ/p8_pmc_force_vsafe.C | 517 | ||||
| -rwxr-xr-x | src/usr/occ/p8_pmc_force_vsafe.H | 81 | ||||
| -rw-r--r-- | src/usr/occ/runtime/makefile | 39 | ||||
| -rw-r--r-- | src/usr/occ/runtime/rt_occ.C | 486 |
9 files changed, 3044 insertions, 0 deletions
diff --git a/src/usr/occ/makefile b/src/usr/occ/makefile new file mode 100644 index 000000000..0d5144e99 --- /dev/null +++ b/src/usr/occ/makefile @@ -0,0 +1,37 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/occ/makefile $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2013,2016 +# [+] 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. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG +ROOTPATH = ../../../../.. + +MODULE = occ + +SUBDIRS += runtime.d + +## Objects unique to HB IPL +OBJS += + +## Objects common to HB IPL and HBRT +include occ.mk + +include ${ROOTPATH}/config.mk diff --git a/src/usr/occ/occ.C b/src/usr/occ/occ.C new file mode 100644 index 000000000..c13f09e70 --- /dev/null +++ b/src/usr/occ/occ.C @@ -0,0 +1,572 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/occ/occ.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2013,2016 */ +/* [+] 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. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#include <stdint.h> +#include <config.h> + +#include <hwpf/hwp/occ/occ.H> +#include <hwpf/hwp/occ/occ_common.H> + +#include <initservice/taskargs.H> +#include <errl/errlentry.H> + +#include <devicefw/userif.H> +#include <sys/misc.h> +#include <sys/mm.h> +#include <sys/mmio.h> +#include <vmmconst.h> +#include <kernel/vmmmgr.H> // INITIAL_MEM_SIZE + +// targeting support +#include <targeting/common/commontargeting.H> +#include <targeting/common/utilFilter.H> +#include <targeting/common/targetservice.H> +#include <targeting/common/util.H> + +// fapi support +#include <fapi.H> +#include <fapiPlatHwpInvoker.H> +#include <hwpf/plat/fapiPlatTrace.H> +#include <isteps/hwpf_reasoncodes.H> + +#include <vfs/vfs.H> +#include <util/utillidmgr.H> + +#include <htmgt/htmgt.H> + +// Procedures +#include <p8_pba_init.H> +#include <p8_occ_control.H> +#include <p8_pba_bar_config.H> +#include <p8_pm_init.H> +#include <p8_pm_firinit.H> + +#include <config.h> +// Easy macro replace for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) + +extern trace_desc_t* g_fapiTd; + +using namespace TARGETING; + +namespace HBOCC +{ + /** + * @brief Determine homer addresses and load OCC image for a processor. + * + * @param[in] i_target0 Target proc to load + * @param[in] i_homerVirtAddrBase + * IPL: Base Virtual address of all HOMER images + * Runtime: Ignored - Determined using Attributes + * + * @param[in] i_homerPhysAddrBase + * IPL: Base Physical address of all HOMER images + * Runtime: Ignored - Determined using Attributes + * @param[in] i_useSRAM: bool - use SRAM for OCC image, ie during IPL + * true if during IPL, false if at end of IPL (default) + * + * @return errlHndl_t Error log + */ + + errlHndl_t primeAndLoadOcc (Target* i_target, + void* i_homerVirtAddrBase, + uint64_t i_homerPhysAddrBase, + bool i_useSRAM) + { + errlHndl_t l_errl = NULL; + + TRACUCOMP( g_fapiTd, + ENTER_MRK"primeAndLoadOcc(%d)", i_useSRAM); + + do { + //============================== + //Setup Addresses + //============================== + uint64_t occImgPaddr, occImgVaddr; + uint64_t commonPhysAddr, homerHostVirtAddr; + +#ifndef __HOSTBOOT_RUNTIME + const uint8_t procPos = i_target->getAttr<ATTR_POSITION>(); + const uint64_t procOffset = (procPos * VMM_HOMER_INSTANCE_SIZE); + + if (i_useSRAM) + { + occImgVaddr = reinterpret_cast<uint64_t>(i_homerVirtAddrBase); + } + else + { + occImgVaddr = reinterpret_cast<uint64_t>(i_homerVirtAddrBase) + + procOffset + HOMER_OFFSET_TO_OCC_IMG; + } + + occImgPaddr = + i_homerPhysAddrBase + procOffset + HOMER_OFFSET_TO_OCC_IMG; + + commonPhysAddr = + i_homerPhysAddrBase + VMM_HOMER_REGION_SIZE; + + homerHostVirtAddr = reinterpret_cast<uint64_t> + (i_homerVirtAddrBase) + procOffset + + HOMER_OFFSET_TO_OCC_HOST_DATA; +#else + uint64_t homerPaddr = i_target->getAttr<ATTR_HOMER_PHYS_ADDR>(); + uint64_t homerVaddr = i_target->getAttr<ATTR_HOMER_VIRT_ADDR>(); + + occImgPaddr = homerPaddr + HOMER_OFFSET_TO_OCC_IMG; + occImgVaddr = homerVaddr + HOMER_OFFSET_TO_OCC_IMG; + + TARGETING::Target* sys = NULL; + TARGETING::targetService().getTopLevelTarget(sys); + commonPhysAddr = + sys->getAttr<ATTR_OCC_COMMON_AREA_PHYS_ADDR>(); + + homerHostVirtAddr = + homerVaddr + HOMER_OFFSET_TO_OCC_HOST_DATA; +#endif + + //============================== + // Load OCC + //============================== + l_errl = HBOCC::loadOCC(i_target, + occImgPaddr, + occImgVaddr, + commonPhysAddr, + i_useSRAM); + if(l_errl != NULL) + { + TRACFCOMP( g_fapiImpTd, ERR_MRK"primeAndLoadOcc: loadOCC failed" ); + break; + } + +#ifdef CONFIG_IPLTIME_CHECKSTOP_ANALYSIS +#ifndef __HOSTBOOT_RUNTIME + if (i_useSRAM) + { + //============================== + //Setup host data area in SRAM + //============================== + l_errl = HBOCC::loadHostDataToSRAM(i_target, + PRDF::MASTER_PROC_CORE); + if( l_errl != NULL ) + { + TRACFCOMP( g_fapiImpTd, ERR_MRK"loading Host Data Area failed!" ); + break; + } + } + else +#endif +#endif + { + //============================== + //Setup host data area of HOMER; + //============================== + void* occHostVirt = reinterpret_cast<void*>(homerHostVirtAddr); + l_errl = HBOCC::loadHostDataToHomer(i_target,occHostVirt); + if( l_errl != NULL ) + { + TRACFCOMP( g_fapiImpTd, ERR_MRK"loading Host Data Area failed!" ); + break; + } + } + } while (0); + + TRACUCOMP( g_fapiTd, + EXIT_MRK"primeAndLoadOcc" ); + return l_errl; + } + + /** + * @brief Starts OCCs on all Processors in the node + * This is intended to be used for AVP testing. + * + * @param[out] o_failedOccTarget: Pointer to the target failing + * loadnStartAllOccs + * @param[in] i_useSRAM: bool - use SRAM for OCC image, ie during IPL + * true if during IPL, false if at end of IPL (default) + * @return errlHndl_t Error log if OCC load failed + */ + errlHndl_t loadnStartAllOccs(TARGETING::Target *& o_failedOccTarget, + bool i_useSRAM) + { + errlHndl_t l_errl = NULL; + void* homerVirtAddrBase = NULL; + uint64_t homerPhysAddrBase = VMM_HOMER_REGION_START_ADDR; + bool winkle_loaded = false; + + TRACUCOMP( g_fapiTd, + ENTER_MRK"loadnStartAllOccs(%d)", i_useSRAM); + + do { +#ifndef __HOSTBOOT_RUNTIME + //OCC requires the build_winkle_images library + if ( !VFS::module_is_loaded( "libbuild_winkle_images.so" ) ) + { + l_errl = VFS::module_load( "libbuild_winkle_images.so" ); + + if ( l_errl ) + { + // load module returned with errl set + TRACFCOMP( g_fapiTd,ERR_MRK"loadnStartAllOccs: Could not load build_winkle module" ); + // break from do loop if error occured + break; + } + winkle_loaded = true; + } + + assert(VMM_HOMER_REGION_SIZE <= THIRTYTWO_GB, + "loadnStartAllOccs: Unsupported HOMER Region size"); + + if (!i_useSRAM) + { + //If running Sapphire need to place this at the top of memory + if(TARGETING::is_sapphire_load()) + { + homerPhysAddrBase = TARGETING::get_top_mem_addr(); + assert (homerPhysAddrBase != 0, + "loadnStartAllOccs: Top of memory was 0!"); + homerPhysAddrBase -= VMM_ALL_HOMER_OCC_MEMORY_SIZE; + } + TRACFCOMP( g_fapiTd, "HOMER is at %.16X", homerPhysAddrBase ); + + //Map entire homer region into virtual memory + homerVirtAddrBase = + mm_block_map(reinterpret_cast<void*>(homerPhysAddrBase), + VMM_HOMER_REGION_SIZE); + TRACFCOMP( g_fapiTd, "HOMER virtaddrbase %.16X", homerVirtAddrBase ); + } + else + { + // Use page of memory previously set aside for OCC Bootloader + // see src/kernel/misc.C::expand_full_cache() + homerVirtAddrBase = reinterpret_cast<void*> + (VmmManager::INITIAL_MEM_SIZE); + homerPhysAddrBase = mm_virt_to_phys(homerVirtAddrBase); + + TRACUCOMP(g_fapiTd, "Virtual Address = 0x%16lx", + homerVirtAddrBase); + TRACUCOMP(g_fapiTd, "Physical Address= 0x%16lx", + homerPhysAddrBase); + } +#endif + + if (i_useSRAM) + { + // OCC is going into L3 and SRAM so only need 1 prime and load + // into the Master Proc + TargetService & tS = targetService(); + Target * sysTarget = NULL; + tS.getTopLevelTarget( sysTarget ); + assert( sysTarget != NULL ); + Target* masterproc = NULL; + tS.masterProcChipTargetHandle( masterproc ); + + /******* SETUP AND LOAD **************/ + l_errl = primeAndLoadOcc (masterproc, + homerVirtAddrBase, + homerPhysAddrBase, + i_useSRAM); + if(l_errl) + { + o_failedOccTarget = masterproc; + TRACFCOMP( g_fapiImpTd, ERR_MRK + "loadnStartAllOccs:primeAndLoadOcc failed"); + break; + } + + /********* START OCC *************/ + l_errl = HBOCC::startOCC (masterproc, NULL, o_failedOccTarget); + + + if (l_errl) + { + TRACFCOMP( g_fapiImpTd, ERR_MRK"loadnStartAllOccs: startOCC failed"); + break; + } + } + else + { + + TargetHandleList procChips; + getAllChips(procChips, TYPE_PROC, true); + + if(procChips.size() == 0) + { + TRACFCOMP( g_fapiTd,INFO_MRK"loadnStartAllOccs: No processors found" ); + //We'll never get this far in the IPL without any processors, + // so just exit. + break; + } + + TRACUCOMP( g_fapiTd, + INFO_MRK"loadnStartAllOccs: %d procs found", + procChips.size()); + + TargetHandleList::iterator itr1 = procChips.begin(); + //The OCC Procedures require processors within a DCM be + //setup together. So, first checking if any proc has + //DCM installed attribute set. If not, we can iterate + //over the list in any order. + + //If DCM installed is set, we work under the assumption + //that each nodeID is a DCM. So sort the list by NodeID + //then call OCC Procedures on NodeID pairs. + if(0 == + (*itr1)->getAttr<ATTR_PROC_DCM_INSTALLED>()) + { + TRACUCOMP( g_fapiTd, + INFO_MRK"loadnStartAllOccs: non-dcm path entered"); + + for (TargetHandleList::iterator itr = procChips.begin(); + itr != procChips.end(); + ++itr) + { + /******* SETUP AND LOAD **************/ + l_errl = primeAndLoadOcc (*itr, + homerVirtAddrBase, + homerPhysAddrBase, + i_useSRAM); + if(l_errl) + { + o_failedOccTarget = *itr; + TRACFCOMP( g_fapiImpTd, ERR_MRK + "loadnStartAllOccs:primeAndLoadOcc failed"); + break; + } + + /********* START OCC *************/ + l_errl = HBOCC::startOCC (*itr, NULL, o_failedOccTarget); + if (l_errl) + { + TRACFCOMP( g_fapiImpTd, ERR_MRK"loadnStartAllOccs: startOCC failed"); + break; + } + } + if (l_errl) + { + break; + } + + } + else + { + TRACUCOMP( g_fapiTd, + INFO_MRK"loadnStartAllOccs: Following DCM Path"); + + std::sort(procChips.begin(), + procChips.end(), + orderByNodeAndPosition); + + TRACUCOMP( g_fapiTd, + INFO_MRK"loadnStartAllOccs: procChips list sorted"); + + for (TargetHandleList::iterator itr = procChips.begin(); + itr != procChips.end(); + ++itr) + { + TRACUCOMP( g_fapiImpTd, INFO_MRK"loadnStartAllOccs: Insepcting first target" ); + Target* targ0 = *itr; + Target* targ1 = NULL; + + TRACUCOMP( g_fapiImpTd, INFO_MRK + "loadnStartAllOccs: Cur target nodeID=%d", + targ0->getAttr<ATTR_FABRIC_GROUP_ID>()); + + + //if the next target in the list is in the same node + // they are on the same DCM, so bump itr forward + // and update targ1 pointer + if((itr+1) != procChips.end()) + { + TRACUCOMP( g_fapiImpTd, INFO_MRK + "loadnStartAllOccs: n+1 target nodeID=%d", + ((*(itr+1))->getAttr<ATTR_FABRIC_GROUP_ID>()) + ); + + if((targ0->getAttr<ATTR_FABRIC_GROUP_ID>()) == + ((*(itr+1))->getAttr<ATTR_FABRIC_GROUP_ID>())) + { + itr++; + targ1 = *itr; + } + } + + /********** Setup and load targ0 ***********/ + l_errl = primeAndLoadOcc (targ0, + homerVirtAddrBase, + homerPhysAddrBase, + i_useSRAM); + if(l_errl) + { + o_failedOccTarget = targ0; + TRACFCOMP( g_fapiImpTd, ERR_MRK + "loadnStartAllOccs: " + "primeAndLoadOcc failed on targ0"); + break; + } + + /*********** Setup and load targ1 **********/ + l_errl = primeAndLoadOcc (targ1, + homerVirtAddrBase, + homerPhysAddrBase, + i_useSRAM); + if(l_errl) + { + o_failedOccTarget = targ1; + TRACFCOMP( g_fapiImpTd, ERR_MRK + "loadnStartAllOccs: " + "primeAndLoadOcc failed on targ1"); + break; + } + + /*********** Start OCC *******************/ + l_errl = HBOCC::startOCC (targ0, targ1, o_failedOccTarget); + if (l_errl) + { + TRACFCOMP( g_fapiImpTd, ERR_MRK + "loadnStartAllOccs: start failed"); + break; + } + } + if (l_errl) + { + break; + } + } + } + } while(0); + + errlHndl_t l_tmpErrl = NULL; +//Unless HTMGT is in use, there are no further accesses to HOMER memory +//required during the IPL +#ifndef CONFIG_HTMGT + if(homerVirtAddrBase) + { + int rc = 0; + rc = mm_block_unmap(homerVirtAddrBase); + if (rc != 0) + { + /*@ + * @errortype + * @moduleid fapi::MOD_OCC_LOAD_START_ALL_OCCS + * @reasoncode fapi::RC_MM_UNMAP_ERR + * @userdata1 Return Code + * @userdata2 Unmap address + * @devdesc mm_block_unmap() returns error + * @custdesc A problem occurred during the IPL + * of the system. + */ + l_tmpErrl = + new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + fapi::MOD_OCC_LOAD_START_ALL_OCCS, + fapi::RC_MM_UNMAP_ERR, + rc, + reinterpret_cast<uint64_t> + (homerVirtAddrBase)); + if(l_tmpErrl) + { + if(l_errl) + { + errlCommit( l_tmpErrl, HWPF_COMP_ID ); + } + else + { + l_errl = l_tmpErrl; + } + } + } + } +#endif + //make sure we always unload the module + if (winkle_loaded) + { + l_tmpErrl = VFS::module_unload( "libbuild_winkle_images.so" ); + if ( l_tmpErrl ) + { + TRACFCOMP + ( g_fapiTd,ERR_MRK + "loadnStartAllOccs: Error unloading build_winkle module" + ); + if(l_errl) + { + errlCommit( l_tmpErrl, HWPF_COMP_ID ); + } + else + { + l_errl = l_tmpErrl; + } + } + } + + TRACUCOMP( g_fapiTd, + EXIT_MRK"loadnStartAllOccs" ); + + return l_errl; + } + + /** + * @brief Starts OCCs on all Processors in the node + * This is intended to be used for Open Power. + * + * @return errlHndl_t Error log if OCC load failed + */ + errlHndl_t activateOCCs(bool i_useSRAM) + { + TRACUCOMP( g_fapiTd,ENTER_MRK"activateOCCs(%d)", i_useSRAM ); + errlHndl_t l_errl = NULL; + TARGETING::Target* l_failedOccTarget = NULL; +#ifdef CONFIG_HTMGT + bool occStartSuccess = true; +#endif + + l_errl = loadnStartAllOccs (l_failedOccTarget, i_useSRAM); + if (l_errl) + { + errlCommit (l_errl, HWPF_COMP_ID); +#ifdef CONFIG_HTMGT + occStartSuccess = false; +#endif + } + + //TODO RTC:116027 + //HB configures/enables the occ buffers + + //TODO RTC:115636 + //HB enables the scon-via-i2c logic on the OCCs + +#ifdef CONFIG_HTMGT + // Report OCC status to HTMGT + if (!i_useSRAM) + { + HTMGT::processOccStartStatus(occStartSuccess,l_failedOccTarget); + } +#endif + TRACUCOMP( g_fapiTd,EXIT_MRK"activateOCC" ); + return l_errl; + } + + +} //end OCC namespace diff --git a/src/usr/occ/occ.mk b/src/usr/occ/occ.mk new file mode 100644 index 000000000..a64a2f2e3 --- /dev/null +++ b/src/usr/occ/occ.mk @@ -0,0 +1,84 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/occ/occ.mk $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2014,2016 +# [+] 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. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG +## support for Targeting and fapi +EXTRAINCDIR += ${ROOTPATH}/src/include/usr/ecmddatabuffer +EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/fapi +EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/plat +EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/hwp + +## pointer to common HWP files +EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/include + +## pointer to already consumed procedures. +EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/p8_set_pore_bar + +## NOTE: add the base istep dir here. +EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/occ + +## Include sub dirs +## NOTE: add a new EXTRAINCDIR when you add a new HWP +## EXAMPLE: +## EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/occ/<HWP_dir> +EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/occ/occ_procedures +EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/hwp/utility_procedures + +## NOTE: add new object files when you add a new HWP +OBJS += p8_pba_init.o +OBJS += p8_pm_init.o +OBJS += p8_pcbs_init.o +OBJS += p8_pmc_init.o +OBJS += p8_poregpe_init.o +OBJS += p8_oha_init.o +OBJS += p8_ocb_init.o +OBJS += p8_pss_init.o +OBJS += p8_occ_control.o +OBJS += p8_occ_sram_init.o +OBJS += p8_pm_firinit.o +OBJS += p8_pm_oha_firinit.o +OBJS += p8_pm_pcbs_firinit.o +OBJS += p8_pm_occ_firinit.o +OBJS += p8_pm_pba_firinit.o +OBJS += p8_pm_pmc_firinit.o +OBJS += p8_pm_utils.o + + +#These procedures are included per Stradale's request so +#they can implement OCC Reset. +OBJS += p8_pm_prep_for_reset.o +OBJS += p8_pmc_force_vsafe.o +OBJS += p8_ocb_indir_access.o +OBJS += p8_ocb_indir_setup_linear.o + +#common occ functions between ipl and runtime +OBJS += occ_common.o +OBJS += occ.o +OBJS += $(if $(CONFIG_HTMGT),occAccess.o) + +## NOTE: add a new directory onto the vpaths when you add a new HWP +## EXAMPLE: +# VPATH += ${ROOTPATH}/src/usr/hwpf/hwp/occ/<HWP_dir> +VPATH += ${ROOTPATH}/src/usr/hwpf/hwp/occ/occ_procedures + + diff --git a/src/usr/occ/occAccess.C b/src/usr/occ/occAccess.C new file mode 100644 index 000000000..d06a47680 --- /dev/null +++ b/src/usr/occ/occAccess.C @@ -0,0 +1,292 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/occ/occAccess.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ +/* [+] 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. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#include <stdint.h> + +#include <errl/errlentry.H> +#include <occ/occAccess.H> +#include <targeting/common/utilFilter.H> + +// Fapi +#include <fapi.H> +#include <fapiPlatHwpInvoker.H> +#include <isteps/hwpf_reasoncodes.H> + +// Procedures +#include <p8_ocb_init.H> +#include <p8_ocb_indir_setup_linear.H> +#include <p8_ocb_indir_access.H> + +// Easy macro replace for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) + +namespace HBOCC +{ + +// Passed target should be either a PROC or an OCC target +// If passed an OCC, then use it's parent PROC +// If passed a PROC, then use it +errlHndl_t getChipTarget(const TARGETING::Target* i_target, + TARGETING::Target* & o_pChipTarget) +{ + errlHndl_t l_errl = NULL; + TARGETING::TYPE l_type = TARGETING::TYPE_NA; + bool l_found = false; //error if no chip target found + uint32_t l_huid = 0xFFFFFFFF; //read for error FFDC + + do + { + if(NULL == i_target) //unexpected error + { + TRACFCOMP( g_fapiTd, ERR_MRK"getChipTarget: null target passed"); + break; // log and return error + } + + l_type = i_target->getAttr<TARGETING::ATTR_TYPE> (); + if (TARGETING::TYPE_OCC == l_type) // if OCC, use parent PROC + { + const TARGETING::Target * l_pChipTarget = getParentChip( + const_cast<TARGETING::Target *>(i_target)); + o_pChipTarget = const_cast<TARGETING::Target *>(l_pChipTarget); + if (NULL == o_pChipTarget) + { + l_huid = i_target->getAttr<TARGETING::ATTR_HUID>(); + TRACFCOMP( g_fapiTd, ERR_MRK"getChipTarget:" + " Error OCC target has no parent" + " Target type: 0x%X huid:0x%X", + l_type, l_huid); + break; // log and return error + } + l_found = true; + } + else if (TARGETING::TYPE_PROC == l_type) //use passed PROC target + { + o_pChipTarget = const_cast<TARGETING::Target *>(i_target); + l_found = true; + } + else // unexpected target type + { + l_huid = i_target->getAttr<TARGETING::ATTR_HUID>(); + TRACFCOMP( g_fapiTd, ERR_MRK"getChipTarget:" + " Error Unexpected target type. Not PROC or" + " OCC. Target is of type: 0x%X huid:0x%X", + l_type, l_huid); + break; // log and return error + } + + } + while (0); + + if (!l_found) + { + /*@ + * @errortype + * @moduleid fapi::MOD_GET_OCC_CHIP_TARGET + * @reasoncode fapi::RC_TARGET_UNSUPPORTED + * @userdata1 Target Type + * @userdata2 Target HUID + * @devdesc PROC or OCC expected + * @custdesc A problem occurred during the IPL + * of the system. + */ + const bool hbSwError = true; + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + fapi::MOD_GET_OCC_CHIP_TARGET, + fapi::RC_TARGET_UNSUPPORTED, + l_type, + l_huid, + hbSwError); + } + + return l_errl; +} + +// common wrapper to p8_ocb_indir_access to access an OCB indirect channel +enum accessOCBIndirectCmd +{ + ACCESS_OCB_READ_LINEAR, + ACCESS_OCB_WRITE_LINEAR, + ACCESS_OCB_WRITE_CIRCULAR, +}; + +errlHndl_t accessOCBIndirectChannel(accessOCBIndirectCmd i_cmd, + const TARGETING::Target * i_pTarget, + const uint32_t i_addr, + ecmdDataBufferBase & io_dataBuf) +{ + errlHndl_t l_errl = NULL; + uint32_t l_len = 0; + TARGETING::Target* l_pChipTarget = NULL; + + uint32_t l_channel = OCB_CHAN0; // OCB channel (0,1,2,3) + uint32_t l_operation = OCB_GET; // Operation(Get, Put) + bool l_ociAddrValid = true; // use oci_address + bool l_setup=true; // set up linear + + TRACUCOMP( g_fapiTd, ENTER_MRK"accessOCBIndirectChannel cmd=%d",i_cmd); + + switch (i_cmd) + { + case (ACCESS_OCB_READ_LINEAR): + break; // use defaults + case (ACCESS_OCB_WRITE_LINEAR): + l_operation = OCB_PUT; + break; + case (ACCESS_OCB_WRITE_CIRCULAR): + l_channel = OCB_CHAN1; + l_operation = OCB_PUT; + l_ociAddrValid = false; + l_setup = false; + break; + } + + TRACUCOMP( g_fapiTd, INFO_MRK"accessOCBIndirectChannel" + " channel=%d operation=%d addrValid=%d", + l_channel,l_operation,l_ociAddrValid); + do + { + l_errl = getChipTarget(i_pTarget,l_pChipTarget); + if (l_errl) + { + break; //exit with error + } + TRACUCOMP( g_fapiTd, INFO_MRK"accessOCBIndirectChannel:" + " target=%.8x type=%d", + get_huid(l_pChipTarget), + l_pChipTarget->getAttr<TARGETING::ATTR_TYPE>()); + + fapi::Target l_fapiTarget(fapi::TARGET_TYPE_PROC_CHIP, + reinterpret_cast<void *> (l_pChipTarget) ); + + // buffer must be multiple of bytes + if(io_dataBuf.getByteLength()%8 != 0) + { + TRACFCOMP( g_fapiImpTd, ERR_MRK"accessOCBIndirectChannel:" + " Error Improper data size:%d(in bytes),size of data" + " requested to be read is not aligned in size of 8 Bytes", + io_dataBuf.getByteLength()); + /*@ + * @errortype + * @moduleid fapi::MOD_ACCESS_OCB_INDIRECT_CHANNEL + * @reasoncode fapi::RC_INVALID_DATA_BUFFER_LENGTH + * @userdata1 Length of requested buffer size(in Bytes) to + * perform read operation. + * @userdata2 OCI address + * @devdesc Improper data size, data is not 8 byte aligned. + * @custdesc A problem occurred during the IPL + * of the system. + */ + const bool hbSwError = true; + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + fapi::MOD_ACCESS_OCB_INDIRECT_CHANNEL, + fapi::RC_INVALID_DATA_BUFFER_LENGTH, + io_dataBuf.getByteLength(), + i_addr, + hbSwError); + break; // return with error + } + + // TODO RTC: 116027 To be consistent with FSP code hwcoOCC.C, + // p8_ocb_indir_setup_linear is always called for read and write + // linear and not called for write circular. + // a) linear read and write set up may only be needed once + // b) circular write may need to be set up once + if (l_setup) + { + FAPI_INVOKE_HWP(l_errl, p8_ocb_indir_setup_linear, l_fapiTarget, + OCB_CHAN0, OCB_TYPE_LINSTR, i_addr); + if(l_errl) + { + TRACFCOMP( g_fapiImpTd, ERR_MRK"accessOCBIndirectChannel:" + " Error [0x%X] in call to " + " FAPI_INVOKE_HWP(p8_ocb_indir_setup_linear)", + l_errl->reasonCode()); + break; // return with error + } + } + + // perform operation + FAPI_INVOKE_HWP(l_errl, p8_ocb_indir_access, l_fapiTarget, + l_channel,l_operation,io_dataBuf.getByteLength()/8, + io_dataBuf,l_len,l_ociAddrValid,i_addr); + if(l_errl) + { + TRACFCOMP( g_fapiImpTd, ERR_MRK"accessOCBIndirectChannel:" + " Error [0x%X] in call to" + " FAPI_INVOKE_HWP(p8_ocb_indir_access)", + l_errl->reasonCode()); + break; // return with error + } + + } + while (0); + + TRACUCOMP( g_fapiTd, EXIT_MRK"accessOCBIndirectChannel"); + + return l_errl; +} + +// Read OCC SRAM +errlHndl_t readSRAM(const TARGETING::Target * i_pTarget, + const uint32_t i_addr, + ecmdDataBufferBase & io_dataBuf) +{ + errlHndl_t l_errl = NULL; + l_errl = accessOCBIndirectChannel(ACCESS_OCB_READ_LINEAR, + i_pTarget, + i_addr, + io_dataBuf); + return l_errl; +} + +// Write OCC SRAM +errlHndl_t writeSRAM(const TARGETING::Target * i_pTarget, + const uint32_t i_addr, + ecmdDataBufferBase & i_dataBuf) +{ + errlHndl_t l_errl = NULL; + l_errl = accessOCBIndirectChannel(ACCESS_OCB_WRITE_LINEAR, + i_pTarget, + i_addr, + i_dataBuf); + return l_errl; +} + +// Write OCC Circular Buffer +errlHndl_t writeCircularBuffer(const TARGETING::Target * i_pTarget, + ecmdDataBufferBase & i_dataBuf) +{ + errlHndl_t l_errl = NULL; + l_errl = accessOCBIndirectChannel(ACCESS_OCB_WRITE_CIRCULAR, + i_pTarget, + 0, + i_dataBuf); + return l_errl; +} + +} //end OCC namespace diff --git a/src/usr/occ/occ_common.C b/src/usr/occ/occ_common.C new file mode 100644 index 000000000..98a01a9da --- /dev/null +++ b/src/usr/occ/occ_common.C @@ -0,0 +1,936 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/occ/occ_common.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2013,2016 */ +/* [+] 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. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#include <stdint.h> + +#include <occ/occ_common.H> +#include <occ/occAccess.H> + +#include <initservice/taskargs.H> +#include <errl/errlentry.H> + +#include <devicefw/userif.H> +#include <sys/misc.h> +#include <sys/mm.h> +#include <sys/mmio.h> +#include <limits.h> +#include <vmmconst.h> + +// targeting support +#include <targeting/common/commontargeting.H> +#include <targeting/common/utilFilter.H> +#include <targeting/common/targetservice.H> +#include <targeting/common/util.H> + +// fapi support +#include <fapi.H> +#include <fapiPlatHwpInvoker.H> +#include <hwpf/plat/fapiPlatTrace.H> +#include <isteps/hwpf_reasoncodes.H> + +#include <vfs/vfs.H> +#include <util/utillidmgr.H> +#include <initservice/initserviceif.H> + +// Procedures +#include <p8_pba_init.H> +#include <p8_occ_control.H> +#include <p8_pba_bar_config.H> +#include <p8_pm_init.H> +#include <p8_pm_firinit.H> +#include <p8_pm_prep_for_reset.H> +#include <arch/ppc.H> + +#ifdef CONFIG_ENABLE_CHECKSTOP_ANALYSIS + #include <diag/prdf/prdfWriteHomerFirData.H> +#endif + +// Easy macro replace for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) + +extern trace_desc_t* g_fapiTd; + +using namespace TARGETING; + +namespace HBOCC +{ + /** + * @brief Fetches OCC image from FSP and writes to + * specified offset. + * + * @param[in] i_occVirtAddr Virtual + * address where OCC image + * should be loaded. + * + * @return errlHndl_t Error log image load failed + */ + errlHndl_t loadOCCImageToHomer(void* i_occVirtAddr) + { + TRACUCOMP( g_fapiTd, + ENTER_MRK"loadOCCImageToHomer(%p)", + i_occVirtAddr); + + errlHndl_t l_errl = NULL; + size_t lidSize = 0; + do { + UtilLidMgr lidMgr(HBOCC::OCC_LIDID); + + l_errl = lidMgr.getLidSize(lidSize); + if(l_errl) + { + TRACFCOMP( g_fapiImpTd, + ERR_MRK"loadOCCImageToHomer: Error getting lid size. lidId=0x%.8x", + OCC_LIDID); + break; + } + + l_errl = lidMgr.getLid(i_occVirtAddr, lidSize); + if(l_errl) + { + TRACFCOMP( g_fapiImpTd, + ERR_MRK"loadOCCImageToHomer: Error getting lid.. lidId=0x%.8x", + OCC_LIDID); + break; + } + + }while(0); + + TRACUCOMP( g_fapiTd, + EXIT_MRK"loadOCCImageToHomer"); + + return l_errl; + } + +#ifdef CONFIG_IPLTIME_CHECKSTOP_ANALYSIS + errlHndl_t loadOCCImageDuringIpl( TARGETING::Target* i_target, + void* i_occVirtAddr) + { + TRACUCOMP( g_fapiTd, + ENTER_MRK"loadOCCImageDuringIpl(%p)", + i_occVirtAddr); + + errlHndl_t l_errl = NULL; + size_t lidSize = 0; + void* l_occImage = NULL; + do { + // allocate memory big enough for all OCC + l_occImage = (void*)malloc(1*MEGABYTE); + + UtilLidMgr lidMgr(HBOCC::OCC_LIDID); + + // Get the size of the OCC lid + l_errl = lidMgr.getLidSize(lidSize); + if(l_errl) + { + TRACFCOMP( g_fapiImpTd, + ERR_MRK"loadOCCImageDuringIpl: Error getting lid size. lidId=0x%.8x", + OCC_LIDID); + break; + } + + // Ensure occ lid size is less than memory allocated for it + assert(lidSize <= 1*MEGABYTE); + + // Get the entire OCC lid and write it into temporary memory + l_errl = lidMgr.getLid(l_occImage, lidSize); + if(l_errl) + { + TRACFCOMP( g_fapiImpTd, + ERR_MRK"loadOCCImageDuringIpl: Error getting lid. lidId=0x%.8x", + OCC_LIDID); + break; + } + // Pointer to OCC LID + char *l_occLid = reinterpret_cast<char*>(l_occImage); + + + // Get system target in order to access ATTR_NEST_FREQ_MHZ + TARGETING::TargetService & tS = TARGETING::targetService(); + TARGETING::Target * sysTarget = NULL; + tS.getTopLevelTarget( sysTarget ); + assert( sysTarget != NULL ); + + // Save Nest Frequency; + ATTR_NEST_FREQ_MHZ_type l_nestFreq = + sysTarget->getAttr<ATTR_FREQ_PB>(); + + + size_t l_length = 0; // length of this section + size_t l_startOffset = 0; // offset to start of the section + + // offset to length of the section + size_t l_offsetToLength = OCC_OFFSET_LENGTH; + + // Get length of OCC bootloader + uint32_t *ptrToLength = (uint32_t *)(l_occLid + l_offsetToLength); + l_length = *ptrToLength; + + // We only have PAGESIZE to work with so make sure we do not exceed + // limit. + assert(l_length <= PAGESIZE); + // Write the OCC Bootloader into memory + memcpy(i_occVirtAddr, l_occImage, l_length); + + + // OCC Main Application + l_startOffset = l_length; // after the Boot image + char * l_occMainAppPtr = reinterpret_cast<char *>(l_occLid) + + l_startOffset; + + // Get the length of the OCC Main application + ptrToLength = (uint32_t *)(l_occMainAppPtr + l_offsetToLength); + l_length = *ptrToLength; + + + // write the IPL flag and the nest freq into OCC main app. + // IPL_FLAG is a two byte field. OR a 1 into these two bytes. + // FREQ is the 4 byte nest frequency value that goes into + // the same field in the HOMER. + + uint16_t *ptrToIplFlag = + (uint16_t *)((char *)l_occMainAppPtr + OCC_OFFSET_IPL_FLAG); + + uint32_t *ptrToFreq = + (uint32_t *)((char *)l_occMainAppPtr + OCC_OFFSET_FREQ); + + *ptrToIplFlag |= 0x0001; + *ptrToFreq = l_nestFreq; + + // Store the OCC Main applicatoin into ecmdDataBuffer + // so we may write it to SRAM + ecmdDataBufferBase l_occAppData(l_length * 8 /* bits */); + uint32_t rc = l_occAppData.insert((uint32_t *)l_occMainAppPtr, 0, + l_length * 8 /* bits */); + if (rc) + { + TRACFCOMP( g_fapiImpTd, + ERR_MRK"loadOCCImageDuringIpl: Error %d doing insert", + rc); + // create l_errl + break; + } + // Write the OCC Main app into SRAM + const uint32_t l_SramAddrApp = OCC_SRAM_ADDRESS; + l_errl = HBOCC::writeSRAM(i_target, l_SramAddrApp, l_occAppData); + if(l_errl) + { + TRACFCOMP( g_fapiImpTd, + ERR_MRK"loadOCCImageDuringIpl: Error in writeSRAM of app"); + break; + } + + + }while(0); + + //free memory used for OCC lid + free(l_occImage); + + TRACUCOMP( g_fapiTd, + EXIT_MRK"loadOCCImageDuringIpl"); + return l_errl; + } +#endif + + /** + * @brief Sets up OCC Host data in Homer + */ + errlHndl_t loadHostDataToHomer( TARGETING::Target* i_proc, + void* i_occHostDataVirtAddr) + { + TRACUCOMP( g_fapiTd, + ENTER_MRK"loadHostDataToHomer(%p)", + i_occHostDataVirtAddr); + + errlHndl_t l_errl = NULL; + + //Treat virtual address as starting pointer + //for config struct + HBOCC::occHostConfigDataArea_t * config_data = + reinterpret_cast<HBOCC::occHostConfigDataArea_t *> + (i_occHostDataVirtAddr); + + // Get top level system target + TARGETING::TargetService & tS = TARGETING::targetService(); + TARGETING::Target * sysTarget = NULL; + tS.getTopLevelTarget( sysTarget ); + assert( sysTarget != NULL ); + + uint32_t nestFreq = sysTarget->getAttr<ATTR_FREQ_PB>(); + + config_data->version = HBOCC::OccHostDataVersion; + config_data->nestFrequency = nestFreq; + + // Figure out the interrupt type + if( INITSERVICE::spBaseServicesEnabled() ) + { + config_data->interruptType = USE_FSI2HOST_MAILBOX; + } + else + { + config_data->interruptType = USE_PSIHB_COMPLEX; + } + +#ifdef CONFIG_ENABLE_CHECKSTOP_ANALYSIS + // Figure out the FIR master + TARGETING::Target* masterproc = NULL; + tS.masterProcChipTargetHandle( masterproc ); + if( masterproc == i_proc ) + { + config_data->firMaster = IS_FIR_MASTER; + + // TODO: RTC 124683 The ability to write the HOMER data + // is currently not available at runtime. +#ifndef __HOSTBOOT_RUNTIME + l_errl = PRDF::writeHomerFirData( config_data->firdataConfig, + sizeof(config_data->firdataConfig) ); +#endif + + } + else + { + config_data->firMaster = NOT_FIR_MASTER; + } + +#else + config_data->firMaster = 0; + //force to an older version so we can support + // older levels of OCC + config_data->version = PRE_FIR_MASTER_VERSION; +#endif + + TRACUCOMP( g_fapiTd, + EXIT_MRK"loadHostDataToHomer"); + + return l_errl; + } // loadHostDataToHomer + +#ifdef CONFIG_IPLTIME_CHECKSTOP_ANALYSIS +#ifndef __HOSTBOOT_RUNTIME + /** + * @brief Sets up OCC Host data in SRAM + */ + errlHndl_t loadHostDataToSRAM( TARGETING::Target* i_proc, + const PRDF::HwInitialized_t i_curHw) + { + TRACUCOMP( g_fapiTd, + ENTER_MRK"loadHostDataToSRAM i_curHw=%d",i_curHw); + + errlHndl_t l_errl = NULL; + + //Treat virtual address as starting pointer + //for config struct + HBOCC::occHostConfigDataArea_t * config_data = + new HBOCC::occHostConfigDataArea_t(); + + // Get top level system target + TARGETING::TargetService & tS = TARGETING::targetService(); + TARGETING::Target * sysTarget = NULL; + tS.getTopLevelTarget( sysTarget ); + assert( sysTarget != NULL ); + + uint32_t nestFreq = sysTarget->getAttr<ATTR_FREQ_PB>(); + + + + config_data->version = HBOCC::OccHostDataVersion; + config_data->nestFrequency = nestFreq; + + // Figure out the interrupt type + if( INITSERVICE::spBaseServicesEnabled() ) + { + config_data->interruptType = USE_FSI2HOST_MAILBOX; + } + else + { + config_data->interruptType = USE_PSIHB_COMPLEX; + } + + config_data->firMaster = IS_FIR_MASTER; + l_errl = PRDF::writeHomerFirData( config_data->firdataConfig, + sizeof(config_data->firdataConfig), + i_curHw); + if (l_errl) + { + TRACFCOMP( g_fapiImpTd, + ERR_MRK"loadHostDataToSRAM: Error in writeHomerFirData"); + } + else + { + const uint32_t l_SramAddrFir = OCC_SRAM_FIR_DATA; + ecmdDataBufferBase l_occFirData(OCC_SRAM_FIR_LENGTH * 8 /* bits */); + /// copy config_data in here + uint32_t rc = l_occFirData.insert( + (uint32_t *)config_data->firdataConfig, + 0, + sizeof(config_data->firdataConfig) * 8 /* bits */); + if (rc) + { + TRACFCOMP( g_fapiImpTd, + ERR_MRK"loadHostDataToSRAM: Error %d doing insert", + rc); + /*@ + * @errortype + * @moduleid fapi::MOD_OCC_LOAD_HOST_DATA_TO_SRAM + * @reasoncode fapi::RC_ECMD_INSERT_FAILED + * @userdata1 Return Code + * @userdata2 0 + * @devdesc ecmd insert failed for l_occFirData + * @custdesc A problem occurred during the IPL + * of the system. + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + fapi::MOD_OCC_LOAD_HOST_DATA_TO_SRAM, + fapi::RC_ECMD_INSERT_FAILED, + rc, 0); + } + else + { + l_errl = HBOCC::writeSRAM(i_proc, l_SramAddrFir, l_occFirData); + if(l_errl) + { + TRACFCOMP( g_fapiImpTd, + ERR_MRK"loadHostDataToSRAM: Error in writeSRAM"); + } + } + } + + TRACUCOMP( g_fapiTd, + EXIT_MRK"loadHostDataToSRAM"); + + return l_errl; + } // loadHostDataToSRAM +#endif +#endif + + errlHndl_t loadOCC(TARGETING::Target* i_target, + uint64_t i_occImgPaddr, + uint64_t i_occImgVaddr, // dest + uint64_t i_commonPhysAddr, + bool i_useSRAM) + { + errlHndl_t l_errl = NULL; + + TRACFCOMP( g_fapiTd, + ENTER_MRK"loadOCC(0x%08X, 0x%08X, 0x%08X, %d)", + i_occImgPaddr, i_occImgVaddr, i_commonPhysAddr, + i_useSRAM); + do{ + // Remember where we put things + // Subtract HOMER_OFFSET_TO_OCC_IMG to be technically + // correct though HOMER_OFFSET_TO_OCC_IMG happens to be zero + i_target->setAttr<ATTR_HOMER_PHYS_ADDR> + (i_occImgPaddr - HOMER_OFFSET_TO_OCC_IMG); + i_target->setAttr<ATTR_HOMER_VIRT_ADDR> + (i_occImgVaddr - HOMER_OFFSET_TO_OCC_IMG); + + // cast OUR type of target to a FAPI type of target. + const fapi::Target l_fapiTarg(fapi::TARGET_TYPE_PROC_CHIP, + (const_cast<Target*>(i_target))); + TRACFCOMP( g_fapiTd, "FapiTarget: %s",l_fapiTarg.toEcmdString()); + + //============================== + //Setup for OCC Load + //============================== + + // BAR0 is the Entire HOMER (start of HOMER contains OCC base Image) + // Bar size is in MB, obtained value of 4MB from Greg Still + TRACUCOMP( g_fapiImpTd, + INFO_MRK"loadOCC: OCC Address: 0x%.8X, size=0x%.8X", + i_occImgPaddr, VMM_HOMER_INSTANCE_SIZE_IN_MB); + + FAPI_INVOKE_HWP( l_errl, + p8_pba_bar_config, + l_fapiTarg, + 0, + i_occImgPaddr, + VMM_HOMER_INSTANCE_SIZE_IN_MB, + PBA_CMD_SCOPE_NODAL ); + + if (l_errl) + { + TRACFCOMP( g_fapiImpTd, + ERR_MRK"loadOCC: Bar0 config failed!" ); + l_errl->collectTrace(FAPI_TRACE_NAME,256); + l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256); + break; + } + + // BAR1 is what OCC uses to talk to the Centaur + // Bar size is in MB + uint64_t centaur_addr = + i_target->getAttr<ATTR_IBSCOM_PROC_BASE_ADDR>(); + FAPI_INVOKE_HWP( l_errl, + p8_pba_bar_config, + l_fapiTarg, + 1, //i_index + centaur_addr, //i_pba_bar_addr + (uint64_t)OCC_IBSCOM_RANGE_IN_MB, //i_pba_bar_size + PBA_CMD_SCOPE_NODAL ); //i_pba_cmd_scope + + if ( l_errl ) + { + TRACFCOMP( g_fapiImpTd, + ERR_MRK"loadOCC: Bar1 config failed!" ); + l_errl->collectTrace(FAPI_TRACE_NAME,256); + l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256); + break; + } + + // BAR3 is the OCC Common Area + // Bar size is in MB, obtained value of 8MB from Tim Hallett + TARGETING::Target* sys = NULL; + TARGETING::targetService().getTopLevelTarget(sys); + sys->setAttr<ATTR_OCC_COMMON_AREA_PHYS_ADDR>(i_commonPhysAddr); + + TRACUCOMP( g_fapiImpTd, + INFO_MRK"loadOCC: OCC Common Addr: 0x%.8X,size=0x%.8X", + i_commonPhysAddr,VMM_OCC_COMMON_SIZE_IN_MB); + + FAPI_INVOKE_HWP( l_errl, + p8_pba_bar_config, + l_fapiTarg, + 3, + i_commonPhysAddr, + VMM_OCC_COMMON_SIZE_IN_MB, + PBA_CMD_SCOPE_NODAL ); + + if ( l_errl ) + { + TRACFCOMP( g_fapiImpTd, + ERR_MRK"loadOCC: Bar3 config failed!" ); + l_errl->collectTrace(FAPI_TRACE_NAME,256); + l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256); + break; + } + +#ifdef CONFIG_IPLTIME_CHECKSTOP_ANALYSIS + if (i_useSRAM) + { + void* occVirt = reinterpret_cast<void *>(i_occImgVaddr); + l_errl = loadOCCImageDuringIpl( i_target, occVirt ); + if( l_errl ) + { + TRACFCOMP(g_fapiImpTd, + ERR_MRK"loadOCC: loadOCCImageDuringIpl failed!"); + break; + } + } + else +#endif + { + //============================== + //Load the OCC HOMER image + //============================== + +#ifdef CONFIG_IPLTIME_CHECKSTOP_ANALYSIS + // clear (up to and including) the IPL Flag + const uint32_t l_SramAddrApp = OCC_SRAM_ADDRESS; + ecmdDataBufferBase l_occAppData((OCC_OFFSET_IPL_FLAG + 6) * 8 /* bits */); + l_errl = HBOCC::writeSRAM(i_target, l_SramAddrApp, l_occAppData); + if(l_errl) + { + TRACFCOMP( g_fapiImpTd, + ERR_MRK"loadOCC: Error in writeSRAM of 0"); + break; + } +#endif + void* occVirt = reinterpret_cast<void *>(i_occImgVaddr); + l_errl = loadOCCImageToHomer( occVirt ); + if( l_errl ) + { + TRACFCOMP(g_fapiImpTd, + ERR_MRK"loadOCC: loadOCCImageToHomer failed!"); + break; + } + } + }while(0); + + TRACFCOMP( g_fapiTd, + EXIT_MRK"loadOCC"); + return l_errl; + } + + /** + * @brief Start OCC for specified DCM pair of processors. + * If 2nd input is NULL, OCC will be setup on just + * one target. + */ + errlHndl_t startOCC (Target* i_target0, + Target* i_target1, + Target *& o_failedTarget) + { + TRACFCOMP( g_fapiTd, + ENTER_MRK"startOCC"); + errlHndl_t l_errl = NULL; + + // cast OUR type of target to a FAPI type of target. + // figure out homer offsets + const fapi::Target + l_fapiTarg0(fapi::TARGET_TYPE_PROC_CHIP, + (const_cast<Target*>(i_target0))); + fapi::Target l_fapiTarg1; + if(i_target1) + { + l_fapiTarg1.setType(fapi::TARGET_TYPE_PROC_CHIP); + l_fapiTarg1.set(const_cast<Target*>(i_target1)); + } + else + { + l_fapiTarg1.setType(fapi::TARGET_TYPE_NONE); + } + do { + //============================== + // Initialize the logic + //============================== + + // Config path + // p8_pm_init.C enum: PM_CONFIG + FAPI_INVOKE_HWP( l_errl, + p8_pm_init, + l_fapiTarg0, + l_fapiTarg1, + PM_CONFIG ); + + if ( l_errl != NULL ) + { + o_failedTarget = i_target0; + TRACFCOMP( g_fapiImpTd, + ERR_MRK"startOCC: p8_pm_init, config failed!"); + l_errl->collectTrace(FAPI_TRACE_NAME,256); + l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256); + break; + } + + // Init path + // p8_pm_init.C enum: PM_INIT + FAPI_INVOKE_HWP( l_errl, + p8_pm_init, + l_fapiTarg0, + l_fapiTarg1, + PM_INIT ); + + if ( l_errl != NULL ) + { + o_failedTarget = i_target0; + TRACFCOMP( g_fapiImpTd, + ERR_MRK"startOCC: p8_pm_init, init failed!" ); + l_errl->collectTrace(FAPI_TRACE_NAME,256); + l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256); + + break; + } + + //============================== + //Start the OCC on primary chip of DCM + //============================== + FAPI_INVOKE_HWP( l_errl, + p8_occ_control, + l_fapiTarg0, + PPC405_RESET_OFF, + PPC405_BOOT_MEM ); + + if ( l_errl != NULL ) + { + o_failedTarget = i_target0; + TRACFCOMP( g_fapiImpTd, + ERR_MRK"startOCC: occ_control failed!"); + l_errl->collectTrace(FAPI_TRACE_NAME,256); + l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256); + + break; + } + + //============================== + // Start the OCC on slave chip of DCM + //============================== + if ( l_fapiTarg1.getType() != fapi::TARGET_TYPE_NONE ) + { + FAPI_INVOKE_HWP( l_errl, + p8_occ_control, + l_fapiTarg1, + PPC405_RESET_OFF, + PPC405_BOOT_MEM ); + + if ( l_errl != NULL ) + { + o_failedTarget = i_target1; + TRACFCOMP( g_fapiImpTd, + ERR_MRK"startOCCocc_control failed on slave chip!"); + l_errl->collectTrace(FAPI_TRACE_NAME,256); + l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256); + + break; + } + } + } while (0); + + TRACFCOMP( g_fapiTd, + EXIT_MRK"startOCC"); + return l_errl; + } + + /** + * @brief Stop OCC for specified DCM pair of processors. + * If 2nd input is NULL, OCC will be setup on just + * one target. + */ + errlHndl_t stopOCC(TARGETING::Target * i_target0, + TARGETING::Target * i_target1) + { + TRACFCOMP( g_fapiTd, + ENTER_MRK"stopOCC"); + errlHndl_t err = NULL; + do + { + const fapi::Target + l_fapiTarg0(fapi::TARGET_TYPE_PROC_CHIP, + (const_cast<TARGETING::Target*>(i_target0))); + + fapi::Target l_fapiTarg1; + if(i_target1) + { + l_fapiTarg1.setType(fapi::TARGET_TYPE_PROC_CHIP); + l_fapiTarg1.set(const_cast<TARGETING::Target*>(i_target1)); + + } + else + { + l_fapiTarg1.setType(fapi::TARGET_TYPE_NONE); + } + + FAPI_INVOKE_HWP( err, + p8_pm_prep_for_reset, + l_fapiTarg0, + l_fapiTarg1, + PM_RESET ); + + if ( err != NULL ) + { + TRACFCOMP( g_fapiTd, + ERR_MRK"stopOCC:p8_pm_prep_for_reset failed!" ); + err->collectTrace(FAPI_TRACE_NAME,256); + err->collectTrace(FAPI_IMP_TRACE_NAME,256); + + break; + } + + } while(0); + + TRACFCOMP( g_fapiTd, + EXIT_MRK"stopOCC"); + return err; + } + + /** + * @brief Stops OCCs on all Processors in the node + */ + errlHndl_t stopAllOCCs() + { + TRACFCOMP( g_fapiTd,ENTER_MRK"stopAllOCCs" ); + errlHndl_t l_errl = NULL; + bool winkle_loaded = false; + do { + +#ifndef __HOSTBOOT_RUNTIME + //OCC requires the build_winkle_images library + if ( !VFS::module_is_loaded( "libbuild_winkle_images.so" ) ) + { + l_errl = VFS::module_load( "libbuild_winkle_images.so" ); + + if ( l_errl ) + { + // load module returned with errl set + TRACFCOMP( g_fapiTd,ERR_MRK"loadnStartAllOccs: Could not load build_winkle module" ); + // break from do loop if error occured + break; + } + winkle_loaded = true; + } +#endif + + + TargetHandleList procChips; + getAllChips(procChips, TYPE_PROC, true); + + if(procChips.size() == 0) + { + TRACFCOMP( g_fapiTd,INFO_MRK"loadnStartAllOccs: No processors found" ); + //We'll never get this far in the IPL without any processors, + // so just exit. + break; + } + + TRACFCOMP( g_fapiTd, + INFO_MRK"loadnStartAllOccs: %d procs found", + procChips.size()); + + //The OCC Procedures require processors within a DCM be + //setup together. If DCM installed is set, we work under + //the assumption that each nodeID is a DCM. So sort the + //list by NodeID then call OCC Procedures on NodeID pairs. + std::sort(procChips.begin(), + procChips.end(), + orderByNodeAndPosition); + + //The OCC master for the node must be reset last. For all + //OP systems there is only a single OCC that can be the + //master so it is safe to look at the MASTER_CAPABLE flag. + Target* masterProc0 = NULL; + Target* masterProc1 = NULL; + + TargetHandleList::iterator itr1 = procChips.begin(); + + if(0 == (*itr1)->getAttr<ATTR_PROC_DCM_INSTALLED>()) + { + TRACUCOMP( g_fapiTd, + INFO_MRK"stopAllOCCs: non-dcm path entered"); + + for (TargetHandleList::iterator itr = procChips.begin(); + itr != procChips.end(); + ++itr) + { + TargetHandleList pOccs; + getChildChiplets(pOccs, *itr, TYPE_OCC); + if (pOccs.size() > 0) + { + if( pOccs[0]->getAttr<ATTR_OCC_MASTER_CAPABLE>() ) + { + masterProc0 = *itr; + continue; + } + } + + l_errl = HBOCC::stopOCC( *itr, NULL ); + if (l_errl) + { + TRACFCOMP( g_fapiImpTd, ERR_MRK"stopAllOCCs: stop failed"); + errlCommit (l_errl, HWPF_COMP_ID); + // just commit and try the next chip + } + } + if (l_errl) + { + break; + } + } + else + { + TRACFCOMP( g_fapiTd, + INFO_MRK"stopAllOCCs: Following DCM Path"); + + for (TargetHandleList::iterator itr = procChips.begin(); + itr != procChips.end(); + ++itr) + { + Target* targ0 = *itr; + Target* targ1 = NULL; + + TRACFCOMP( g_fapiImpTd, INFO_MRK"stopAllOCCs: Cur target nodeID=%d", + targ0->getAttr<ATTR_FABRIC_GROUP_ID>()); + + //if the next target in the list is in the same node + // they are on the same DCM, so bump itr forward + // and update targ0 pointer + if((itr+1) != procChips.end()) + { + TRACFCOMP( g_fapiImpTd, INFO_MRK"stopAllOCCs: n+1 target nodeID=%d", ((*(itr+1))->getAttr<ATTR_FABRIC_GROUP_ID>())); + + if((targ0->getAttr<ATTR_FABRIC_GROUP_ID>()) == + ((*(itr+1))->getAttr<ATTR_FABRIC_GROUP_ID>())) + { + //need to flip the numbers because we were reversed + targ1 = targ0; + itr++; + targ0 = *itr; + } + } + + TargetHandleList pOccs; + getChildChiplets(pOccs, targ0, TYPE_OCC); + if (pOccs.size() > 0) + { + if( pOccs[0]->getAttr<ATTR_OCC_MASTER_CAPABLE>() ) + { + masterProc0 = targ0; + masterProc1 = targ1; + continue; + } + } + + l_errl = HBOCC::stopOCC( targ0, targ1 ); + if (l_errl) + { + TRACFCOMP( g_fapiImpTd, ERR_MRK"stopAllOCCs: stop failed"); + errlCommit (l_errl, HWPF_COMP_ID); + // just commit and try the next module + } + } + if (l_errl) + { + break; + } + } + + //now do the master OCC + if( masterProc0 ) + { + l_errl = HBOCC::stopOCC( masterProc0, masterProc1 ); + if (l_errl) + { + TRACFCOMP( g_fapiImpTd, ERR_MRK"stopAllOCCs: stop failed on master"); + break; + } + } + } while(0); + + //make sure we always unload the module if we loaded it + if (winkle_loaded) + { +#ifndef __HOSTBOOT_RUNTIME + errlHndl_t l_tmpErrl = + VFS::module_unload( "libbuild_winkle_images.so" ); + if ( l_tmpErrl ) + { + TRACFCOMP( g_fapiTd,ERR_MRK"stopAllOCCs: Error unloading build_winkle module" ); + if(l_errl) + { + errlCommit( l_tmpErrl, HWPF_COMP_ID ); + } + else + { + l_errl = l_tmpErrl; + } + } +#endif + } + + TRACFCOMP( g_fapiTd,EXIT_MRK"stopAllOCCs" ); + return l_errl; + } + +} //end OCC namespace + diff --git a/src/usr/occ/p8_pmc_force_vsafe.C b/src/usr/occ/p8_pmc_force_vsafe.C new file mode 100644 index 000000000..3bd59b986 --- /dev/null +++ b/src/usr/occ/p8_pmc_force_vsafe.C @@ -0,0 +1,517 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/occ/p8_pmc_force_vsafe.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2013,2016 */ +/* [+] 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. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: p8_pmc_force_vsafe.C,v 1.18 2014/04/24 16:54:18 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/p8_pmc_force_vsafe.C,v $ +//------------------------------------------------------------------------------ +// *! (C) Copyright International Business Machines Corp. 2011 +// *! All Rights Reserved -- Property of IBM +// *! *** *** +//------------------------------------------------------------------------------ +// *! OWNER NAME: Joe Procwriter Email: asmartpersion@xx.ibm.com +// *! +// *! General Description: Forces the PMC to VSAFE mode +// *! +// *! The purpose of this procedure is to ...... +// *! +// *! High-level procedure flow: +// *! o Do thing 1 +// *! o Do thing 2 +// *! o Do thing 3 +// *! o Check if all went well +// *! o If so celebrate +// *! o Else write logs, set bad return code +// *! +// *! Procedure Prereq: +// *! o System clocks are running +// *! +// buildfapiprcd -e ../../xml/error_info/p8_force_vsafe_errors.xml,../../xml/error_info/p8_pstate_registers.xml p8_pmc_force_vsafe.C + +// ----------------------------------------------------------------------------- +// Write a voltage value into +// PVSAFE - PMC_PARAMETER_REG1 +// Actually, this value will be been written outside this procedure by the OCC pstate installation routine after the p8_build_pstate runs to build +// the Pstate superstructure. We had identified a HWP ATTR (ATTR_PM_PVSAFE_PSTATE) to be used by p8_pmc_init to set this up originally but we're +// going away from that approach so that we have all things about Pstates being done in one place (the OCC pstate installation routine). +// So, this step should not exist in the p8_pmc_force_vsafe procedure; rather, you should write a value into the hardware with a script that +// represents what the OCC pstate install routine would have done + +// ------------------ +// | Procedure Starts | +// ------------------ +// | +// | +// V +// Write into PMC_OCC_HEARTBEAT_REG +// PMC_OCC_HEARTBEAT_TIME - Write the field to 0 to cause an immediate heartbeat loss. +// PMC_OCC_HEARTBEAT_EN - this bit needs to be 1 to acually cause the 0 time value to trigger the heartbeat loss. +// | +// | +// V +// POLL PMC_STATUS_REG (8) +// VOLT_CHG_ONGOING (bit 8) Yes... this bit needs to be 0 to indicate that the voltage controller is at its target. + +// 1.3V Turbo to 0.8V (most of the supported range) in 25mV steps (the eVRM step size with iVRMs enabled) is 20 steps which, at 12.5mV/5us rate +// (a modest time), yields 8us. Given this an error case, we need a conservative time. So let's set the timeout at 100us for the lab. +// To test the timeout, clear PMC.PMC_MODE_REG (3) (with a script) so that the PMC won't respond. + + + + +// Check that the other bits in PMC_STATUS_REG do not indicate errors (eg they should be all zeros). If any are 1 +// | ^ +// | | +// V | +// timeout ------ + +// ---------------------------------------------------------------------- +// Flowchart Ends +// ---------------------------------------------------------------------- + +// ---------------------------------------------------------------------- +// Includes +// ---------------------------------------------------------------------- +#include <fapi.H> +#include "p8_scom_addresses.H" + +extern "C" { + +using namespace fapi; + +// ---------------------------------------------------------------------- +// Constant definitions +// ---------------------------------------------------------------------- + + +// ---------------------------------------------------------------------- +// Global variables +// ---------------------------------------------------------------------- + + +// ---------------------------------------------------------------------- +// Function prototypes +// ---------------------------------------------------------------------- + + +// ---------------------------------------------------------------------- +// Function definitions +// ---------------------------------------------------------------------- + + +// function: xxx +/// \param[in] i_target Chip target +// returns: ECMD_SUCCESS if something good happens, +// BAD_RETURN_CODE otherwise +fapi::ReturnCode +p8_pmc_force_vsafe( const fapi::Target& i_target, + const fapi::Target& i_dcm_target) +{ + fapi::ReturnCode rc; + ecmdDataBufferBase data(64); + ecmdDataBufferBase pmcstatusreg(64); + uint32_t e_rc = 0; + + // maximum number of status poll attempts to make before giving up + const uint32_t MAX_POLL_ATTEMPTS = 0x200; + + uint32_t count = 0; + uint16_t pvsafe = 0; + bool l_set; + uint16_t pstate_target = 0; + uint16_t pstate_step_target = 0; + uint16_t pstate_actual = 0; + uint8_t DONE_FLAG = 0; + uint8_t pmc_error = 0; + uint8_t intchp_error = 0; + uint8_t any_error = 0; + uint8_t any_ongoing = 0; + uint8_t dummy = 0; + + FAPI_INF("p8_pmc_force_vsafe start to primary target %s", + i_target.toEcmdString()); + + do + { + // ****************************************************************** + // - PMC_MODE_REG checking + // ****************************************************************** + rc = fapiGetScom(i_target, PMC_MODE_REG_0x00062000, data ); + if (rc) + { + FAPI_ERR("fapiGetScom(PMC_MODE_REG_0x00062000) failed."); + break; + } + + + if ( (data.isBitClear(0) && data.isBitClear(1) )) + { + FAPI_INF("PMC is not in HARDWARE or FIRMWARE AUCTION MODE so hardware mechanism cannot be used."); + break; + } + + if ( ( data.isBitClear(3) )) + { + FAPI_ERR("PMC is disabled for Voltage changes"); + const fapi::Target & CHIP = i_target; + const uint64_t & PMCMODE = data.getDoubleWord(0); + FAPI_SET_HWP_ERROR(rc, RC_PROCPM_VOLTAGE_CHANGE_MODE_ERR); + break; + } + + if ( ( !data.isBitClear(5) )) + { + FAPI_ERR("PMC is disabled PMC_MASTER_SEQUENCER"); + const fapi::Target & CHIP = i_target; + const uint64_t & PMCMODE = data.getDoubleWord(0); + FAPI_SET_HWP_ERROR(rc, RC_PROCPM_MST_SEQUENCER_STATE_ERR); + break; + } + + // **************************************************************************** + // - PMC_STATE_MONITOR_AND_CTRL_REG PMC_PARAMETER_REG1 before the psafe + // **************************************************************************** + + rc = fapiGetScom(i_target, PMC_PARAMETER_REG1_0x00062006, data ); + if (rc) + { + FAPI_ERR("fapiGetScom(PMC_PARAMETER_REG1_0x00062006) failed."); + break; + } + + e_rc |= data.extractToRight( &pvsafe,22,8); + if (e_rc) + { + rc.setEcmdError(e_rc); + break; + } + + rc = fapiGetScom(i_target, PMC_PSTATE_MONITOR_AND_CTRL_REG_0x00062002, data ); + if (rc) + { + FAPI_ERR("fapiGetScom(PMC_PSTATE_MONITOR_AND_CTRL_REG_0x00062002) failed."); + break; + } + + e_rc |= data.extractToRight( &pstate_target,0,8); + e_rc |= data.extractToRight( &pstate_step_target,8,8); + e_rc |= data.extractToRight( &pstate_actual,16,8); + if (e_rc) + { + rc.setEcmdError(e_rc); + break; + } + + FAPI_INF(" voltage values before the hearbeat loss " ); + FAPI_INF(" pvsafe => %x , ptarget => %x , pstarget => %x ,pactual => %x " , pvsafe , pstate_target ,pstate_step_target , pstate_actual); + + // ****************************************************************** + // - SEE PMC_STATUS_REG if debug_mode ==1 + // ****************************************************************** + + rc = fapiGetScom(i_target, PMC_STATUS_REG_0x00062009, data ); + if (rc) + { + FAPI_ERR("fapiGetScom(PMC_STATUS_REG_0x00062009) failed."); + break; + } + FAPI_DBG(" debug_mode : status_b4_heartbeat_loss => 0x%16llx", data.getDoubleWord(0)); + + l_set = data.isBitSet(0); + FAPI_DBG(" pstate_processing_is_susp => %x ", l_set ) ; + l_set = data.isBitSet(1); + FAPI_DBG(" gpsa_bdcst_error => %x ", l_set ); + + e_rc = data.extractToRight( &dummy,2,3); + if (e_rc) + { + rc.setEcmdError(e_rc); + break; + } + FAPI_DBG(" gpsa_bdcst_resp_info => %x ", dummy ); + l_set = data.isBitSet(5); + FAPI_DBG(" gpsa_vchg_error => %x ", l_set ); + l_set = data.isBitSet(6); + FAPI_DBG(" gpsa_timeout_error => %x ", l_set ); + l_set = data.isBitSet(7); + FAPI_DBG(" gpsa_chg_ongoing => %x ", l_set ); + l_set = data.isBitSet(8); + FAPI_DBG(" volt_chg_ongoing => %x ", l_set ); + l_set = data.isBitSet(9); + FAPI_DBG(" brd_cst_ongoing => %x ", l_set ); + l_set = data.isBitSet(10); + FAPI_DBG(" gpsa_table_error => %x ", l_set ); + l_set = data.isBitSet(11); + FAPI_DBG(" pstate_interchip_error => %x ", l_set ); + l_set = data.isBitSet(12); + FAPI_DBG(" istate_processing_is_susp => %x ", l_set ); + + + // ****************************************************************** + // - PMC_OCC_HEARTBEAT_REG + // ****************************************************************** + + FAPI_INF("Forcing PMC Heartbeat loss "); + + e_rc |= data.flushTo0(); + e_rc |= data.setBit(16); + if (e_rc) + { + rc.setEcmdError(e_rc); + break; + } + + rc = fapiPutScom(i_target, PMC_OCC_HEARTBEAT_REG_0x00062066, data ); + if (rc) + { + FAPI_ERR("fapiPutScom(PMC_OCC_HEARTBEAT_REG_0x00062066) failed."); + break; + } + + // delay to reduce number of polling loops + rc = fapiDelay(1000, 1000); + + // ****************************************************************** + // POLL for PMC_STATUS_REG --> BIT_8 to go to 0 or any errors + // ****************************************************************** + FAPI_DBG("Start polling for ongoing to go low ... "); + // Loop only if count is less thean poll attempts and DONE_FLAG = 0 and no error + for(count=0; ((count<=MAX_POLL_ATTEMPTS) && (DONE_FLAG == 0) && (any_error == 0)); count++) + { + rc = fapiGetScom(i_target, PMC_STATUS_REG_0x00062009, pmcstatusreg ); + if (rc) + { + FAPI_ERR("fapiGetScom(PMC_STATUS_REG_0x00062009) failed."); + break; + } + + FAPI_DBG(" PMC Status poll => 0x%16llx", pmcstatusreg.getDoubleWord(0)); + + pmc_error = ( pmcstatusreg.isBitSet(1) || // GPSA_BDCST_ERROR + pmcstatusreg.isBitSet(5) || // GPSA_VCHG_ERROR + pmcstatusreg.isBitSet(6) || // GPSA_TIMEOUT_ERROR + pmcstatusreg.isBitSet(10) || // GPS_TABLE_ERROR + pmcstatusreg.isBitSet(12) ); // ISTATE_PROCESSING_IS_SUSPENDED + + any_ongoing = ( pmcstatusreg.isBitSet(7) || // GPSA_CHG_ONGOING + pmcstatusreg.isBitSet(8) || // VOLT_CHG_ONGOING + pmcstatusreg.isBitSet(9) ); // BRD_CST_ONGOING + + + // If there is an interchip error, determine if it is expected or not + // Unexpected: gpsa_timeout or ECC UE error + if (pmcstatusreg.isBitSet(11)) // PSTATE_INTERCHIP_ERROR + { + rc = fapiGetScom(i_target, PMC_INTCHP_STATUS_REG_0x00062013, data ); + if (rc) + { + FAPI_ERR("fapiGetScom(PMC_STATUS_REG_0x00062009) failed."); + break; + } + + intchp_error = (data.isBitSet(18) || // GPSA_TIMEOUT_ERROR + data.isBitSet(19) ); // ECC UE ERROR + } + + any_error = (pmc_error || intchp_error); + + // log status if voltage change has any error + // Due to SW258130 + // This block only dumps any detected hw error status + // without taking out an error log and stop the reset flow. + // Since this procedure is only used by p8_pm_prep_for_reset + // we will and should be able to recover from such hardware errors + // by going through occ reset flow, thus no FAPI error logged. + // Also since if hardware error occurs, there is no need to check + // for pstate ongoing or pstate equals to pvsafe due to possible + // hardware stuck; therefore, this if/else logic remains. + if (any_error) + { + // dump individual error status + FAPI_INF(" PMC_STATUS_REG upon Error"); + if (pmcstatusreg.isBitSet(0)) + FAPI_INF(" pstate_processing_is_susp active"); + if (pmcstatusreg.isBitSet(1)) + FAPI_INF(" gpsa_bdcst_error active"); + + e_rc = pmcstatusreg.extractToRight( &dummy,2,3); + if (e_rc) + { + rc.setEcmdError(e_rc); + break; + } + if (dummy) + FAPI_INF(" gpsa_bdcst_resp_info is non-zero => %x ", dummy ); + + if (pmcstatusreg.isBitSet(5)) + FAPI_INF(" gpsa_vchg_error active"); + if (pmcstatusreg.isBitSet(6)) + FAPI_INF(" gpsa_timeout_error active"); + if (pmcstatusreg.isBitSet(7)) + FAPI_INF(" gpsa_chg_ongoing active"); + if (pmcstatusreg.isBitSet(8)) + FAPI_INF(" volt_chg_ongoing active"); + if (pmcstatusreg.isBitSet(9)) + FAPI_INF(" brd_cst_ongoing active"); + if (pmcstatusreg.isBitSet(10)) + FAPI_INF(" gpsa_table_error active"); + if (pmcstatusreg.isBitSet(11)) + FAPI_INF(" pstate_interchip_error active"); + if (pmcstatusreg.isBitSet(12)) + FAPI_INF(" istate_processing_is_susp active"); + + FAPI_INF("Status dumpped with PMC on-going deassertion during safe voltage movement, now continue on reset"); + } // end of status log if + else if (any_ongoing == 0) + { + // Voltage change done (not on-going) and not errors + FAPI_INF("PMC completed performing safe mode transition"); + l_set = pmcstatusreg.isBitSet(0); + if (l_set) FAPI_INF(" pstate_processing_is_susp => %x ", l_set ) ; + + l_set = pmcstatusreg.isBitSet(1); + if (l_set) FAPI_INF(" gpsa_bdcst_error => %x ", l_set ); + + e_rc = pmcstatusreg.extractToRight( &dummy,2,3); + if (e_rc) + { + rc.setEcmdError(e_rc); + break; + } + if (l_set) FAPI_INF(" gpsa_bdcst_resp_info => %x ", dummy ); + + l_set = pmcstatusreg.isBitSet(5); + if (l_set) FAPI_INF(" gpsa_vchg_error => %x ", l_set ); + + l_set = pmcstatusreg.isBitSet(6); + if (l_set) FAPI_INF(" gpsa_timeout_error => %x ", l_set ); + + l_set = pmcstatusreg.isBitSet(7); + if (l_set) FAPI_INF(" gpsa_chg_ongoing => %x ", l_set ); + + l_set = pmcstatusreg.isBitSet(8); + if (l_set) FAPI_INF(" volt_chg_ongoing => %x ", l_set ); + + l_set = pmcstatusreg.isBitSet(9); + if (l_set) FAPI_INF(" brd_cst_ongoing => %x ", l_set ); + + l_set = pmcstatusreg.isBitSet(10); + if (l_set) FAPI_INF(" gpsa_table_error => %x ", l_set ); + + l_set = pmcstatusreg.isBitSet(11); + if (l_set) FAPI_INF(" pstate_interchip_error => %x ", l_set ); + + l_set = pmcstatusreg.isBitSet(12); + if (l_set) FAPI_INF(" istate_processing_is_susp => %x ", l_set ); + + + rc = fapiGetScom(i_target, PMC_PARAMETER_REG1_0x00062006, data ); + if (rc) + { + FAPI_ERR("fapiGetScom(PMC_PARAMETER_REG1_0x00062006) failed."); + break; + } + + e_rc = data.extractToRight( &pvsafe,22,8); + if (e_rc) + { + rc.setEcmdError(e_rc); + break; + } + + rc = fapiGetScom(i_target, PMC_PSTATE_MONITOR_AND_CTRL_REG_0x00062002, data ); + if (rc) + { + FAPI_ERR("fapiGetScom(PMC_PSTATE_MONITOR_AND_CTRL_REG_0x00062002) failed."); + break; + } + + e_rc |= data.extractToRight( &pstate_target,0,8); + e_rc |= data.extractToRight( &pstate_step_target,8,8); + e_rc |= data.extractToRight( &pstate_actual,16,8); + if (e_rc) + { + rc.setEcmdError(e_rc); + break; + } + FAPI_INF(" pvsafe => %x , ptarget => %x , pstarget => %x ,pactual => %x " , pvsafe , pstate_target ,pstate_step_target , pstate_actual); + + // Check that PVSAFE Pstate (in PMC Parameter Reg1) is the value + // in the voltage stepper in the following fields of + // PMC_STATE_MONITOR_AND_CRTL_REG + // 0:7 - Global Pstate Target + // 8:15 - Global Pstate Step Target + // 16:23 - Global Pstate Actual + // if the above do not match, post an error + if (pstate_target != pvsafe || pstate_step_target != pvsafe || pstate_actual != pvsafe ) + { + FAPI_ERR("Pstate monitor and control register targets did not match"); + const fapi::Target & THISCHIP = i_target; + const fapi::Target & DCMCHIP = i_dcm_target; + const uint64_t & PSTATETARGET = (uint64_t)pstate_target; + const uint64_t & PSTATESTEPTARGET = (uint64_t)pstate_step_target; + const uint64_t & PSTATEACTUAL = (uint64_t)pstate_actual; + FAPI_SET_HWP_ERROR(rc, RC_PROCPM_PSTATE_MONITOR_ERR); + break; + } + DONE_FLAG = 1; + } + else // voltage change is ongoing so wait and then poll again + { + + // wait for 1 millisecond in hardware + rc = fapiDelay(1000*1000, 20000000); + if (rc) + { + FAPI_ERR("fapi delay ends up with error"); + break; + } + } + } // For loop + // Inner loop error check + if (!rc.ok()) + { + break; + } + + // Check if the above loop timed out + if (count>=MAX_POLL_ATTEMPTS) + { + FAPI_ERR("Timed out wait for voltage change on-going to drop"); + const uint64_t & PSTATETARGET = (uint64_t)pstate_target; + const uint64_t & PSTATESTEPTARGET = (uint64_t)pstate_step_target; + const uint64_t & PSTATEACTUAL = (uint64_t)pstate_actual; + const fapi::Target & THISCHIP = i_target; + const fapi::Target & DCMCHIP = i_dcm_target; + FAPI_SET_HWP_ERROR(rc, RC_PROCPM_VLT_TIMEOUT); + break; + } + + } while(0); + + FAPI_INF("p8_pmc_force_vsafe end ...."); + + return rc ; +} // Procedure + +} //end extern C diff --git a/src/usr/occ/p8_pmc_force_vsafe.H b/src/usr/occ/p8_pmc_force_vsafe.H new file mode 100755 index 000000000..eeec2b840 --- /dev/null +++ b/src/usr/occ/p8_pmc_force_vsafe.H @@ -0,0 +1,81 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/occ/p8_pmc_force_vsafe.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2013,2016 */ +/* [+] 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. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: p8_pmc_force_vsafe.H,v 1.3 2014/03/05 21:10:02 stillgs Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/p8_pmc_force_vsafe.H,v $ +//------------------------------------------------------------------------------ +// *| +// *! (C) Copyright International Business Machines Corp. 2011 +// *! All Rights Reserved -- Property of IBM +// *! *** *** +// *| +// *! TITLE : p8_pmc_force_vsafe.H +// *! DESCRIPTION : Force Safe voltage to the chip via PMC +// *! +// *! OWNER NAME : Greg Still Email: stillgs@us.ibm.com +// *! BACKUP NAME : Pradeep CN Email: padeepcn@in.ibm.com +// *! +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ + + +// function pointer typedef definition for HWP call support +typedef fapi::ReturnCode (*p8_pmc_force_vsafe_FP_t) (const fapi::Target&, + const fapi::Target& ); + +extern "C" { + + +//------------------------------------------------------------------------------ +// Constant definitions +//------------------------------------------------------------------------------ + + + +//------------------------------------------------------------------------------ +// Parameter structure definitions +//------------------------------------------------------------------------------ + + + +//------------------------------------------------------------------------------ +// Function prototype +//------------------------------------------------------------------------------ +/// \param[in] i_target Chip target +/// \param[in] i_dcm_target Chip target of the other DCM chip (for FFDC) + +/// \retval ECMD_SUCCESS if something good happens, +/// \retval BAD_RETURN_CODE otherwise +fapi::ReturnCode +p8_pmc_force_vsafe( const fapi::Target& i_target, + const fapi::Target& i_dcm_target ); + + +} // extern "C" + + diff --git a/src/usr/occ/runtime/makefile b/src/usr/occ/runtime/makefile new file mode 100644 index 000000000..008798945 --- /dev/null +++ b/src/usr/occ/runtime/makefile @@ -0,0 +1,39 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/occ/runtime/makefile $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# [+] 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. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + +HOSTBOOT_RUNTIME = 1 + +ROOTPATH = ../../../../../.. +VPATH += ../ + +MODULE = occ_rt + +## Objects unique to HBRT +OBJS += rt_occ.o + +## Objects common to HBRT and HB IPL +include ../occ.mk + +include ${ROOTPATH}/config.mk diff --git a/src/usr/occ/runtime/rt_occ.C b/src/usr/occ/runtime/rt_occ.C new file mode 100644 index 000000000..a5a2126b0 --- /dev/null +++ b/src/usr/occ/runtime/rt_occ.C @@ -0,0 +1,486 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/occ/runtime/rt_occ.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ +/* [+] 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. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include <runtime/interface.h> +#include <kernel/console.H> + +#include <hwpf/hwp/occ/occ_common.H> + +#include <vmmconst.h> +#include <sys/misc.h> +#include <errno.h> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <util/utillidmgr.H> +#include <htmgt/htmgt.H> + +// targeting support +#include <targeting/common/commontargeting.H> +#include <targeting/common/utilFilter.H> +#include <targeting/common/targetservice.H> +#include <targeting/common/utilFilter.H> +#include <targeting/common/util.H> +#include <runtime/rt_targeting.H> + +// fapi support +#include <fapi.H> +#include <fapiPlatHwpInvoker.H> +#include <hwpf/plat/fapiPlatTrace.H> +#include <isteps/hwpf_reasoncodes.H> + +// Procedures +#include <p8_occ_control.H> +#include <p8_pba_bar_config.H> +#include <p8_pm_init.H> +#include <p8_pm_prep_for_reset.H> + +using namespace TARGETING; +// Trace + +extern trace_desc_t* g_fapiTd; // defined in rt_fapiPlatUtil.C + +namespace RT_OCC +{ + typedef std::vector<TARGETING::Target *> target_list_t; + + //------------------------------------------------------------------------ + + void process_occ_error (uint64_t i_chipId) + { +#ifdef CONFIG_HTMGT + TARGETING::Target* l_reportingOccTarget = NULL; + errlHndl_t err = RT_TARG::getHbTarget(i_chipId,l_reportingOccTarget); + if (err) + { + TRACFCOMP (g_fapiTd, ERR_MRK"process_occ_error: getHbTarget" + " failed at %d chipId", i_chipId); + errlCommit (err, HWPF_COMP_ID); + } + else + { + HTMGT::processOccError(l_reportingOccTarget); + } +#else + TRACFCOMP(g_fapiTd, ERR_MRK"Unexpected call to process_occ_error(%d)" + " when HTMGT is not enabled", i_chipId); +#endif + } + + //------------------------------------------------------------------------ + + void process_occ_reset (uint64_t i_chipId) + { +#ifdef CONFIG_HTMGT + TARGETING::Target* l_failedOccTarget = NULL; + errlHndl_t err = RT_TARG::getHbTarget(i_chipId,l_failedOccTarget); + if (err) + { + TRACFCOMP (g_fapiTd, ERR_MRK"process_occ_reset: getHbTarget" + " failed at %d chipId", i_chipId); + errlCommit (err, HWPF_COMP_ID); + } + else + { + HTMGT::processOccReset(l_failedOccTarget); + } +#else + TRACFCOMP(g_fapiTd, ERR_MRK"Unexpected call to process_occ_reset(%d)" + " when HTMGT is not enabled", i_chipId); +#endif + } + + //------------------------------------------------------------------------ + + int enable_occ_actuation (int i_occ_activation) + { + int rc = 0; +#ifdef CONFIG_HTMGT + errlHndl_t err = HTMGT::enableOccActuation(0 != i_occ_activation); + if (err) + { + rc = err->reasonCode(); + if (0 == rc) + { + // If there was a failure, be sure to return non-zero status + rc = -1; + } + TRACFCOMP (g_fapiTd,ERR_MRK"enable_occ_actuation: OCC state change" + " failed with rc=0x%04X (actuate=%d)", + err->reasonCode(), i_occ_activation); + errlCommit (err, HWPF_COMP_ID); + } +#else + rc = -1; + TRACFCOMP(g_fapiTd,ERR_MRK"Unexpected call to enable_occ_actuation(%d)" + " when HTMGT is not enabled", i_occ_activation); +#endif + return rc; + } + + //------------------------------------------------------------------------ + + int htmgt_pass_thru (uint16_t i_cmdLength, + uint8_t * i_cmdData, + uint16_t * o_rspLength, + uint8_t * o_rspData) + { + int rc = 0; +#ifdef CONFIG_HTMGT + errlHndl_t err = HTMGT::passThruCommand(i_cmdLength, i_cmdData, + *o_rspLength, o_rspData); + if (err) + { + rc = err->reasonCode(); + if (0 == rc) + { + // If there was a failure, be sure to return non-zero status + rc = -1; + } + if ((i_cmdLength > 0) && (NULL != i_cmdData)) + { + TRACFCOMP (g_fapiTd,ERR_MRK"htmgt_pass_thru: command 0x%02X" + " (%d bytes) failed with rc=0x%04X", + i_cmdData[0], i_cmdLength, err->reasonCode()); + } + errlCommit (err, HWPF_COMP_ID); + } +#else + o_rspLength = 0; +#endif + return rc; + } + + //------------------------------------------------------------------------ + + int executeLoadOCC(uint64_t i_homer_addr_phys, + uint64_t i_homer_addr_va, + uint64_t i_common_addr_phys, + uint64_t i_common_addr_va, + uint64_t i_proc_chip) + { + errlHndl_t err = NULL; + int rc = 0; + + TRACFCOMP( g_fapiTd, + "LoadOCC: homer paddr=%016llx vaddr=%016llx. " + " common paddr=%016lx vaddr=%016llx. RtProcChip=%llx", + i_homer_addr_phys, + i_homer_addr_va, + i_common_addr_phys, + i_common_addr_va, + i_proc_chip); + + do + { + // Utility to convert i_proc_chip to Target + TARGETING::Target* proc_target = NULL; + err = RT_TARG::getHbTarget(i_proc_chip, proc_target); + if(err) + { + rc = EINVAL; + break; + } + err = HBOCC::loadOCC(proc_target, + i_homer_addr_phys, + i_homer_addr_va, + i_common_addr_phys); + if( err ) + { + break; + } + + void* occHostVirt = reinterpret_cast <void *> (i_homer_addr_va + + HOMER_OFFSET_TO_OCC_HOST_DATA); + err = HBOCC::loadHostDataToHomer(proc_target,occHostVirt); + if( err != NULL ) + { + TRACFCOMP( g_fapiImpTd, ERR_MRK"loading Host Data Area failed!" ); + break; + } + + } while(0); + + if ( err ) + { + uint64_t status = err->plid(); + errlCommit( err, HWPF_COMP_ID ); + + if(g_hostInterfaces && + g_hostInterfaces->report_failure) + { + + g_hostInterfaces->report_failure(status, + i_proc_chip); + } + + if(rc == 0) + { + rc = -1; + } + } + return rc; + } + + //------------------------------------------------------------------------ + + int executeOnDcms(HBOCC::occAction_t i_action, + uint64_t * i_proc_chip, + size_t i_num_chips) + { + errlHndl_t err = NULL; + int rc = 0; + TARGETING::Target* l_failedTarget = NULL; + TRACFCOMP( g_fapiTd, + "Action=%d, number of procs = %d ", + i_action, + i_num_chips); + + for(size_t i = 0; i < i_num_chips; ++i) + { + TRACFCOMP( g_fapiTd, "\tRtProcChip %llx", i_proc_chip[i]); + } + + do + { + if(i_num_chips < 1 || i_proc_chip == NULL) + { + rc = EINVAL; + break; + } + + // Convert chipIds to HB targets + target_list_t targets; + targets.reserve(i_num_chips); + + for(size_t i = 0; i < i_num_chips; ++i) + { + TARGETING::Target* proc_target = NULL; + err = RT_TARG::getHbTarget(i_proc_chip[i], proc_target); + if( err ) + { + rc = EINVAL; + break; + } + targets.push_back(proc_target); + } + if (err) + { + break; + } + + // If there are no DCMs INSTALLED the do on each proc + target_list_t::iterator itarg = targets.begin(); + if (0 == (*itarg)->getAttr<ATTR_PROC_DCM_INSTALLED>()) + { + for(itarg = targets.begin(); + itarg != targets.end(); + ++itarg) + { + if(i_action == HBOCC::OCC_START) + { + err = HBOCC::startOCC(*itarg, NULL, l_failedTarget); + } + else if(i_action == HBOCC::OCC_STOP) + { + err = HBOCC::stopOCC(*itarg, NULL); + } + + if( err ) + { + uint64_t status = err->plid(); + errlCommit( err, HWPF_COMP_ID ); + + if(g_hostInterfaces && + g_hostInterfaces->report_failure) + { + RT_TARG::rtChipId_t proc_chip = 0; + errlHndl_t err2 = + RT_TARG::getRtTarget(*itarg, proc_chip); + + if(err2) // should never happen + { + TRACFCOMP + (g_fapiTd, ERR_MRK + "Error converting target to RT chipID"); + errlCommit( err2, HWPF_COMP_ID ); + } + + g_hostInterfaces->report_failure(status, + proc_chip); + } + err = NULL; + rc = -1; + // keep going + } + } + break; // done + } + + // continue here only if have DCMs + // Sort the target list by node then pos + std::sort(targets.begin(), + targets.end(), + orderByNodeAndPosition); + + for(itarg = targets.begin(); + itarg != targets.end(); + ++itarg) + { + TARGETING::Target* t0 = *itarg; + TARGETING::Target* t1 = NULL; + if((itarg+1) != targets.end()) + { + if((t0->getAttr<ATTR_FABRIC_GROUP_ID>()) == + ((*(itarg+1))->getAttr<ATTR_FABRIC_GROUP_ID>())) + { + ++itarg; + t1 = *itarg; + } + } + if(i_action == HBOCC::OCC_START) + { + err = HBOCC::startOCC(t0,t1, l_failedTarget); + } + else if(i_action == HBOCC::OCC_STOP) + { + err = HBOCC::stopOCC(t0,t1); + } + + if( err ) + { + uint64_t status = err->plid(); + errlCommit( err, HWPF_COMP_ID ); + + if(g_hostInterfaces && + g_hostInterfaces->report_failure) + { + RT_TARG::rtChipId_t proc_chip = 0; + errlHndl_t err2 = + RT_TARG::getRtTarget(t0, proc_chip); + + if(err2) // should never happen + { + TRACFCOMP + (g_fapiTd, ERR_MRK + "Error converting target to RT chipID"); + errlCommit( err2, HWPF_COMP_ID ); + } + + g_hostInterfaces->report_failure(status, + proc_chip); + + if(t1) + { + err2 = RT_TARG::getRtTarget(t1, proc_chip); + if(err2) // should never happen + { + TRACFCOMP + (g_fapiTd, ERR_MRK + "Error converting target to RT chipID"); + errlCommit( err2, HWPF_COMP_ID ); + } + + g_hostInterfaces->report_failure(status, + proc_chip); + } + } + err = NULL; + rc = -1; + // keep going + } + } + if( err ) + { + break; + } + + } while(0); + + + if( err ) + { + errlCommit( err, HWPF_COMP_ID ); + if(rc == 0) + { + rc = -1; + } + } + + return rc; + } + + int executeStartOCCs(uint64_t* i_proc_chip, + size_t i_num_chips) + { + return executeOnDcms(HBOCC::OCC_START, + i_proc_chip, + i_num_chips); + } + + int executeStopOCCs(uint64_t* i_proc_chip, + size_t i_num_chips) + { + return executeOnDcms(HBOCC::OCC_STOP, + i_proc_chip, + i_num_chips); + } + + //------------------------------------------------------------------------ + + struct registerOcc + { + registerOcc() + { + runtimeInterfaces_t * rt_intf = getRuntimeInterfaces(); + rt_intf->get_lid_list = &UtilLidMgr::getLidList; + rt_intf->occ_load = &executeLoadOCC; + rt_intf->occ_start = &executeStartOCCs; + rt_intf->occ_stop = &executeStopOCCs; + rt_intf->process_occ_error = &process_occ_error; + rt_intf->process_occ_reset = &process_occ_reset; + rt_intf->enable_occ_actuation = &enable_occ_actuation; + rt_intf->mfg_htmgt_pass_thru = &htmgt_pass_thru; + + // If we already loaded OCC during the IPL we need to fix up + // the virtual address because we're now not using virtual + // memory + + TargetHandleList procChips; + getAllChips(procChips, TYPE_PROC, true); + for (TargetHandleList::iterator itr = procChips.begin(); + itr != procChips.end(); + ++itr) + { + uint64_t l_instance = (*itr)->getAttr<ATTR_POSITION>(); + uint64_t l_homerAddr = + g_hostInterfaces->get_reserved_mem("ibm,homer-image", + l_instance); + (*itr)->setAttr<ATTR_HOMER_VIRT_ADDR>(l_homerAddr); + } + } + }; + + registerOcc g_registerOcc; +} + |

