/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* $Source: src/sbefw/app/power/ipl_table.C $ */ /* */ /* OpenPOWER sbe Project */ /* */ /* Contributors Listed Below - COPYRIGHT 2017,2019 */ /* [+] 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 "core/ipl.H" #include "sbecmdiplcontrol.H" #include "sbefifo.H" #include "sbetrace.H" #include "sbe_sp_intf.H" #include "sbeFifoMsgUtils.H" #include "assert.h" #include "sberegaccess.H" #include "sbestates.H" #include "sbecmdcntrldmt.H" #include "sbeglobals.H" // TODO Workaround #include "plat_target_parms.H" #include "fapi2.H" #include "p9_misc_scom_addresses_fld.H" #include "p9_perv_scom_addresses_fld.H" #include "p9n2_quad_scom_addresses.H" // Pervasive HWP Header Files ( istep 2) #include #include #include #include #include #include #include #include #include #include #include #include #include // Pervasive HWP Header Files ( istep 3) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Cache HWP header file #include #include #include #include // Core HWP header file #include // istep 5 hwp header files #include "p9_sbe_instruct_start.H" #include "p9_sbe_load_bootloader.H" // istep mpipl header files #include "p9_block_wakeup_intr.H" #include "p9_query_core_access_state.H" #include "p9_sbe_check_quiesce.H" #include "p9_l2_flush.H" #include "p9_l3_flush.H" #include "p9_sbe_sequence_drtm.H" #include "p9_thread_control.H" #include "sbecmdcntlinst.H" #include "p9_quad_power_off.H" #include "p9_hcd_cache_stopclocks.H" #include "p9_stopclocks.H" #include "p9_suspend_powman.H" #include "p9_query_cache_access_state.H" #include "sbeXipUtils.H" // For getting hbbl offset #include "sbeutil.H" // For getting SBE_TO_NEST_FREQ_FACTOR #include "p9_fbc_utils.H" #include "sbeSecureMemRegionManager.H" #include "sbeIPLStatusLPC.H" #include "sbeConsole.H" #include "sbecmdflushnvdimm.H" // Forward declaration using namespace fapi2; // constants static const uint32_t SBE_ROLE_MASK = 0x00000002; static const uint32_t SBE_SYSTEM_QUIESCE_TIMEOUT_LOOP = 20000; static const uint64_t SBE_LQA_DELAY_HW_US = 1000000ULL; // 1ms static const uint64_t SBE_LQA_DELAY_SIM_CYCLES = 0x1ULL; // Bit-33 used to checkstop the system, Since this is directly getting inserted // will have to use bit (63-33) = 30th bit static const uint64_t N3_FIR_SYSTEM_CHECKSTOP_BIT = 30; // 63-33 = 30 // Externs extern p9_thread_control_FP_t threadCntlhwp; extern uint64_t G_ring_save[8]; //Utility function to mask special attention extern ReturnCode maskSpecialAttn( const Target& i_target ); // Aliases using sbeIstepHwpProc_t = ReturnCode (*) (const Target & i_target); using sbeIstepHwpTpSwitchGears_t = ReturnCode (*) (const Target & i_target); using sbeIstepHwpEq_t = ReturnCode (*) (const Target & i_target); using sbeIstepHwpCore_t = ReturnCode (*) (const Target & i_target); using sbeIstepHwpExL2Flush_t = ReturnCode (*) (const Target & i_target, const p9core::purgeData_t & i_purgeData); using sbeIstepHwpExL3Flush_t = ReturnCode (*) (const Target & i_target, const uint32_t i_purgeType, const uint32_t i_purgeAddr); using sbeIstepHwpCoreBlockIntr_t = ReturnCode (*) (const Target & i_target, const p9pmblockwkup::OP_TYPE i_oper); using sbeIstepHwpCoreScomState_t = ReturnCode (*) (const Target & i_target, bool & o_isScom, bool & o_isScan); using sbeIstepHwpSequenceDrtm_t = ReturnCode (*) (const Target & i_target, uint8_t & o_status); using sbeIstepHwpQuadPoweroff_t = ReturnCode (*) (const Target & i_target, uint64_t * o_ring_save_data); using sbeIstepHwpCacheInitf_t = ReturnCode (*) (const Target & i_target, const uint64_t * i_ring_save_data); // Forward declarations // Wrapper function which will call HWP. ReturnCode istepWithProc( voidfuncptr_t i_hwp ); ReturnCode istepLpcInit( voidfuncptr_t i_hwp ); ReturnCode istepHwpTpSwitchGears( voidfuncptr_t i_hwp); ReturnCode istepAttrSetup( voidfuncptr_t i_hwp ); ReturnCode istepNoOp( voidfuncptr_t i_hwp ); ReturnCode istepWithEq( voidfuncptr_t i_hwp); ReturnCode istepWithCore( voidfuncptr_t i_hwp); ReturnCode istepSelectEx( voidfuncptr_t i_hwp); ReturnCode istepLoadBootLoader( voidfuncptr_t i_hwp); ReturnCode istepCheckSbeMaster( voidfuncptr_t i_hwp); ReturnCode istepStartInstruction( voidfuncptr_t i_hwp); ReturnCode istepWithCoreConditional( voidfuncptr_t i_hwp); ReturnCode istepWithEqConditional( voidfuncptr_t i_hwp); ReturnCode istepNestFreq( voidfuncptr_t i_hwp); ReturnCode istepCacheInitf( voidfuncptr_t i_hwp ); //MPIPL Specific ReturnCode istepWithCoreSetBlock( voidfuncptr_t i_hwp ); ReturnCode istepWithCoreState( voidfuncptr_t i_hwp ); ReturnCode istepMpiplRstClrTpmBits( voidfuncptr_t i_hwp ); ReturnCode istepWithProcQuiesceLQASet( voidfuncptr_t i_hwp ); ReturnCode istepWithExL2Flush( voidfuncptr_t i_hwp ); ReturnCode istepWithExL3Flush( voidfuncptr_t i_hwp ); ReturnCode istepStartMpipl( voidfuncptr_t i_hwp ); ReturnCode istepWithProcSequenceDrtm( voidfuncptr_t i_hwp ); ReturnCode istepMpiplSetFunctionalState( voidfuncptr_t i_hwp ); ReturnCode istepMpiplQuadPoweroff( voidfuncptr_t i_hwp ); ReturnCode istepStopClockMpipl( voidfuncptr_t i_hwp ); #ifndef __SBEFW_SEEPROM__ /* * --------------------------------------------- start PIBMEM CODE */ static istepMap_t g_istepMpiplStartPtrTbl[] = { #ifdef SEEPROM_IMAGE // Place holder for StartMpipl, State Change, PHB State Update, // Clear CRESP error latch register. // Set MPIPL mode in Sratch Reg 3 ISTEP_MAP( istepStartMpipl, NULL ), // Call suspend powerman ISTEP_MAP( istepWithProc, p9_suspend_powman ), // Find all the child cores within proc and call hwp to know the // scom state and call instruction control. Also mask spl attention // from core. ISTEP_MAP( istepWithCoreState, NULL ), // Reset the TPM and clear the TPM deconfig bit, it's not a // procedure but local SBE function ISTEP_MAP( istepMpiplRstClrTpmBits, NULL ), // quiesce state for all units on the powerbus on its chip ISTEP_MAP( istepWithProcQuiesceLQASet, p9_sbe_check_quiesce ), // L2 cache flush via purge engine on each EX ISTEP_MAP( istepWithExL2Flush, p9_l2_flush ), // L3 cache flush via purge engine on each EX ISTEP_MAP( istepWithExL3Flush, p9_l3_flush ), // Check on Quiescing of all Chips in a System by Local SBE ISTEP_MAP( istepWithProcSequenceDrtm, p9_sbe_sequence_drtm ), #endif }; static istepMap_t g_istepMpiplContinuePtrTbl[] = { #ifdef SEEPROM_IMAGE // Setup EC/EQ guard records ISTEP_MAP( istepMpiplSetFunctionalState, p9_sbe_select_ex), ISTEP_MAP( istepNoOp, NULL ), // Witherspoon only (mpipl_dump_reg) ISTEP_MAP( istepNoOp, NULL ), // Witherspoon only (mpipl_query_quad_access_state) ISTEP_MAP( istepNoOp, NULL ), // Witherspoon only (mpipl_hcd_core_stopclocks) ISTEP_MAP( istepNoOp, NULL ), // Witherspoon only (mpipl_hcd_cache_stopclocks) // p9_quad_power_off ISTEP_MAP( istepMpiplQuadPoweroff, p9_quad_power_off ), // No-op ISTEP_MAP( istepNoOp, NULL ), #endif }; static istepMap_t g_istepStopClockPtrTbl[] = { #ifdef SEEPROM_IMAGE // Stop Clock Mpipl ISTEP_MAP( istepStopClockMpipl, p9_stopclocks ), #endif }; // File static data static istepMap_t g_istep2PtrTbl[] = { #ifdef SEEPROM_IMAGE ISTEP_MAP( NULL, NULL ), ISTEP_MAP( istepAttrSetup, p9_sbe_attr_setup ), ISTEP_MAP( istepWithProc, p9_sbe_tp_chiplet_init1 ), ISTEP_MAP( istepWithProc, p9_sbe_tp_gptr_time_initf ), ISTEP_MAP( istepNoOp, NULL ), // DFT only ISTEP_MAP( istepWithProc, p9_sbe_npll_initf ), ISTEP_MAP( istepNestFreq, p9_sbe_npll_setup ), ISTEP_MAP( istepHwpTpSwitchGears, p9_sbe_tp_switch_gears ), ISTEP_MAP( istepWithProc, p9_sbe_clock_test2 ), ISTEP_MAP( istepWithProc, p9_sbe_tp_chiplet_reset ), ISTEP_MAP( istepWithProc, p9_sbe_tp_repr_initf ), ISTEP_MAP( istepWithProc, p9_sbe_tp_chiplet_init2 ), ISTEP_MAP( istepNoOp, NULL ), // DFT only ISTEP_MAP( istepWithProc, p9_sbe_tp_arrayinit ), ISTEP_MAP( istepWithProc, p9_sbe_tp_initf ), ISTEP_MAP( istepNoOp, NULL ), // DFT only ISTEP_MAP( istepWithProc, p9_sbe_tp_chiplet_init3 ), #endif }; static istepMap_t g_istep3PtrTbl[] = { #ifdef SEEPROM_IMAGE ISTEP_MAP( istepWithProc, p9_sbe_chiplet_reset ), ISTEP_MAP( istepWithProc, p9_sbe_gptr_time_initf ), ISTEP_MAP( istepWithProc, p9_sbe_chiplet_pll_initf ), ISTEP_MAP( istepWithProc, p9_sbe_chiplet_pll_setup ), ISTEP_MAP( istepWithProc, p9_sbe_repr_initf ), ISTEP_MAP( istepWithProc, p9_sbe_chiplet_init ), ISTEP_MAP( istepNoOp, NULL ), // DFT only ISTEP_MAP( istepWithProc, p9_sbe_arrayinit ), ISTEP_MAP( istepNoOp, NULL ), // DFT only ISTEP_MAP( istepWithProc, p9_sbe_tp_enable_ridi ), ISTEP_MAP( istepWithProc, p9_sbe_setup_boot_freq ), ISTEP_MAP( istepWithProc, p9_sbe_nest_initf ), ISTEP_MAP( istepWithProc, p9_sbe_nest_startclocks ), ISTEP_MAP( istepWithProc, p9_sbe_nest_enable_ridi ), ISTEP_MAP( istepWithProc, p9_sbe_io_initf ), ISTEP_MAP( istepWithProc, p9_sbe_startclock_chiplets ), ISTEP_MAP( istepWithProc, p9_sbe_scominit ), ISTEP_MAP( istepLpcInit, p9_sbe_lpc_init ), ISTEP_MAP( istepWithProc, p9_sbe_fabricinit ), ISTEP_MAP( istepCheckSbeMaster, NULL ), ISTEP_MAP( istepWithProc, p9_sbe_mcs_setup ), ISTEP_MAP( istepSelectEx, p9_sbe_select_ex ), #endif }; static istepMap_t g_istep4PtrTbl[] = { #ifdef SEEPROM_IMAGE ISTEP_MAP( istepWithEq, p9_hcd_cache_poweron ), ISTEP_MAP( istepWithEq, p9_hcd_cache_chiplet_reset ), ISTEP_MAP( istepWithEq, p9_hcd_cache_chiplet_l3_dcc_setup ), ISTEP_MAP( istepWithEq, p9_hcd_cache_gptr_time_initf ), ISTEP_MAP( istepWithEq, p9_hcd_cache_dpll_initf ), ISTEP_MAP( istepWithEq, p9_hcd_cache_dpll_setup ), ISTEP_MAP( istepWithEq, p9_hcd_cache_dcc_skewadjust_setup ), ISTEP_MAP( istepWithEq, p9_hcd_cache_chiplet_init ), ISTEP_MAP( istepWithEq, p9_hcd_cache_repair_initf ), ISTEP_MAP( istepWithEq, p9_hcd_cache_arrayinit ), ISTEP_MAP( istepNoOp, NULL ), // DFT Only ISTEP_MAP( istepNoOp, NULL ), // DFT Only ISTEP_MAP( istepCacheInitf, p9_hcd_cache_initf ), ISTEP_MAP( istepWithEqConditional, p9_hcd_cache_startclocks ), ISTEP_MAP( istepWithEqConditional, p9_hcd_cache_scominit ), ISTEP_MAP( istepWithEqConditional, p9_hcd_cache_scomcust ), ISTEP_MAP( istepNoOp, NULL ), // Runtime only ISTEP_MAP( istepNoOp, NULL ), // Runtime only ISTEP_MAP( istepNoOp, NULL ), // stub for SBE ISTEP_MAP( istepNoOp, NULL ), // stub for SBE ISTEP_MAP( istepWithCore, p9_hcd_core_poweron ), ISTEP_MAP( istepWithCore, p9_hcd_core_chiplet_reset ), ISTEP_MAP( istepWithCore, p9_hcd_core_gptr_time_initf ), ISTEP_MAP( istepWithCore, p9_hcd_core_chiplet_init ), ISTEP_MAP( istepWithCore, p9_hcd_core_repair_initf ), ISTEP_MAP( istepWithCore, p9_hcd_core_arrayinit ), ISTEP_MAP( istepNoOp, NULL ), // DFT Only ISTEP_MAP( istepNoOp, NULL ), // DFT Only ISTEP_MAP( istepWithCore, p9_hcd_core_initf ), ISTEP_MAP( istepWithCoreConditional, p9_hcd_core_startclocks ), ISTEP_MAP( istepWithCoreConditional, p9_hcd_core_scominit ), ISTEP_MAP( istepWithCoreConditional, p9_hcd_core_scomcust ), ISTEP_MAP( istepNoOp, NULL ), ISTEP_MAP( istepNoOp, NULL ), #endif }; // TODO via RTC 135345 // Add the support for istep 5 HWP static istepMap_t g_istep5PtrTbl[] { #ifdef SEEPROM_IMAGE ISTEP_MAP( istepLoadBootLoader, NULL ), ISTEP_MAP( istepStartInstruction, p9_sbe_instruct_start ), #endif }; istepTableEntry_t istepTableEntries[] = { ISTEP_ENTRY( 2, g_istep2PtrTbl), ISTEP_ENTRY( 3, g_istep3PtrTbl), ISTEP_ENTRY( 4, g_istep4PtrTbl), ISTEP_ENTRY( 5, g_istep5PtrTbl), ISTEP_ENTRY( 96, g_istepMpiplStartPtrTbl), ISTEP_ENTRY( 97, g_istepMpiplContinuePtrTbl), ISTEP_ENTRY( 98, g_istepStopClockPtrTbl), }; REGISTER_ISTEP_TABLE(istepTableEntries) //---------------------------------------------------------------------------- ReturnCode istepAttrSetup( voidfuncptr_t i_hwp) { return performAttrSetup(); } //---------------------------------------------------------------------------- ReturnCode istepWithProc( voidfuncptr_t i_hwp) { ReturnCode rc = FAPI2_RC_SUCCESS; Target proc = plat_getChipTarget(); assert( NULL != i_hwp ); SBE_EXEC_HWP(rc, reinterpret_cast( i_hwp ), proc) return rc; } //---------------------------------------------------------------------------- ReturnCode istepLpcInit( voidfuncptr_t i_hwp) { ReturnCode rc = FAPI2_RC_SUCCESS; Target proc = plat_getChipTarget(); assert( NULL != i_hwp ); SBE_EXEC_HWP(rc, reinterpret_cast( i_hwp ), proc) SBE_ISTEP_LPC_INIT; SBE_UART_INIT; SBE_MSG_CONSOLE( SBE_CONSOLE_WELCOME_MSG ); return rc; } //---------------------------------------------------------------------------- ReturnCode istepHwpTpSwitchGears( voidfuncptr_t i_hwp) { ReturnCode rc = FAPI2_RC_SUCCESS; Target proc = plat_getChipTarget(); assert( NULL != i_hwp ); SBE_EXEC_HWP(rc, reinterpret_cast( i_hwp ), proc) // backup i2c mode register uint32_t reg_address = PU_MODE_REGISTER_B; PPE_LVD( reg_address, SBE_GLOBAL->i2cModeRegister); return rc; } //---------------------------------------------------------------------------- ReturnCode istepNestFreq( voidfuncptr_t i_hwp) { #define SBE_FUNC "istepNestFreq " Target proc = plat_getChipTarget(); ReturnCode rc = FAPI2_RC_SUCCESS; assert( NULL != i_hwp ); do { SBE_EXEC_HWP(rc, reinterpret_cast( i_hwp ),proc) if( rc != FAPI2_RC_SUCCESS ) { break; } // Update PK frequency SBE::updatePkFreq(); }while(0); return rc; #undef SBE_FUNC } //---------------------------------------------------------------------------- ReturnCode istepSelectEx( voidfuncptr_t i_hwp) { ReturnCode rc = FAPI2_RC_SUCCESS; Target proc = plat_getChipTarget(); // TODO via RTC 135345 // Once multicast targets are supported, we may need to pass // p9selectex::ALL as input. SBE_EXEC_HWP(rc, reinterpret_cast(i_hwp), proc, p9selectex::SINGLE) return rc; } //---------------------------------------------------------------------------- ReturnCode istepWithEq( voidfuncptr_t i_hwp) { ReturnCode rc = FAPI2_RC_SUCCESS; // TODO via RTC 135345 // Curently we are passing Hard code eq target. Finally it is // going to be a multicast target. Once multicast support is // present, use the right target. fapi2::Target eqTgt; // Put this in scope so that vector can be freed up before calling hwp. { Target proc = plat_getChipTarget(); auto eqList = proc.getChildren(); // As it is workaround lets assume there will always be atleast one // functional eq. No need to validate. eqTgt = eqList[0]; } assert( NULL != i_hwp); SBE_EXEC_HWP(rc, reinterpret_cast(i_hwp), eqTgt ) return rc; } //---------------------------------------------------------------------------- ReturnCode istepCacheInitf (voidfuncptr_t i_hwp ) { #define SBE_FUNC "istepCacheInitf" SBE_ENTER(SBE_FUNC); ReturnCode l_rc = FAPI2_RC_SUCCESS; // TODO via RTC 135345 fapi2::Target eqTgt; // Put this in scope so that vector can be freed up before calling hwp. { Target proc = plat_getChipTarget(); auto eqList = proc.getChildren(); // As it is workaround lets assume there will always be atleast one // functional eq. No need to validate. eqTgt = eqList[0]; } SBE_EXEC_HWP(l_rc, reinterpret_cast( i_hwp ), eqTgt, G_ring_save) SBE_EXIT(SBE_FUNC); return l_rc; #undef SBE_FUNC } //---------------------------------------------------------------------------- ReturnCode istepWithCore( voidfuncptr_t i_hwp) { #define SBE_FUNC "istepWithCore" ReturnCode rc = FAPI2_RC_SUCCESS; // Get master Ex uint8_t exId = 0; uint8_t fuseMode = 0; Target proc = plat_getChipTarget(); FAPI_ATTR_GET(fapi2::ATTR_MASTER_EX,proc,exId); FAPI_ATTR_GET(ATTR_FUSED_CORE_MODE, Target(), fuseMode); fapi2::Target exTgt(plat_getTargetHandleByInstance(exId)); assert( NULL != i_hwp ); for (auto &coreTgt : exTgt.getChildren()) { // Core0 is assumed to be the master core SBE_EXEC_HWP(rc, reinterpret_cast(i_hwp), coreTgt) if(rc != FAPI2_RC_SUCCESS) { SBE_ERROR(SBE_FUNC " istepWithCore failed, RC=[0x%08X]", rc); break; } // Only continue in case of istep4 && fuse core mode if(!( (fuseMode) && (SbeRegAccess::theSbeRegAccess().getSbeMajorIstepNumber() == 4) ) ) { break; } } return rc; #undef SBE_FUNC } //---------------------------------------------------------------------------- ReturnCode istepWithEqConditional( voidfuncptr_t i_hwp) { SBE_ENTER("istepWithEqCondtional"); fapi2::Target sysTgt; ReturnCode rc = FAPI2_RC_SUCCESS; do { uint8_t iplPhase = ENUM_ATTR_SYSTEM_IPL_PHASE_HB_IPL; FAPI_ATTR_GET(ATTR_SYSTEM_IPL_PHASE, sysTgt, iplPhase); if( ENUM_ATTR_SYSTEM_IPL_PHASE_CACHE_CONTAINED == iplPhase ) { break; } rc = istepWithEq(i_hwp); }while(0); SBE_EXIT("istepWithEqCondtional"); return rc; } //---------------------------------------------------------------------------- ReturnCode istepWithCoreConditional( voidfuncptr_t i_hwp) { SBE_ENTER("istepWithCoreCondtional"); fapi2::Target sysTgt; ReturnCode rc = FAPI2_RC_SUCCESS; do { uint8_t iplPhase = ENUM_ATTR_SYSTEM_IPL_PHASE_HB_IPL; FAPI_ATTR_GET(ATTR_SYSTEM_IPL_PHASE, sysTgt, iplPhase); if( ENUM_ATTR_SYSTEM_IPL_PHASE_CACHE_CONTAINED == iplPhase ) { break; } rc = istepWithCore(i_hwp); }while(0); SBE_EXIT("istepWithCoreCondtional"); return rc; } //---------------------------------------------------------------------------- ReturnCode istepNoOp( voidfuncptr_t i_hwp) { SBE_INFO("istepNoOp"); return FAPI2_RC_SUCCESS ; } /* * end PIBMEMCODE ----------------------------------------------- */ #endif // #ifndef __SBEFW_SEEPROM__ #ifdef __SBEFW_SEEPROM__ //---------------------------------------------------------------------------- constexpr uint32_t HB_MEM_WINDOW_SIZE = 10*1024*1024; //10 MB ReturnCode istepLoadBootLoader( voidfuncptr_t i_hwp) { ReturnCode rc = FAPI2_RC_SUCCESS; // Get master Ex uint8_t exId = 0; Target< TARGET_TYPE_SYSTEM > sysTgt; Target proc = plat_getChipTarget(); FAPI_ATTR_GET(fapi2::ATTR_MASTER_EX,proc,exId); fapi2::Target exTgt(plat_getTargetHandleByInstance(exId)); // Get hbbl section P9XipHeader *hdr = getXipHdr(); P9XipSection *hbblSection = &(hdr->iv_section[P9_XIP_SECTION_SBE_HBBL]); uint64_t drawer_base_address_nm0, drawer_base_address_nm1; uint64_t drawer_base_address_m; uint64_t drawer_base_address_mmio; uint64_t l_hostboot_hrmor_offset; do { // Update the ATTR_SBE_ADDR_KEY_STASH_ADDR before calling the bootloader, // since it is going to access these data from inside. uint64_t addr = SBE_GLOBAL->sbeKeyAddrPair.fetchStashAddrAttribute(); PLAT_ATTR_INIT(fapi2::ATTR_SBE_ADDR_KEY_STASH_ADDR, sysTgt, addr); SBE_EXEC_HWP(rc, p9_sbe_load_bootloader, proc, exTgt, hbblSection->iv_size, getSectionAddr(hbblSection)) if(rc != FAPI2_RC_SUCCESS) { SBE_ERROR(" p9_sbe_load_bootloader failed"); break; } // Open HB Dump memory Region fapi2::Target FAPI_SYSTEM; FAPI_ATTR_GET(fapi2::ATTR_HOSTBOOT_HRMOR_OFFSET, FAPI_SYSTEM, l_hostboot_hrmor_offset); rc = p9_fbc_utils_get_chip_base_address_no_aliases( proc, HB_GRP_CHIP_IDS, drawer_base_address_nm0, drawer_base_address_nm1, drawer_base_address_m, drawer_base_address_mmio); if(rc != FAPI2_RC_SUCCESS) { SBE_ERROR(" p9_fbc_utils_get_chip_base_address failed"); break; } drawer_base_address_nm0 += l_hostboot_hrmor_offset; SBE_INFO("istep 5.1 HB Dump mem Region [0x%08X%08X]", SBE::higher32BWord(drawer_base_address_nm0), SBE::lower32BWord(drawer_base_address_nm0)); mainStoreSecMemRegionManager.add(drawer_base_address_nm0, HB_MEM_WINDOW_SIZE, static_cast(memRegionMode::READ)); } while(0); return rc; } //---------------------------------------------------------------------------- ReturnCode istepStartInstruction( voidfuncptr_t i_hwp) { ReturnCode rc = FAPI2_RC_SUCCESS; SBE_MSG_CONSOLE("SBE starting hostboot"); SBE_ISTEP_LPC_DISABLE; SBE_UART_DISABLE; rc = istepWithCore(i_hwp); if(rc == FAPI2_RC_SUCCESS) { (void)SbeRegAccess::theSbeRegAccess().stateTransition( SBE_RUNTIME_EVENT); } return rc; } //---------------------------------------------------------------------------- ReturnCode istepCheckSbeMaster( voidfuncptr_t i_hwp) { #define SBE_FUNC "istepCheckSbeMaster " ReturnCode rc = FAPI2_RC_SUCCESS; do { rc = performTpmReset(); if( rc != FAPI2_RC_SUCCESS ) { SBE_ERROR(SBE_FUNC" performTpmReset failed"); break; } g_sbeRole = SbeRegAccess::theSbeRegAccess().isSbeSlave() ? SBE_ROLE_SLAVE : SBE_ROLE_MASTER; SBE_INFO(SBE_FUNC"g_sbeRole [%x]", g_sbeRole); if(SBE_ROLE_SLAVE == g_sbeRole) { (void)SbeRegAccess::theSbeRegAccess().stateTransition( SBE_RUNTIME_EVENT); } }while(0); return rc; #undef SBE_FUNC } /* * --------------------------------------------- start SEEPROM CODE */ //---------------------------------------------------------------------------- ReturnCode istepWithCoreSetBlock( voidfuncptr_t i_hwp) { #define SBE_FUNC "istepWithCoreSetBlock" SBE_ENTER(SBE_FUNC); ReturnCode l_rc = FAPI2_RC_SUCCESS; Target l_procTgt = plat_getChipTarget(); for (auto l_coreTgt : l_procTgt.getChildren()) { SBE_EXEC_HWP(l_rc, reinterpret_cast( i_hwp ), l_coreTgt, p9pmblockwkup::SET) if(l_rc != FAPI2_RC_SUCCESS) { SBE_ERROR(SBE_FUNC " p9_block_wakeup_intr failed, RC=[0x%08X]", l_rc); break; } } SBE_EXIT(SBE_FUNC); return l_rc; #undef SBE_FUNC } //---------------------------------------------------------------------------- ReturnCode istepWithCoreState( voidfuncptr_t i_hwp) { #define SBE_FUNC "istepWithCoreState" SBE_ENTER(SBE_FUNC); ReturnCode l_rc = FAPI2_RC_SUCCESS; l_rc = stopAllCoreInstructions(); if( l_rc == FAPI2_RC_SUCCESS ) { l_rc = flushNVDIMM(); if( l_rc != FAPI2_RC_SUCCESS ) { SBE_ERROR(SBE_FUNC "flushNVDIMM failed"); } } else { SBE_ERROR(SBE_FUNC "Stop all core instructions is failed, " "RC=[0x%08X]", l_rc); } SBE_EXIT(SBE_FUNC); return l_rc; #undef SBE_FUNC } //---------------------------------------------------------------------------- ReturnCode istepMpiplRstClrTpmBits( voidfuncptr_t i_hwp) { #define SBE_FUNC "istepMpiplRstClrTpmBits" SBE_ENTER(SBE_FUNC); ReturnCode l_rc = performTpmReset(); if( l_rc != FAPI2_RC_SUCCESS ) { SBE_ERROR(SBE_FUNC" performTpmReset failed"); } SBE_EXIT(SBE_FUNC); return l_rc; #undef SBE_FUNC } //---------------------------------------------------------------------------- ReturnCode istepWithExL2Flush( voidfuncptr_t i_hwp) { #define SBE_FUNC "istepWithExL2Flush" SBE_ENTER(SBE_FUNC); ReturnCode rc = FAPI2_RC_SUCCESS; Target procTgt = plat_getChipTarget(); for (auto& exTgt : procTgt.getChildren()) { bool l2IsScomable[MAX_L2_PER_QUAD] = {false}; bool l2IsScanable[MAX_L2_PER_QUAD] = {false}; bool l3IsScomable[MAX_L3_PER_QUAD] = {false}; bool l3IsScanable[MAX_L3_PER_QUAD] = {false}; uint8_t chipUnitNum = 0; // Get EQ Parent to figure if this EX's L2 is scommable fapi2::Target eqTgt = exTgt.getParent(); rc = p9_query_cache_access_state(eqTgt, l2IsScomable, l2IsScanable, l3IsScomable, l3IsScanable); if(rc != FAPI2_RC_SUCCESS) { SBE_ERROR(SBE_FUNC " p9_query_cache_access_state failed, " "RC=[0x%08X]", rc); break; } FAPI_ATTR_GET( fapi2::ATTR_CHIP_UNIT_POS, exTgt, chipUnitNum ); // check the position of EX i.e. Ex0 or Ex1 if( !(l2IsScomable[(chipUnitNum % 2)]) ) { SBE_INFO(SBE_FUNC "Ex chipletId [%d] Ex%d is not l2 scomable, " "so no purge", chipUnitNum, (chipUnitNum % 2)); continue; } p9core::purgeData_t l_purgeData; SBE_EXEC_HWP(rc, reinterpret_cast(i_hwp), exTgt, l_purgeData) if(rc != FAPI2_RC_SUCCESS) { SBE_ERROR(SBE_FUNC " p9_l2_flush failed, RC=[0x%08X]", rc); break; } } SBE_EXIT(SBE_FUNC); return rc; #undef SBE_FUNC } //---------------------------------------------------------------------------- ReturnCode istepWithExL3Flush( voidfuncptr_t i_hwp) { #define SBE_FUNC "istepWithExL3Flush" SBE_ENTER(SBE_FUNC); ReturnCode rc = FAPI2_RC_SUCCESS; Target procTgt = plat_getChipTarget(); for (auto& exTgt : procTgt.getChildren()) { bool l2IsScomable[MAX_L2_PER_QUAD] = {false}; bool l2IsScanable[MAX_L2_PER_QUAD] = {false}; bool l3IsScomable[MAX_L3_PER_QUAD] = {false}; bool l3IsScanable[MAX_L3_PER_QUAD] = {false}; uint8_t chipUnitNum = 0; // Get EQ Parent to figure if this EX's L3 is scommable fapi2::Target eqTgt = exTgt.getParent(); rc = p9_query_cache_access_state(eqTgt, l2IsScomable, l2IsScanable, l3IsScomable, l3IsScanable); if(rc != FAPI2_RC_SUCCESS) { SBE_ERROR(SBE_FUNC " p9_query_cache_access_state failed, " "RC=[0x%08X]", rc); break; } FAPI_ATTR_GET( fapi2::ATTR_CHIP_UNIT_POS, exTgt, chipUnitNum ); // check the position of EX i.e. Ex0 or Ex1 if( !(l3IsScomable[(chipUnitNum % 2)]) ) { SBE_INFO(SBE_FUNC "Ex chipletId [%d] EX%d is not l3 scomable, " "so no purge", chipUnitNum, (chipUnitNum % 2)); continue; } SBE_EXEC_HWP(rc, reinterpret_cast(i_hwp), exTgt, L3_FULL_PURGE, 0x0) if(rc != FAPI2_RC_SUCCESS) { SBE_ERROR(SBE_FUNC " p9_l3_flush failed, RC=[0x%08X]", rc); break; } } SBE_EXIT(SBE_FUNC); return rc; #undef SBE_FUNC } //---------------------------------------------------------------------------- ReturnCode istepWithProcSequenceDrtm( voidfuncptr_t i_hwp) { #define SBE_FUNC "istepWithProcSequenceDrtm" SBE_ENTER(SBE_FUNC); ReturnCode l_rc = FAPI2_RC_SUCCESS; Target l_procTgt = plat_getChipTarget(); uint8_t l_status = 0; size_t l_timeOut = SBE_SYSTEM_QUIESCE_TIMEOUT_LOOP; while(l_timeOut) { SBE_EXEC_HWP(l_rc, reinterpret_cast(i_hwp), l_procTgt, l_status) if(l_rc != FAPI2_RC_SUCCESS) { SBE_ERROR(SBE_FUNC "p9_sbe_sequence_drtm failed, RC=[0x%08X]",l_rc); break; } if(l_status) { SBE_INFO(SBE_FUNC "p9_sbe_sequence_drtm LQA SBE System Quiesce done"); break; } else { l_timeOut--; // delay prior to repeating the above FAPI_TRY(fapi2::delay(SBE_LQA_DELAY_HW_US, SBE_LQA_DELAY_SIM_CYCLES), "Error from delay"); } } // Checkstop system if SBE system quiesce not set after the loop if(!l_status || l_rc) { SBE_ERROR(SBE_FUNC "p9_sbe_sequence_drtm LQA SBE System Quiesce failed," "Either System Quiesce Achieved not true or procedure " "failed RC=[0x%08X]",l_rc); // check stop the system // TODO RTC 164425 this needs to be replicated on any MPIPL Hwp failure Target l_proc = plat_getChipTarget(); l_rc = putscom_abs_wrap(&l_proc, PERV_N3_LOCAL_FIR_OR, ((uint64_t)1 << N3_FIR_SYSTEM_CHECKSTOP_BIT)); if(l_rc != FAPI2_RC_SUCCESS) { // Scom failed SBE_ERROR(SBE_FUNC "PutScom failed for REG PERV_N3_LOCAL_FIR"); // TODO - Store the response in Async Response // RTC:149074 } } fapi_try_exit: if(fapi2::current_err) { l_rc = fapi2::current_err; } SBE_EXIT(SBE_FUNC); return l_rc; #undef SBE_FUNC } //---------------------------------------------------------------------------- ReturnCode istepStartMpipl( voidfuncptr_t i_hwp) { #define SBE_FUNC "istepStartMpipl" SBE_ENTER(SBE_FUNC); ReturnCode rc = FAPI2_RC_SUCCESS; (void)SbeRegAccess::theSbeRegAccess().stateTransition( SBE_ENTER_MPIPL_EVENT); // Set MPIPL mode bit in Scratch Reg 3 (void)SbeRegAccess::theSbeRegAccess().setMpIplMode(true); // Close all non-secure memory regions mainStoreSecMemRegionManager.closeAllRegions(); do { rc = updatePhbFunctionalState(); if(rc != FAPI2_RC_SUCCESS) { SBE_ERROR(SBE_FUNC "updatePhbFunctionalState failed"); break; } rc = resetCrespErrLatch(); if(rc != FAPI2_RC_SUCCESS) { SBE_ERROR(SBE_FUNC "resetCrespErrLatch failed"); break; } }while(0); SBE_EXIT(SBE_FUNC); return rc; #undef SBE_FUNC } //---------------------------------------------------------------------------- ReturnCode istepMpiplQuadPoweroff( voidfuncptr_t i_hwp) { #define SBE_FUNC "istepMpiplQuadPoweroff" SBE_ENTER(SBE_FUNC); ReturnCode l_rc = FAPI2_RC_SUCCESS; if(g_sbeRole == SBE_ROLE_MASTER) { Target l_proc = plat_getChipTarget(); // Fetch the MASTER_CORE attribute uint8_t l_coreId = 0; FAPI_ATTR_GET(fapi2::ATTR_MASTER_CORE, l_proc, l_coreId); // Construct the Master Core Target fapi2::Target l_core( plat_getTargetHandleByChipletNumber( l_coreId + CORE_CHIPLET_OFFSET)); fapi2::Target l_quad = l_core.getParent(); SBE_EXEC_HWP(l_rc, reinterpret_cast(i_hwp), l_quad, G_ring_save) } SBE_EXIT(SBE_FUNC); return l_rc; #undef SBE_FUNC } //---------------------------------------------------------------------------- ReturnCode istepWithProcQuiesceLQASet( voidfuncptr_t i_hwp ) { #define SBE_FUNC "istepWithProcQuiesceLQASet" SBE_ENTER(SBE_FUNC); ReturnCode l_rc = FAPI2_RC_SUCCESS; do { l_rc = istepWithProc(i_hwp); if(l_rc == FAPI2_RC_SUCCESS) { //set the LQA Bit // TODO RTC 164425 - Create another istep for Setting LQA bit after // L2/L3 flush istep Target l_proc = plat_getChipTarget(); uint64_t l_data = 0x1000000000000000ULL; //Set bit3 l_rc = putscom_abs_wrap(&l_proc, PU_SECURITY_SWITCH_REGISTER_SCOM, l_data); if(l_rc != FAPI2_RC_SUCCESS) { SBE_ERROR(SBE_FUNC "PutScom failed for PU_SECURITY_SWITCH_REGISTER_SCOM"); break; } l_data = 0; l_rc = getscom_abs_wrap (&l_proc, PU_SECURITY_SWITCH_REGISTER_SCOM, &l_data); if(l_rc != FAPI2_RC_SUCCESS) { SBE_ERROR(SBE_FUNC "GetScom failed for PU_SECURITY_SWITCH_REGISTER_SCOM"); break; } SBE_INFO(SBE_FUNC "PU_SECURITY_SWITCH_REGISTER_SCOM Data [0x%08X][%08X]", (uint32_t)((l_data >> 32) & 0xFFFFFFFF), (uint32_t)(l_data & 0xFFFFFFFF)); } }while(0); SBE_EXIT(SBE_FUNC); return l_rc; #undef SBE_FUNC } //---------------------------------------------------------------------------- ReturnCode istepMpiplSetFunctionalState( voidfuncptr_t i_hwp ) { #define SBE_FUNC "istepMpiplSetFunctionalState" SBE_ENTER(SBE_FUNC); Target proc = plat_getChipTarget(); ReturnCode rc = FAPI2_RC_SUCCESS; do { // Read the EQ and EC gard attributes from the chip target fapi2::buffer l_scratchReg1 = 0; uint64_t l_scratchReg8 = 0; static const uint64_t SCRATCH8_SCRATCH1REG_VALID_BIT = 0x8000000000000000ULL; fapi2::buffer l_eqMask = 0; fapi2::buffer l_ecMask = 0; plat_target_handle_t l_hndl; // Set MPIPL mode bit in Scratch Reg 3 (void)SbeRegAccess::theSbeRegAccess().setMpIplMode(true); rc = getscom_abs_wrap (&l_hndl, PERV_SCRATCH_REGISTER_8_SCOM, &l_scratchReg8); if( rc != FAPI2_RC_SUCCESS ) { SBE_ERROR(SBE_FUNC" Failed to read Scratch RegR8"); break; } if(l_scratchReg8 & SCRATCH8_SCRATCH1REG_VALID_BIT) { rc = getscom_abs_wrap (&l_hndl, PERV_SCRATCH_REGISTER_1_SCOM, &l_scratchReg1()); if( rc != FAPI2_RC_SUCCESS ) { SBE_ERROR(SBE_FUNC" Failed to read Scratch Reg1"); break; } l_scratchReg1.extract<0, 6>(l_eqMask); l_scratchReg1.extract<8, 24>(l_ecMask); SBE_INFO(SBE_FUNC" Setting ATTR_EQ_GARD [0x%08X] " "ATTR_EC_GARD [0x%08X]", l_eqMask, l_ecMask); PLAT_ATTR_INIT(fapi2::ATTR_EQ_GARD, proc, l_eqMask); PLAT_ATTR_INIT(fapi2::ATTR_EC_GARD, proc, l_ecMask); // Apply the gard records rc = plat_ApplyGards(); if( rc != FAPI2_RC_SUCCESS ) { SBE_ERROR(SBE_FUNC" Failed to to apply gard records"); break; } if (g_sbeRole == SBE_ROLE_MASTER) { // TODO via RTC 135345 // Once multicast targets are supported, we may need to pass // p9selectex::ALL as input. SBE_EXEC_HWP(rc, reinterpret_cast(i_hwp), proc, p9selectex::SINGLE) if( rc != FAPI2_RC_SUCCESS ) { SBE_ERROR(SBE_FUNC" Failed hwp p9_sbe_select_ex_hwp"); break; } } } else { SBE_ERROR(SBE_FUNC " Scratch Reg 1 is invalid," "not applying gard records"); } }while(0); SBE_EXIT(SBE_FUNC); return rc; #undef SBE_FUNC } //---------------------------------------------------------------------------- ReturnCode istepStopClockMpipl( voidfuncptr_t i_hwp ) { #define SBE_FUNC "istepStopClockMpipl" SBE_ENTER(SBE_FUNC); uint32_t l_fapiRc = FAPI2_RC_SUCCESS; p9_stopclocks_flags l_flags; // Default Flag Values Target l_procTgt = plat_getChipTarget(); p9hcd::P9_HCD_CLK_CTRL_CONSTANTS l_clk_regions = p9hcd::CLK_REGION_ALL_BUT_PLL_REFR; p9hcd::P9_HCD_EX_CTRL_CONSTANTS l_ex_select = p9hcd::BOTH_EX; l_flags.clearAll(); l_flags.stop_core_clks = true; l_flags.stop_cache_clks = true; SBE_EXEC_HWP(l_fapiRc, reinterpret_cast(i_hwp), l_procTgt, l_flags, l_clk_regions, l_ex_select); SBE_EXIT(SBE_FUNC); return l_fapiRc; #undef SBE_FUNC } /* * end SEEPROM CODE -------------------------------------------------- */ #endif // ifdef __SBEFW_SEEPROM__