summaryrefslogtreecommitdiffstats
path: root/src/usr/hwpf/hwp/occ/occ.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/hwpf/hwp/occ/occ.C')
-rw-r--r--src/usr/hwpf/hwp/occ/occ.C587
1 files changed, 494 insertions, 93 deletions
diff --git a/src/usr/hwpf/hwp/occ/occ.C b/src/usr/hwpf/hwp/occ/occ.C
index 2d42091c1..2d6792145 100644
--- a/src/usr/hwpf/hwp/occ/occ.C
+++ b/src/usr/hwpf/hwp/occ/occ.C
@@ -34,6 +34,7 @@
// targeting support
#include <targeting/common/commontargeting.H>
#include <targeting/common/utilFilter.H>
+#include <targeting/common/targetservice.H>
// fapi support
#include <fapi.H>
@@ -51,18 +52,54 @@
#include <p8_pm_init.H>
#include <p8_pm_firinit.H>
+// Easy macro replace for unit testing
+//#define TRACUCOMP(args...) TRACFCOMP(args)
+#define TRACUCOMP(args...)
+
extern trace_desc_t* g_fapiTd;
+using namespace TARGETING;
+
const uint32_t g_OCCLIDID = 0x81e00430;
+const uint64_t OCC_IBSCOM_RANGE_IN_MB = 0x100000; /*128*1024*8*/
-namespace OCC
+///////////////////////////////////////////////////////////////////////////////
+// compareNodeId
+///////////////////////////////////////////////////////////////////////////////
+bool compareNodeId( Target* t0,
+ Target* t1)
{
+ uint8_t nodeId0 = t0->getAttr<ATTR_FABRIC_NODE_ID>();
+ uint8_t nodeId1 = t1->getAttr<ATTR_FABRIC_NODE_ID>();
- errlHndl_t loadOCCImageToHomer(uint64_t i_homer_addr )
+ if (nodeId0 == nodeId1)
{
- errlHndl_t l_errl = NULL;
- void* mapped_homer = NULL;
+ return t0 < t1;
+ }
+ return nodeId0 < nodeId1;
+}
+
+
+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(g_OCCLIDID);
@@ -76,11 +113,7 @@ namespace OCC
break;
}
- //Map homer into virtual memory
- mapped_homer =
- mmio_dev_map(reinterpret_cast<void*>(i_homer_addr), THIRTYTWO_MB);
-
- l_errl = lidMgr.getLid(mapped_homer, lidSize);
+ l_errl = lidMgr.getLid(i_occVirtAddr, lidSize);
if(l_errl)
{
TRACFCOMP( g_fapiImpTd,
@@ -91,77 +124,128 @@ namespace OCC
}while(0);
- if(mapped_homer)
- {
- int rc = 0;
- errlHndl_t l_tmpErrl = NULL;
- rc = mmio_dev_unmap(mapped_homer);
- if (rc != 0)
- {
- /*@
- * @errortype
- * @moduleid fapi::MOD_OCC_LOAD_OCC_IMAGE_TO_HOMER
- * @reasoncode fapi::RC_MMIO_UNMAP_ERR
- * @userdata1 Return Code
- * @userdata2 Unmap address
- * @devdesc mmio_dev_unmap() returns error
- */
- l_tmpErrl =
- new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- fapi::MOD_OCC_LOAD_OCC_IMAGE_TO_HOMER,
- fapi::RC_MMIO_UNMAP_ERR,
- rc,
- reinterpret_cast<uint64_t>
- (mapped_homer));
- if(l_tmpErrl)
- {
- if(l_errl)
- {
- errlCommit( l_tmpErrl, HWPF_COMP_ID );
- }
- else
- {
- l_errl = l_tmpErrl;
- }
- }
- }
- }
+ TRACUCOMP( g_fapiTd,
+ ENTER_MRK"loadOCCImageToHomer");
return l_errl;
}
- errlHndl_t loadnStartOcc(uint64_t i_homer_addr,
- uint64_t i_common_addr,
- TARGETING::Target* i_target)
+ /**
+ * @brief Sets up OCC Host data
+ *
+ * @param[in] i_occHostDataVirtAddr Virtual
+ * address of current
+ * proc's Host data area.
+ *
+ * @return errlHndl_t Error log Host data setup failed
+ */
+ errlHndl_t loadHostDataToHomer(void* i_occHostDataVirtAddr)
{
+ TRACUCOMP( g_fapiTd,
+ ENTER_MRK"loadHostDataToHomer(%p)",
+ i_occHostDataVirtAddr);
+
errlHndl_t l_errl = NULL;
- TRACDCOMP( g_fapiTd,
- "loadnStartOcc entry" );
+ struct occHostConfigDataArea_t
+ {
+ uint32_t version;
+ uint32_t nestFrequency;
+ };
+ enum { OccHostDataVersion = 1 };
+
+ //Treat virtual address as starting pointer
+ //for config struct
+ occHostConfigDataArea_t * config_data =
+ reinterpret_cast<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 = OccHostDataVersion;
+ config_data->nestFrequency = nestFreq;
+
+ TRACUCOMP( g_fapiTd,
+ EXIT_MRK"loadHostDataToHomer");
+
+ return l_errl;
+ }
+
+ /**
+ * @brief Execute procedures and steps necessary
+ * to load OCC data in specified processor
+ *
+ * @param[in] i_target Target proc to load
+ * @param[in] i_homerVirtAddrBase Virtual
+ * address of current
+ * procs HOMER
+ *
+ * @return errlHndl_t Error log image load failed
+ */
+ errlHndl_t load(Target* i_target,
+ void* i_homerVirtAddrBase)
+ {
+ errlHndl_t l_errl = NULL;
+ uint64_t targHomer = 0;
+ uint64_t tmpOffset = 0;
+ void* occVirt = 0;
+ void* occHostVirt = 0;
+
+ TRACFCOMP( g_fapiTd,
+ ENTER_MRK"HBOCC:load()" );
+
+ do{
+
+ //Figure out OCC image offset for Target
+ //OCC image offset = HOMER_SIZE*ProcPosition +
+ // OCC offset within HOMR (happens to be zero)
+ uint8_t tmpPos = i_target->getAttr<ATTR_POSITION>();
+ tmpOffset = tmpPos*VMM_HOMER_INSTANCE_SIZE +
+ HOMER_OFFSET_TO_OCC_IMG;
+ targHomer = VMM_HOMER_REGION_START_ADDR +
+ tmpOffset;
+ occVirt =
+ reinterpret_cast<void *>
+ (reinterpret_cast<uint64_t>(i_homerVirtAddrBase)
+ + tmpOffset) ;
+
+ //Figure out OCC Host Data offset for Target
+ //OCC host data offset = HOMER_SIZE*ProcPosition +
+ // OCC data within HOMR
+ tmpOffset = tmpPos*VMM_HOMER_INSTANCE_SIZE +
+ HOMER_OFFSET_TO_OCC_HOST_DATA;
+ occHostVirt =
+ reinterpret_cast<void *>
+ (reinterpret_cast<uint64_t>(i_homerVirtAddrBase)
+ + tmpOffset) ;
- do {
// cast OUR type of target to a FAPI type of target.
const fapi::Target
l_fapiTarg(fapi::TARGET_TYPE_PROC_CHIP,
- (const_cast<TARGETING::Target*>(i_target)));
-
+ (const_cast<Target*>(i_target)));
//==============================
//Setup for OCC Load
//==============================
- //TODO: put this const in the common location with HOMER struct
- //RTC: 50987
// BAR0 is the Entire HOMER (start of HOMER contains OCC base Image)
// Bar size is in MB, obtained value of 4MB from Greg Still
- const uint32_t bar0_size_MB = 4;
+ const uint64_t bar0_size_MB = VMM_HOMER_INSTANCE_SIZE_IN_MB;
+ TRACUCOMP( g_fapiImpTd,
+ INFO_MRK"OCC Address: 0x%.8X, size=0x%.8X",
+ targHomer, bar0_size_MB );
+
FAPI_INVOKE_HWP( l_errl,
p8_pba_bar_config,
l_fapiTarg,
- 0, i_homer_addr, bar0_size_MB,
+ 0, targHomer, bar0_size_MB,
PBA_CMD_SCOPE_NODAL );
if ( l_errl != NULL )
@@ -174,15 +258,42 @@ namespace OCC
break;
}
- //TODO: put this const in the common location with HOMER struct
- //RTC: 50987
- // BAR3 is the OCC Common Area
+ // 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
+ OCC_IBSCOM_RANGE_IN_MB, //i_pba_bar_size
+ PBA_CMD_SCOPE_NODAL ); //i_pba_cmd_scope
+
+ if ( l_errl != NULL )
+ {
+ TRACFCOMP( g_fapiImpTd,
+ ERR_MRK"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
- const uint32_t bar3_size_MB = 8;
+ const uint64_t bar3_size_MB = VMM_OCC_COMMON_SIZE_IN_MB;
+ const uint64_t occ_common_addr = VMM_OCC_COMMON_START_ADDR;
+
+ TRACUCOMP( g_fapiImpTd,
+ INFO_MRK"OCC Common Address: 0x%.8X, size=0x%.8X",
+ occ_common_addr, bar3_size_MB );
+
FAPI_INVOKE_HWP( l_errl,
p8_pba_bar_config,
l_fapiTarg,
- 3, i_common_addr, bar3_size_MB,
+ 3, occ_common_addr,
+ bar3_size_MB,
PBA_CMD_SCOPE_NODAL );
if ( l_errl != NULL )
@@ -195,13 +306,112 @@ namespace OCC
break;
}
- //TODO: This flow needs to be updated along with procedure refresh
- //RTC: 68461
+ //==============================
+ //Load the OCC HOMER image
+ //==============================
+ l_errl = loadOCCImageToHomer( occVirt );
+ if( l_errl != NULL )
+ {
+ TRACFCOMP( g_fapiImpTd, ERR_MRK"loading image failed!" );
+ break;
+ }
+
+ //==============================
+ //Setup host data area of HOMER;
+ //==============================
+ l_errl = loadHostDataToHomer(occHostVirt);
+ if( l_errl != NULL )
+ {
+ TRACFCOMP( g_fapiImpTd, ERR_MRK"loading Host Data Area failed!" );
+ break;
+ }
+
+ }while(0);
+
+ TRACFCOMP( g_fapiTd,
+ EXIT_MRK"HBOCC:load()" );
+
+ return l_errl;
+
+ }
+
+ /**
+ * @brief Load and Start OCC for specified DCM
+ * pair of processors. If 2nd input target
+ * is NULL, OCC will be setup on just the
+ * one target.
+ *
+ * @param[in] i_target0 Target of first proc in
+ * DCM pair
+ * @param[in] i_target1 Target of second proc in
+ * DCM pair
+ * @param[in] i_homerVirtAddrBase Base Virtual
+ * address of all HOMER
+ * images
+ *
+ * @return errlHndl_t Error log image load failed
+ */
+ errlHndl_t loadnStartOcc(Target* i_target0,
+ Target* i_target1,
+ void* i_homerVirtAddrBase)
+ {
+ errlHndl_t l_errl = NULL;
+
+ TRACUCOMP( g_fapiTd,
+ ENTER_MRK"loadnStartOcc" );
+
+
+ do {
+ // 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);
+ }
+
+ //==============================
+ //Setup and load oCC
+ //==============================
+
+ l_errl = load(i_target0,
+ i_homerVirtAddrBase);
+ if(l_errl != NULL)
+ {
+ TRACFCOMP( g_fapiImpTd, ERR_MRK"loadnStartOcc: load failed for target 0" );
+ break;
+ }
+
+ if(i_target1 != NULL)
+ {
+ l_errl = load(i_target1,
+ i_homerVirtAddrBase);
+ if(l_errl != NULL)
+ {
+ TRACFCOMP( g_fapiImpTd, ERR_MRK"loadnStartOcc: load failed for target 1" );
+ break;
+ }
+ }
+ //==============================
+ // Initialize the logic
+ //==============================
+
// Config path
// p8_pm_init.C enum: PM_CONFIG
FAPI_INVOKE_HWP( l_errl,
p8_pm_init,
- l_fapiTarg,
+ l_fapiTarg0,
+ l_fapiTarg1,
PM_CONFIG );
if ( l_errl != NULL )
@@ -218,7 +428,8 @@ namespace OCC
// p8_pm_init.C enum: PM_INIT
FAPI_INVOKE_HWP( l_errl,
p8_pm_init,
- l_fapiTarg,
+ l_fapiTarg0,
+ l_fapiTarg1,
PM_INIT );
if ( l_errl != NULL )
@@ -233,15 +444,20 @@ namespace OCC
TRACFCOMP( g_fapiImpTd,
INFO_MRK"OCC Finished: p8_pm_init.C enum: PM_INIT" );
- // Firinit
- // p8_pm_firinit.C
+
+ //==============================
+ //Start the OCC on primary chip of DCM
+ //==============================
FAPI_INVOKE_HWP( l_errl,
- p8_pm_firinit,
- l_fapiTarg );
+ p8_occ_control,
+ l_fapiTarg0,
+ PPC405_RESET_OFF,
+ PPC405_BOOT_MEM );
+
if ( l_errl != NULL )
{
TRACFCOMP( g_fapiImpTd,
- ERR_MRK"p8_pm_firinit, failed!" );
+ ERR_MRK"occ_control failed!" );
l_errl->collectTrace(FAPI_TRACE_NAME,256);
l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256);
@@ -249,43 +465,228 @@ namespace OCC
}
//==============================
- //Load the OCC HOMER image
+ // Start the OCC on slave chip of DCM
//==============================
- l_errl = loadOCCImageToHomer( i_homer_addr );
- if( l_errl != NULL )
+ if ( l_fapiTarg1.getType() != fapi::TARGET_TYPE_NONE )
{
- TRACFCOMP( g_fapiImpTd, ERR_MRK"loading images failed!" );
- break;
+ FAPI_INVOKE_HWP( l_errl,
+ p8_occ_control,
+ l_fapiTarg1,
+ PPC405_RESET_OFF,
+ PPC405_BOOT_MEM );
+
+ if ( l_errl != NULL )
+ {
+ TRACFCOMP( g_fapiImpTd,
+ ERR_MRK"occ_control failed!" );
+ l_errl->collectTrace(FAPI_TRACE_NAME,256);
+ l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256);
+
+ break;
+ }
}
- //TODO RTC:50987 - Fill in OCC data areas in HOMER. See Story
- // 49595 for details.
+ } while(0);
- //==============================
- //Start the OCC image
- //==============================
- FAPI_INVOKE_HWP( l_errl,
- p8_occ_control,
- l_fapiTarg,
- PPC405_RESET_OFF,
- PPC405_BOOT_MEM );
+ TRACUCOMP( g_fapiTd,
+ EXIT_MRK"loadnStartOcc" );
- if ( l_errl != NULL )
+ return l_errl;
+ }
+
+
+ ////////////////////////////////////////////////
+ errlHndl_t loadnStartAllOccs()
+ {
+ errlHndl_t l_errl = NULL;
+ void* homerVirtAddrBase = NULL;
+ bool winkle_loaded = false;
+
+ TRACUCOMP( g_fapiTd,
+ ENTER_MRK"loadnStartAllOccs" );
+
+ do {
+ //OCC requires the build_winkle_images library
+ if ( !VFS::module_is_loaded( "libbuild_winkle_images.so" ) )
{
- TRACFCOMP( g_fapiImpTd,
- ERR_MRK"occ_control failed!" );
- l_errl->collectTrace(FAPI_TRACE_NAME,256);
- l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256);
+ 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 if anyone ever changes VMM_HOMER_REGION_SIZE to not
+ //equal 32MB because mmio_dev_map won't support it
+ assert(VMM_HOMER_REGION_SIZE == THIRTYTWO_MB,
+ "loadnStartAllOccs: Unsupported HOMER Region size");
+
+ //Map entire homer region into virtual memory
+ homerVirtAddrBase =
+ mmio_dev_map(reinterpret_cast<void*>(VMM_HOMER_REGION_START_ADDR),
+ THIRTYTWO_MB);
+
+ 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());
+
+ //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.
+
+ TargetHandleList::iterator itr1 = procChips.begin();
+
+ if(0 ==
+ (*itr1)->getAttr<ATTR_PROC_DCM_INSTALLED>())
+ {
+ for (TargetHandleList::iterator itr = procChips.begin();
+ itr != procChips.end();
+ ++itr)
+ {
+ l_errl = loadnStartOcc(*itr,
+ NULL,
+ homerVirtAddrBase);
+ if(l_errl)
+ {
+ TRACFCOMP( g_fapiImpTd, ERR_MRK"loadnStartAllOccs: loadnStartOcc failed!" );
+ break;
+ }
+ }
+
+
+ }
+ else
+ {
+ TRACUCOMP( g_fapiTd,
+ INFO_MRK"loadnStartAllOccs: Following DCM Path");
+
+ std::sort(procChips.begin(), procChips.end(), compareNodeId);
+
+ 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_NODE_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_NODE_ID>()));
+
+ if((targ0->getAttr<ATTR_FABRIC_NODE_ID>()) ==
+ ((*(itr+1))->getAttr<ATTR_FABRIC_NODE_ID>()))
+ {
+ itr++;
+ targ1 = *itr;
+ }
+ }
+ TRACUCOMP( g_fapiImpTd, INFO_MRK"loadnStartAllOccs: calling loadnStartOcc." );
+ l_errl = loadnStartOcc(targ0,
+ targ1,
+ homerVirtAddrBase);
+ if(l_errl)
+ {
+ TRACFCOMP( g_fapiImpTd, ERR_MRK"loadnStartAllOccs: loadnStartOcc failed!" );
+ break;
+ }
+ }
+ }
+
} while(0);
- TRACDCOMP( g_fapiTd,
- "loadnStartOcc Exit" );
+ errlHndl_t l_tmpErrl = NULL;
+ if(homerVirtAddrBase)
+ {
+ int rc = 0;
+ rc = mmio_dev_unmap(homerVirtAddrBase);
+ if (rc != 0)
+ {
+ /*@
+ * @errortype
+ * @moduleid fapi::MOD_OCC_LOAD_START_ALL_OCCS
+ * @reasoncode fapi::RC_MMIO_UNMAP_ERR
+ * @userdata1 Return Code
+ * @userdata2 Unmap address
+ * @devdesc mmio_dev_unmap() returns error
+ */
+ l_tmpErrl =
+ new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ fapi::MOD_OCC_LOAD_START_ALL_OCCS,
+ fapi::RC_MMIO_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;
+ }
+ }
+ }
+ }
+
+ //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;
}
+
+
} //end OCC namespace
OpenPOWER on IntegriCloud