diff options
author | Ilya Smirnov <ismirno@us.ibm.com> | 2017-07-28 10:55:14 -0500 |
---|---|---|
committer | William G. Hoffa <wghoffa@us.ibm.com> | 2017-08-23 14:28:43 -0400 |
commit | e5790aed63a53234a4ae733b5b351feae9e81670 (patch) | |
tree | c191b191a43cd3cb191aa7a1e8e46ad86ef1ca75 /src | |
parent | a8cbc4f396c1c3555e133aebded97ee03398925d (diff) | |
download | talos-hostboot-e5790aed63a53234a4ae733b5b351feae9e81670.tar.gz talos-hostboot-e5790aed63a53234a4ae733b5b351feae9e81670.zip |
IPL Time Checkstop Analysis Part 2: Start OCC
Created a function that calls the necessary HWPs to start OCC
Change-Id: Id94820dc1f8105bb183a25ddef88ab32bda7db97
RTC:155065
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/43863
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Reviewed-by: Gregory S. Still <stillgs@us.ibm.com>
Reviewed-by: William G. Hoffa <wghoffa@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/isteps/pm/occCheckstop.H | 19 | ||||
-rw-r--r-- | src/usr/diag/HBconfig | 3 | ||||
-rw-r--r-- | src/usr/isteps/istep06/host_start_occ_xstop_handler.C | 5 | ||||
-rw-r--r-- | src/usr/isteps/pm/occCheckstop.C | 255 |
4 files changed, 277 insertions, 5 deletions
diff --git a/src/include/usr/isteps/pm/occCheckstop.H b/src/include/usr/isteps/pm/occCheckstop.H index 10efd4897..026c8db55 100644 --- a/src/include/usr/isteps/pm/occCheckstop.H +++ b/src/include/usr/isteps/pm/occCheckstop.H @@ -53,16 +53,20 @@ namespace HBOCC OCC_GPE1_SRAM_ADDRESS = 0xFFF10000, // SRAM Address and length for FIR HOMER data - OCC_SRAM_FIR_DATA = 0xFFFBA000, - OCC_SRAM_FIR_LENGTH = 0x3000, + OCC_SRAM_FIR_DATA = 0xFFFBD000, + OCC_SRAM_FIR_LENGTH = 0x1000, // offsets for OCC loading during IPL OCC_OFFSET_LENGTH = 0x48, OCC_OFFSET_GPE0_LENGTH = 0x64, OCC_OFFSET_GPE1_LENGTH = 0x68, + OCC_OFFSET_MAIN_EP = 0x6C, OCC_OFFSET_IPL_FLAG = 0x92, OCC_OFFSET_FREQ = 0x94, + OCC_BRANCH_INSTR = 0x4B00000200000000, + BRANCH_ADDR_MASK = 0x00FFFFFC, + }; enum occAction_t @@ -97,6 +101,17 @@ namespace HBOCC #endif #ifdef CONFIG_IPLTIME_CHECKSTOP_ANALYSIS + + /** + * @brief Starts OCC that has been loaded to SRAM (used during IPL time + * checkstop analysis. + * + * @param[in] i_target: the proc we're operating on (should be masterproc) + * + * @return errlHndl_t Error log if start fails + */ + errlHndl_t startOCCFromSRAM(TARGETING::Target* i_proc); + /** * @brief Loads the OCC image from PNOR to SRAM * diff --git a/src/usr/diag/HBconfig b/src/usr/diag/HBconfig index cf4aa6da8..965c24ee5 100644 --- a/src/usr/diag/HBconfig +++ b/src/usr/diag/HBconfig @@ -9,8 +9,9 @@ config ENABLE_CHECKSTOP_ANALYSIS Enable collection of FIR data by OCC for checkstops and post-checkstop analysis by PRD on system reboot +#TODO RTC:178806 Re-enable once simics defect is fixed config IPLTIME_CHECKSTOP_ANALYSIS - default y + default n help Enable collection of FIR data by the OCC for checkstops during the IPL. diff --git a/src/usr/isteps/istep06/host_start_occ_xstop_handler.C b/src/usr/isteps/istep06/host_start_occ_xstop_handler.C index d75a9ec62..aa3c6b8c3 100644 --- a/src/usr/isteps/istep06/host_start_occ_xstop_handler.C +++ b/src/usr/isteps/istep06/host_start_occ_xstop_handler.C @@ -33,6 +33,7 @@ #include <sys/mm.h> #include <pm/pm_common.H> #include <targeting/common/commontargeting.H> +#include <isteps/pm/occCheckstop.H> namespace ISTEP_06 { @@ -75,11 +76,11 @@ void* host_start_occ_xstop_handler( void *io_pArgs ) break; } - //l_errl = HBPM::startPMComplex(masterproc); + l_errl = HBOCC::startOCCFromSRAM(masterproc); if(l_errl) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, - "startPMComplex failed"); + "startOCCFromSRAM failed"); l_stepError.addErrorDetails(l_errl); ERRORLOG::errlCommit(l_errl, HWPF_COMP_ID); break; diff --git a/src/usr/isteps/pm/occCheckstop.C b/src/usr/isteps/pm/occCheckstop.C index 62d1ad8f8..8c8fb2a0a 100644 --- a/src/usr/isteps/pm/occCheckstop.C +++ b/src/usr/isteps/pm/occCheckstop.C @@ -54,6 +54,7 @@ #include <arch/ppc.H> #include <fapi2.H> +#include <fapi2/plat_hwp_invoker.H> #include <pnorif.H> #include <pnor_const.H> @@ -63,9 +64,14 @@ #include <diag/prdf/prdfWriteHomerFirData.H> #endif +#include <p9_pm_utils.H> +#include <p9_pm_init.H> + // Easy macro replace for unit testing //#define TRACUCOMP(args...) TRACFCOMP(args) #define TRACUCOMP(args...) +#define OCB_OITR0 0x6C008 +#define OCB_OIEPR0 0x6C00C extern trace_desc_t* g_fapiTd; extern trace_desc_t* g_fapiImpTd; @@ -76,6 +82,254 @@ namespace HBOCC { #ifdef CONFIG_IPLTIME_CHECKSTOP_ANALYSIS + + errlHndl_t makeStart405Instruction(const TARGETING::Target* i_target, + uint64_t* o_instr) + { + errlHndl_t l_errl = NULL; + uint64_t l_epAddr; + + l_errl = HBOCC::readSRAM(i_target, + OCC_405_SRAM_ADDRESS + OCC_OFFSET_MAIN_EP, + &l_epAddr, + sizeof(uint64_t)); + + // The branch instruction is of the form 0x4BXXXXX200000000, where X + // is the address of the 405 main's entry point (alligned as shown). + // Example: If 405 main's EP is FFF5B570, then the branch instruction + // will be 0x4bf5b57200000000. The last two bits of the first byte of + // the branch instruction must be '2' according to the OCC instruction + // set manual. + *o_instr = OCC_BRANCH_INSTR | + (((uint64_t)(BRANCH_ADDR_MASK & l_epAddr)) << 32); + TRACFCOMP(g_fapiTd, "makeStart405Instruction instruction = %16x", + *o_instr); + return l_errl; + } + + errlHndl_t startOCCFromSRAM(TARGETING::Target* i_proc) + { + TRACUCOMP(g_fapiTd, ENTER_MRK"startOCCFromSRAM"); + + errlHndl_t l_errl = NULL; + uint64_t l_start405MainInstr = 0; + + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>l_target(i_proc); + fapi2::ReturnCode l_rc; + + do { + // ************************************************************ + // Initialize Cores and Quads + // ************************************************************ + FAPI_DBG("Executing p9_pm_corequad_init to" + " initialize cores & quads"); + FAPI_INVOKE_HWP(l_errl, p9_pm_corequad_init, + l_target, + p9pm::PM_INIT, + 0,//CME FIR MASK for reset + 0,//Core Error Mask for reset + 0 //Quad Error Mask for reset + ); + if(l_errl) + { + TRACFCOMP(g_fapiTd, + "ERROR: Failed to initialize cores & quads"); + break; + } + + // ************************************************************ + // Issue init to OCB + // ************************************************************ + FAPI_DBG("Executing p9_pm_ocb_init to initialize OCB channels"); + FAPI_INVOKE_HWP(l_errl, p9_pm_ocb_init, + l_target, + p9pm::PM_INIT,// Channel setup type + p9ocb::OCB_CHAN1,// Channel + p9ocb:: OCB_TYPE_NULL,// Channel type + 0,// Channel base address + 0,// Push/Pull queue length + p9ocb::OCB_Q_OUFLOW_NULL,// Channel flow control + p9ocb::OCB_Q_ITPTYPE_NULL// Channel interrupt ctrl + ); + if(l_errl) + { + TRACFCOMP(g_fapiTd, "ERROR: Failed to initialize channel 1"); + break; + } + + // ************************************************************ + // Initializes P2S and HWC logic + // ************************************************************ + FAPI_DBG("Executing p9_pm_pss_init"); + FAPI_INVOKE_HWP(l_errl, p9_pm_pss_init, l_target, p9pm::PM_INIT); + if(l_errl) + { + TRACFCOMP(g_fapiTd, "ERROR: Failed to initialize PSS & HWC"); + break; + } + + // ************************************************************ + // Set the OCC FIR actions + // ************************************************************ + FAPI_DBG("Executing p9_pm_occ_firinit to set FIR actions."); + FAPI_INVOKE_HWP(l_errl, p9_pm_occ_firinit, l_target, p9pm::PM_INIT); + if(l_errl) + { + TRACFCOMP(g_fapiTd, "ERROR: Failed to set OCC FIR actions."); + break; + } + + // ************************************************************* + // Switch off OCC initiated special wakeup on EX to allowSTOP + // functionality + // ************************************************************* + FAPI_DBG("Clear off the wakeup"); + FAPI_INVOKE_HWP(l_errl, clear_occ_special_wakeups, l_target); + if(l_errl) + { + TRACFCOMP(g_fapiTd, "ERROR: Failed to clear off the wakeup"); + break; + } + + // ************************************************************ + // Take all EX chiplets out of special wakeup + // ************************************************************ + FAPI_DBG("Disable special wakeup for all functional" + " EX targets."); + FAPI_INVOKE_HWP(l_errl, special_wakeup_all, l_target, false); + if(l_errl) + { + TRACFCOMP(g_fapiTd, + "ERROR: Failed to remove EX chiplets from special wakeup"); + } + + // Hack provided by Doug Gilbert (@dgilbert). The following six + // scoms set up the communications between GPE0 and the 405. This + // allows to not load and start SGPE that is responsible for setting + // up the IRQ routing. + // TODO: RTC 178699 come up with a more permanent solution for + // communication setup + uint64_t l_writeData; + uint32_t l_writeAddress; + size_t l_writeSize = sizeof(l_writeData); + + l_writeAddress = 0x6C040; + l_writeData = 0x218780f800000000; + l_errl = deviceWrite(i_proc, &l_writeData, l_writeSize, + DEVICE_SCOM_ADDRESS(l_writeAddress)); + if(l_errl) + { + TRACFCOMP(g_fapiTd, "SCOM to address 0x%08x failed", + l_writeAddress); + break; + } + + l_writeAddress = 0x6C050; + l_writeData = 0x0003d03c00000000; + l_errl = deviceWrite(i_proc, &l_writeData, l_writeSize, + DEVICE_SCOM_ADDRESS(l_writeAddress)); + if(l_errl) + { + TRACFCOMP(g_fapiTd, "SCOM to address 0x%08x failed", + l_writeAddress); + break; + } + + l_writeAddress = 0x6C044; + l_writeData = 0x2181801800000000; + l_errl = deviceWrite(i_proc, &l_writeData, l_writeSize, + DEVICE_SCOM_ADDRESS(l_writeAddress)); + if(l_errl) + { + TRACFCOMP(g_fapiTd, "SCOM to address 0x%08x failed", + l_writeAddress); + break; + } + + l_writeAddress = 0x6C054; + l_writeData = 0x0003d00c00000000; + l_errl = deviceWrite(i_proc, &l_writeData, l_writeSize, + DEVICE_SCOM_ADDRESS(l_writeAddress)); + if(l_errl) + { + TRACFCOMP(g_fapiTd, "SCOM to address 0x%08x failed", + l_writeAddress); + break; + } + + l_writeAddress = 0x6C048; + l_writeData = 0x010280ac00000000; + l_errl = deviceWrite(i_proc, &l_writeData, l_writeSize, + DEVICE_SCOM_ADDRESS(l_writeAddress)); + if(l_errl) + { + TRACFCOMP(g_fapiTd, "SCOM to address 0x%08x failed", + l_writeAddress); + break; + } + + l_writeAddress = 0x6C058; + l_writeData = 0x0001901400000000; + l_errl = deviceWrite(i_proc, &l_writeData, l_writeSize, + DEVICE_SCOM_ADDRESS(l_writeAddress)); + if(l_errl) + { + TRACFCOMP(g_fapiTd, "SCOM to address 0x%08x failed", + l_writeAddress); + break; + } + + // ************************************************************ + // Start OCC PPC405 + // ************************************************************ + l_errl = makeStart405Instruction(i_proc, &l_start405MainInstr); + if(l_errl) + { + TRACFCOMP(g_fapiTd, "startOCCFromSRAM: could not make instr" + " to start 405 main"); + break; + } + FAPI_DBG("Executing p9_pm_occ_control to start OCC PPC405"); + FAPI_INVOKE_HWP(l_errl, p9_pm_occ_control, l_target, + p9occ_ctrl::PPC405_START,// Operation on PPC405 + p9occ_ctrl::PPC405_BOOT_WITHOUT_BL, // PPC405 boot loc + l_start405MainInstr); + if(l_errl) + { + TRACFCOMP(g_fapiTd, "ERROR: Failed to initialize OCC PPC405"); + break; + } + + // Set checkstop interrupt to be active-high and rising edge + // TODO RTC:178798 Remove the following workaround + l_writeAddress = OCB_OITR0; + l_writeData = 0xffffffffffffffff; + l_errl = deviceWrite(i_proc, &l_writeData, l_writeSize, + DEVICE_SCOM_ADDRESS(l_writeAddress)); + if(l_errl) + { + TRACFCOMP(g_fapiTd, "SCOM to address 0x%08x failed", + l_writeAddress); + break; + } + + l_writeAddress = OCB_OIEPR0; + l_writeData = 0xffffffffffffffff; + l_errl = deviceWrite(i_proc, &l_writeData, l_writeSize, + DEVICE_SCOM_ADDRESS(l_writeAddress)); + if(l_errl) + { + TRACFCOMP(g_fapiTd, "SCOM to address 0x%08x failed", + l_writeAddress); + break; + } + + + } while(0); + + return l_errl; + } + errlHndl_t loadOCCImageDuringIpl(TARGETING::Target* i_target, void* i_occVirtAddr) { @@ -267,6 +521,7 @@ namespace HBOCC return l_errl; } // loadHostDataToSRAM + #endif } //end HBOCC namespace |