fapi2::ReturnCode ppe_resume( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, const uint64_t i_base_address) { fapi2::buffer<uint64_t> l_data64; static const uint32_t RESUME_TRIES = 10; uint32_t l_timeout_count = RESUME_TRIES; //Before reume always clear debug status (Michael's comment) FAPI_INF(" Clear debug status via XCR..."); l_data64.flush<0>(); FAPI_TRY(putScom(i_target, i_base_address + PPE_XIXCR, l_data64), "Error in PUTSCOM in XCR to clear dbg status"); FAPI_INF(" Send RESUME command via XCR..."); l_data64.flush<0>().insertFromRight(p9hcd::RESUME, 1, 3); FAPI_TRY(putScom(i_target, i_base_address + PPE_XIXCR, l_data64), "Error in PUTSCOM in XCR to resume condition"); do { FAPI_TRY(getScom(i_target, i_base_address + PPE_XIRAMEDR, l_data64)); FAPI_DBG(" Poll content: XSR: 0x%16llX", l_data64); } while((l_data64.getBit<p9hcd::HALTED_STATE>() != 0) && (--l_timeout_count != 0)); fapi_try_exit: return fapi2::current_err; }
errlHndl_t FakeRegSvc::modifyScom( TargetHandle_t i_target, uint64_t i_address, uint64_t i_data, uint64_t & o_data, ScomOp i_op) { errlHndl_t err = 0; uint64_t data = iv_regs[i_target][i_address]; uint64_t changedData = i_op == SCOM_OR ? (data | i_data) : (data & i_data); bool changed = changedData != data; if(changed) { putScom( i_target, i_address, changedData); } return err; }
errlHndl_t MemInjectSink::putAttention(const AttnData & i_attn) { return putScom( getTargetService().getMcs(i_attn.targetHndl), MCI::address, ~0); }
fapi2::ReturnCode ppe_hard_reset( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, const uint64_t i_base_address) { fapi2::buffer<uint64_t> l_data64; FAPI_INF(" Hard reset via XCR..."); l_data64.flush<0>().insertFromRight(6, 1, 3); FAPI_TRY(putScom(i_target, i_base_address + PPE_XIXCR, l_data64), "Error in PUTSCOM in XCR to do hard reset"); fapi_try_exit: return fapi2::current_err; }
fapi2::ReturnCode ppe_resume_only( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, const uint64_t i_base_address) { fapi2::buffer<uint64_t> l_data64; FAPI_INF(" Resume only through XCR..."); l_data64.flush<0>().insertFromRight(p9hcd::RESUME, 1, 3); FAPI_TRY(putScom(i_target, i_base_address + PPE_XIXCR, l_data64), "Error in PUTSCOM in XCR only resume"); fapi_try_exit: return fapi2::current_err; }
fapi2::ReturnCode ppe_clear_dbg( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, const uint64_t i_base_address) { fapi2::buffer<uint64_t> l_data64; FAPI_INF(" Clear debug status via XCR..."); l_data64.flush<0>(); FAPI_TRY(putScom(i_target, i_base_address + PPE_XIXCR, l_data64), "Error in PUTSCOM in XCR to clear dbg status"); fapi_try_exit: return fapi2::current_err; }
fapi2::ReturnCode ppe_halt( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, const uint64_t i_base_address) { fapi2::buffer<uint64_t> l_data64; FAPI_INF(" Send HALT command via XCR..."); l_data64.flush<0>().insertFromRight(p9hcd::HALT, 1, 3); FAPI_TRY(putScom(i_target, i_base_address + PPE_XIXCR, l_data64), "Error in PUTSCOM in XCR to generate Halt condition"); FAPI_TRY(ppe_pollHaltState(i_target, i_base_address)); fapi_try_exit: return fapi2::current_err; }
fapi2::ReturnCode ppe_ss_only( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, const uint64_t i_base_address, uint64_t i_step_count) { fapi2::buffer<uint64_t> l_data64; FAPI_TRY(ppe_pollHaltState(i_target, i_base_address)); while(i_step_count != 0) { FAPI_DBG(" Send Single step command via XCR...step count = 0x%16llx", i_step_count); l_data64.flush<0>().insertFromRight(p9hcd::SINGLE_STEP, 1, 3); FAPI_TRY(putScom(i_target, i_base_address + PPE_XIXCR, l_data64), "Error in PUTSCOM in XCR to generate Single Step condition"); --i_step_count; //Decrement step count FAPI_TRY(ppe_pollHaltState(i_target, i_base_address)); } fapi_try_exit: return fapi2::current_err; }
errlHndl_t FakePrd::callPrd(const AttentionList & i_attentions) { errlHndl_t l_elog = i_attentions.forEach(Clear(*iv_injectSink)).err; AttnList l_attnList; i_attentions.getAttnList(l_attnList); ATTN_TRACE("fakeCallPrd with Attn Count of %d", l_attnList.size()); // ----------------------------------------------------- // This is FAKE code only. // If you do the EC/MODEL check, it crashes in CXX testcase. // Kind of thinking some library missing that is needed when // adding these calls, For now, I will just leave them out // and we could probably scrap this test now that it runs // successfully (see attntestproc.H) // (Maybe add to 'fake target service' for these ATTRs) // ----------------------------------------------------- // For the initial NIMBUS chip, there is a HW issue // which requires us to clear the "Combined Global // interrupt register" on recoverable errors. // This also affects Checkstop/Special Attns, but // the FSP handles those and already clears the reg. // The issue does not apply to host/unit cs attns. // uint8_t l_ecLevel = 0; AttnList::iterator l_attnIter = l_attnList.begin(); // Shouldn't be mixing NIMBUS with CUMULUS,etc... // so probably don't need to repeat this call per chip. // bool l_isNimbus = ( (*l_attnIter).targetHndl-> // getAttr<ATTR_MODEL>() == MODEL_NIMBUS ); // Iterate thru all chips in case PRD handled // a chip other than the first one. while(l_attnIter != l_attnList.end()) { // l_ecLevel = (*l_attnIter).targetHndl->getAttr<ATTR_EC>(); if ( (RECOVERABLE == (*l_attnIter).attnType) // && (true == l_isNimbus) && (l_ecLevel < 0x11) ) { errlHndl_t l_scomErr = NULL; uint64_t l_clrAllBits = 0; l_scomErr = putScom( (*l_attnIter).targetHndl, PIB_INTR_TYPE_REG, l_clrAllBits ); if (NULL != l_scomErr) { ATTN_ERR("Clear PibIntrReg failed, HUID:0X%08X", get_huid( (*l_attnIter).targetHndl) ); errlCommit(l_scomErr, ATTN_COMP_ID); } // failed to clear PIB intr reg } // if recoverable attn ++l_attnIter; } // end while looping thru attn list return l_elog; }
void ServiceCommon::processAttnPreAck(const TargetHandle_t i_proc) { uint64_t hostMask = HostMask::host(); uint64_t nonHostMask = HostMask::nonHost(); uint64_t data = 0; // do the minimum that is required // for sending EOI without getting // another interrupt. for host attentions // this is clearing the gpio interrupt // type status register // and for xstp,rec,spcl this is // masking the appropriate bit in // ipoll mask // read the ipoll status register // to determine the interrupt was // caused by host attn or something // else (xstp,rec,spcl) errlHndl_t err = getScom(i_proc, IPOLL_STATUS_REG, data); if(err) { errlCommit(err, ATTN_COMP_ID); // assume everything is on data = hostMask | nonHostMask; } if(data & hostMask) { // if host attention, clear the ITR macro gpio interrupt // type status register. err = putScom(i_proc, INTR_TYPE_LCL_ERR_STATUS_AND_REG, 0); if(err) { errlCommit(err, ATTN_COMP_ID); } } if(data & nonHostMask) { // mask local proc xstp,rec and/or special attns if on. // the other thread might be trying to unmask // on the same target. The mutex ensures // neither thread corrupts the register. mutex_lock(&iv_mutex); err = modifyScom(i_proc, IPOLL::address, data & nonHostMask, SCOM_OR); mutex_unlock(&iv_mutex); if(err) { errlCommit(err, ATTN_COMP_ID); } } }
fapi2::ReturnCode p9a_omi_setup_bars( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target) { FAPI_DBG("Start"); std::vector<uint64_t> l_base_addr_nm0; std::vector<uint64_t> l_base_addr_nm1; std::vector<uint64_t> l_base_addr_m; fapi2::buffer<uint64_t> l_mmio_bar; fapi2::buffer<uint64_t> l_cfg_bar; uint64_t l_base_addr_mmio; uint8_t l_pos; uint8_t l_mcc_pos; uint64_t l_ext_mask; // determine base address of chip MMIO range FAPI_TRY(p9_fbc_utils_get_chip_base_address(i_target, EFF_FBC_GRP_CHIP_IDS, l_base_addr_nm0, l_base_addr_nm1, l_base_addr_m, l_base_addr_mmio), "Error from p9_fbc_utils_get_chip_base_address"); FAPI_TRY(p9a_get_ext_mask(l_ext_mask)); FAPI_DBG("l_ext_mask: %x", l_ext_mask); FAPI_DBG("l_base_addr_mmio: 0x%llx", l_base_addr_mmio); for (auto l_mcc : i_target.getChildren<fapi2::TARGET_TYPE_MCC>()) { fapi2::ATTR_OMI_INBAND_BAR_BASE_ADDR_OFFSET_Type l_bar_offset; uint64_t l_omi_inband_addr = 0; fapi2::buffer<uint64_t> l_scom_data; auto l_omi_targets = l_mcc.getChildren<fapi2::TARGET_TYPE_OMI>(); if (l_omi_targets.size() > 0) { // Set the sizes for the MMIO/Config bars FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_mcc, l_pos), "Error getting ATTR_CHIP_UNIT_POS, l_rc 0x%.8X", (uint64_t)fapi2::current_err); l_scom_data.flush<0>(); // 2GB cfg and MMIO l_scom_data.insertFromRight<P9A_MI_MCFGP0_MCFGPR0_CONFIGURATION_GROUP_SIZE, P9A_MI_MCFGP0_MCFGPR0_CONFIGURATION_GROUP_SIZE_LEN>(mss::exp::ib::EXPLR_IB_BAR_SIZE); l_scom_data.insertFromRight<P9A_MI_MCFGP0_MCFGPR0_MMIO_GROUP_SIZE, P9A_MI_MCFGP0_MCFGPR0_MMIO_GROUP_SIZE_LEN>(mss::exp::ib::EXPLR_IB_BAR_SIZE); // Write to reg if (l_pos % 2 == 0) { FAPI_INF("Write MCFGP0 reg 0x%.16llX, Value 0x%.16llX", P9A_MI_MCFGP0, l_scom_data); FAPI_TRY(fapi2::putScom(l_mcc.getParent<fapi2::TARGET_TYPE_MI>(), P9A_MI_MCFGP0, l_scom_data), "Error writing to MCS_MCFGP reg"); } else { FAPI_INF("Write MCFGP1 reg 0x%.16llX, Value 0x%.16llX", P9A_MI_MCFGP1, l_scom_data); FAPI_TRY(fapi2::putScom(l_mcc.getParent<fapi2::TARGET_TYPE_MI>(), P9A_MI_MCFGP1, l_scom_data), "Error writing to MCS_MCFGP reg"); } for (auto l_omi : l_omi_targets) { // retrieve OMI pos FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_omi, l_pos), "Error from FAPI_ATTR_GET (ATTR_CHIP_UNIT_POS)"); // retrieve inband BAR offset FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_OMI_INBAND_BAR_BASE_ADDR_OFFSET, l_omi, l_bar_offset), "Error from FAPI_ATTR_GET (ATTR_OMI_INBAND_BAR_BASE_ADDR_OFFSET)"); FAPI_DBG("l_bar_offset: 0x%llx", l_bar_offset); // If this is channel B, then the B bit must be set. If it is not, then the B bit must not be set. FAPI_ASSERT( ((l_pos % 2) == 1) == // Is this B channel? ((l_bar_offset & mss::exp::ib::EXPLR_IB_BAR_B_BIT) == mss::exp::ib::EXPLR_IB_BAR_B_BIT), fapi2::PROC_OMI_SETUP_BARS_INVALID_BAR() .set_TARGET(l_omi) .set_BAR_VALUE(l_bar_offset), "B Channel requires BAR size bit set"); FAPI_ASSERT(((l_bar_offset & mss::exp::ib::EXPLR_IB_BAR_MASK_ZERO) == 0), fapi2::PROC_OMI_SETUP_BARS_INVALID_BAR() .set_TARGET(l_omi) .set_BAR_VALUE(l_bar_offset), "Bar size not honored"); FAPI_ASSERT(((l_bar_offset & mss::exp::ib::EXPLR_IB_MMIO_OFFSET) == 0), fapi2::PROC_OMI_SETUP_BARS_INVALID_BAR() .set_TARGET(l_omi) .set_BAR_VALUE(l_bar_offset), "MMIO bit must not be set"); l_omi_inband_addr = l_bar_offset; } FAPI_DBG("l_omi_inband_addr: 0x%llx", l_omi_inband_addr); // Force A Bar value l_omi_inband_addr = l_omi_inband_addr & (~mss::exp::ib::EXPLR_IB_BAR_B_BIT); FAPI_DBG("l_omi_inband_addr: 0x%llx", l_omi_inband_addr); // Add MMIO address for the chip l_omi_inband_addr = l_omi_inband_addr | l_base_addr_mmio; FAPI_DBG("l_omi_inband_addr: 0x%llx", l_omi_inband_addr); // Get cfg bar value fapi2::buffer<uint64_t> l_omi_inband_buf = l_omi_inband_addr; FAPI_DBG("l_omi_inband_buf: 0x%llx", l_omi_inband_buf); FAPI_TRY(extendBarAddress(l_ext_mask, l_omi_inband_buf, l_cfg_bar)); FAPI_DBG("l_cfg_bar: 0x%llx", l_cfg_bar); // Get MMIO bar value l_omi_inband_addr = l_omi_inband_addr | mss::exp::ib::EXPLR_IB_MMIO_OFFSET; l_omi_inband_buf = l_omi_inband_addr; FAPI_DBG("l_omi_inband_buf: 0x%llx", l_omi_inband_buf); FAPI_TRY(extendBarAddress(l_ext_mask, l_omi_inband_buf, l_mmio_bar)); FAPI_DBG("l_mmio_bar: 0x%llx", l_mmio_bar); // Write the channel cfg reg l_scom_data.flush<0>(); l_scom_data.setBit<P9A_MI_MCFGPR0_CONFIGURATION_VALID>(); //Enable CFG l_scom_data.setBit<P9A_MI_MCFGPR0_MMIO_VALID>(); //Enable MMIO l_scom_data.insert<P9A_MI_MCFGPR0_CONFIGURATION_GROUP_BASE_ADDRESS, P9A_MI_MCFGPR0_CONFIGURATION_GROUP_BASE_ADDRESS_LEN>(l_cfg_bar); l_scom_data.insert<P9A_MI_MCFGPR0_MMIO_GROUP_BASE_ADDRESS, P9A_MI_MCFGPR0_MMIO_GROUP_BASE_ADDRESS_LEN>(l_mmio_bar); // get MI target to configure MCFGPR fapi2::Target<fapi2::TARGET_TYPE_MI> l_mi = l_mcc.getParent<fapi2::TARGET_TYPE_MI>(); // retrieve DMI pos FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_mcc, l_mcc_pos), "Error from FAPI_ATTR_GET (ATTR_CHIP_UNIT_POS)"); // configure inband channel 0 MCFGPR0 if(l_mcc_pos % 2 == 0) { FAPI_TRY(putScom(l_mi, P9A_MI_MCFGPR0, l_scom_data)); } // configure inband channel 1 MCFGPR1 else { FAPI_TRY(putScom(l_mi, P9A_MI_MCFGPR1, l_scom_data)); } } } fapi_try_exit: FAPI_DBG("End"); return fapi2::current_err; }
void Service::processIntrQMsgPreAck(const msg_t & i_msg) { // this function should do as little as possible // since the hw can't generate additional interrupts // until the msg is acknowledged TargetHandle_t proc = NULL; INTR::XISR_t xisr; xisr.u32 = i_msg.data[0]; TargetHandleList procs; getTargetService().getAllChips(procs, TYPE_PROC); TargetHandleList::iterator it = procs.begin(); // resolve the xisr to a proc target while(it != procs.end()) { uint64_t node = 0, chip = 0; getTargetService().getAttribute(ATTR_FABRIC_NODE_ID, *it, node); getTargetService().getAttribute(ATTR_FABRIC_CHIP_ID, *it, chip); if(node == xisr.node && chip == xisr.chip) { proc = *it; break; } ++it; } uint64_t hostMask = HostMask::host(); uint64_t nonHostMask = HostMask::nonHost(); uint64_t data = 0; // do the minimum that is required // for sending EOI without getting // another interrupt. for host attentions // this is clearing the gpio interrupt // type status register // and for xstp,rec,spcl this is // masking the appropriate bit in // ipoll mask // read the ipoll status register // to determine the interrupt was // caused by host attn or something // else (xstp,rec,spcl) errlHndl_t err = getScom(proc, IPOLL_STATUS_REG, data); if(err) { errlCommit(err, ATTN_COMP_ID); // assume everything is on data = hostMask | nonHostMask; } if(data & hostMask) { // if host attention, clear the ITR macro gpio interrupt // type status register. err = putScom(proc, INTR_TYPE_LCL_ERR_STATUS_AND_REG, 0); if(err) { errlCommit(err, ATTN_COMP_ID); } } if(data & nonHostMask) { // mask local proc xstp,rec and/or special attns if on. // the other thread might be trying to unmask // on the same target. The mutex ensures // neither thread corrupts the register. mutex_lock(&iv_mutex); err = modifyScom(proc, IPOLL::address, data & nonHostMask, SCOM_OR); mutex_unlock(&iv_mutex); if(err) { errlCommit(err, ATTN_COMP_ID); } } }
errlHndl_t Service::configureInterrupts( msg_q_t i_q, ConfigureMode i_mode) { errlHndl_t err = NULL; // First register for Q // This will set up the psi host bridge logic for // lcl_err interrupt on all chips if(i_mode == UP) { err = INTR::registerMsgQ(i_q, ATTENTION, INTR::ISN_LCL_ERR); } // setup the ITR macro for GPIO type host attentions, // on all procs if(!err) { TargetHandleList procs; getTargetService().getAllChips(procs, TYPE_PROC); TargetHandleList::iterator it = procs.begin(); while(it != procs.end()) { uint64_t mask = 0; // clear GPIO interrupt type status register if(i_mode == UP) { err = putScom(*it, INTR_TYPE_LCL_ERR_STATUS_AND_REG, 0); } if(err) { break; } // unmask GPIO interrupt type mask = 0x8000000000000000ull; err = putScom( *it, (i_mode == UP ? INTR_TYPE_MASK_AND_REG : INTR_TYPE_MASK_OR_REG), i_mode == UP ? ~mask : mask); if(err) { break; } // set GPIO interrupt type mode - or if(i_mode == UP) { err = putScom(*it, INTR_TYPE_CONFIG_AND_REG, ~mask); } if(err) { break; } // enable/disable MCSes mask = 0; GP1::forEach(~0, &mask, &getPbGp2Mask); err = modifyScom( *it, GP2_REG, i_mode == UP ? mask : ~mask, i_mode == UP ? SCOM_OR : SCOM_AND); if(err) { break; } // enable attentions in ipoll mask mask = HostMask::nonHost(); mask |= HostMask::host(); // this doesn't have an and/or reg for some reason... err = modifyScom( *it, IPOLL::address, i_mode == UP ? ~mask : mask, i_mode == UP ? SCOM_AND : SCOM_OR); if(err) { break; } ++it; } if(!err && i_mode == DOWN) { if(NULL == INTR::unRegisterMsgQ(INTR::ISN_LCL_ERR)) { ATTN_ERR("INTR did not find isn: 0x%07x", INTR::ISN_LCL_ERR); } } } return err; }
/** brief handle chip attentions * * @param[in] i_proc - processor chip id at attention * XSCOM chip id based on devtree defn * @param[in] i_ipollStatus - processor chip Ipoll status * @param[in] i_ipollMask - processor chip Ipoll mask * @return 0 on success else return code */ int handleAttns(uint64_t i_proc, uint64_t i_ipollStatus, uint64_t i_ipollMask) { ATTN_SLOW(ENTER_MRK"ATTN_RT::handleAttns RtProc: %llx" ", ipollMask: %llx, ipollStatus: %llx", i_proc, i_ipollMask, i_ipollStatus); int rc = 0; errlHndl_t err = NULL; AttentionList attentions; MemOps & memOps = getMemOps(); uint64_t l_iprScomData = 0; do { // Convert chipIds to HB targets TargetHandle_t proc = NULL; err = RT_TARG::getHbTarget(i_proc, proc); if(err) { ATTN_ERR("ATTN_RT::handleAttns getHbTarget " "returned error for RtProc: %llx", i_proc); rc = EINVAL; break; } err = Singleton<Service>::instance().handleAttentions(proc); if(err) { ATTN_ERR("ATTN_RT::handleAttns service::handleAttentions " "returned error for RtProc: %llx", i_proc); break; } // For host attentions, clear gpio interrupt type register. // If we do not clear gpio register, ipoll status will again // get set and we will end up in infinite loop. uint64_t hostMask = 0; IPOLL::getCheckbits(HOST, hostMask); if( i_ipollMask & hostMask) { // After handling attn, check GP1 for more attns // as there could be additional memory units with attns. attentions.clear(); err = memOps.resolve(proc, attentions); if(err) { ATTN_ERR("RT GP1 Chk:memOps returned error.HUID:0X%08X ", get_huid( proc )); break; } // Save the IPR if any attns still active on Centaurs if (!attentions.empty()) { err = getScom(proc, INTR_TYPE_LCL_ERR_STATUS_REG, l_iprScomData); if(err) { ATTN_ERR("RT SaveIPR returned error.HUID:0X%08X ", get_huid( proc )); break; } } // end if any attentions // Clear the IPR (interrupt presentation register) err = putScom(proc, INTR_TYPE_LCL_ERR_STATUS_AND_REG, 0); if(err) { ATTN_ERR("ATTN_RT::handleAttns putscom failed for " "RtProc: %llx address:0x%08X", i_proc, INTR_TYPE_LCL_ERR_STATUS_AND_REG); break; } // Restore the IPR if any attns still active in Centaurs if (!attentions.empty()) { err = putScom(proc, INTR_TYPE_LCL_ERR_STATUS_OR_REG, l_iprScomData); if(err) { ATTN_ERR("RT RestoreIPR returned error.HUID:0X%08X ", get_huid( proc )); break; } } // end if any attentions } // end if i_ipollMask & hostMask) } while(0); if(err) { errlCommit( err, ATTN_COMP_ID ); if(0 == rc) { rc = -1; } } attentions.clear(); ATTN_SLOW(EXIT_MRK"ATTN_RT::handleAttns rc: %d", rc); return rc; }
fapi2::ReturnCode p9_hcd_core_stopclocks( const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target, const bool i_sync_stop_quad_clk) { FAPI_INF(">>p9_hcd_core_stopclocks"); fapi2::ReturnCode l_rc; fapi2::buffer<uint64_t> l_ccsr; fapi2::buffer<uint64_t> l_data64; fapi2::buffer<uint64_t> l_temp64; uint32_t l_loops1ms; uint8_t l_attr_chip_unit_pos; uint8_t l_attr_vdm_enabled; uint8_t l_attr_sdisn_setup; const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> l_sys; auto l_quad = i_target.getParent<fapi2::TARGET_TYPE_EQ>(); auto l_perv = i_target.getParent<fapi2::TARGET_TYPE_PERV>(); auto l_chip = i_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>(); auto l_ex_vector = l_quad.getChildren<fapi2::TARGET_TYPE_EX> (fapi2::TARGET_STATE_FUNCTIONAL); FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_SDISN_SETUP, l_chip, l_attr_sdisn_setup)); FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_VDM_ENABLED, l_chip, l_attr_vdm_enabled)); FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_perv, l_attr_chip_unit_pos)); l_attr_chip_unit_pos = (l_attr_chip_unit_pos - p9hcd::PERV_TO_CORE_POS_OFFSET) % 4; //Check if EQ is powered off; if so, return FAPI_TRY(fapi2::getScom(l_quad, EQ_PPM_PFSNS, l_data64), "Error reading data from EQ_PPM_PFSNS"); if (l_data64.getBit<EQ_PPM_PFSNS_VDD_PFETS_DISABLED_SENSE>()) { FAPI_DBG("Set core as stopped in STOP history register"); FAPI_TRY(putScom(i_target, C_PPM_SSHSRC, BIT64(0))); return fapi2::current_err; } //Check if core is powered off; if so, return FAPI_TRY(fapi2::getScom(i_target, C_PPM_PFSNS, l_data64), "Error reading data from C_PPM_PFSNS"); if (l_data64.getBit<C_PPM_PFSNS_VDD_PFETS_DISABLED_SENSE>()) { FAPI_DBG("Set core as stopped in STOP history register"); FAPI_TRY(putScom(i_target, C_PPM_SSHSRC, BIT64(0))); return fapi2::current_err; } // ---------------------------- // Prepare to stop core clocks // ---------------------------- FAPI_DBG("Check PM_RESET_STATE_INDICATOR via GPMMR[15]"); FAPI_TRY(getScom(i_target, C_PPM_GPMMR_SCOM, l_data64)); if (!l_data64.getBit<15>()) { FAPI_DBG("Gracefully turn off power management, continue anyways if fail"); /// @todo RTC158181 suspend_pm() } FAPI_DBG("Check core clock controller status"); l_rc = p9_common_clk_ctrl_state<fapi2::TARGET_TYPE_CORE>(i_target); if (l_rc) { FAPI_INF("Clock controller of this core chiplet is inaccessible, return"); goto fapi_try_exit; } FAPI_DBG("Check cache clock controller status"); l_rc = p9_common_clk_ctrl_state<fapi2::TARGET_TYPE_EQ>(l_quad); if (l_rc) { FAPI_INF("WARNING: core is enabled while cache is not, continue anyways"); } else { FAPI_DBG("Check PERV clock status for access to CME via CLOCK_STAT[4]"); FAPI_TRY(getScom(l_quad, EQ_CLOCK_STAT_SL, l_data64)); FAPI_DBG("Check PERV fence status for access to CME via CPLT_CTRL1[4]"); FAPI_TRY(getScom(l_quad, EQ_CPLT_CTRL1, l_temp64)); if (l_data64.getBit<4>() == 0 && l_temp64.getBit<4>() == 0) { #ifdef DD2 FAPI_DBG("Halting the PGPE ..."); l_rc = ppe_halt(l_chip, PGPE_BASE_ADDRESS); FAPI_ASSERT_NOEXIT(!l_rc, fapi2::CORE_STOPCLKS_PGPE_HALT_TIMEOUT() .set_CHIP(l_chip), "PSTATE GPE Halt timeout"); FAPI_DBG("Halting the SGPE ..."); l_rc = ppe_halt(l_chip, SGPE_BASE_ADDRESS); FAPI_ASSERT_NOEXIT(!l_rc, fapi2::CORE_STOPCLKS_SGPE_HALT_TIMEOUT() .set_CHIP(l_chip), "STOP GPE Halt timeout"); FAPI_DBG("Clear the atomic lock on EQ %d", l_attr_chip_unit_pos); l_rc = p9_clear_atomic_lock(l_quad); FAPI_ASSERT_NOEXIT(!l_rc, fapi2::CORE_STOPCLKS_ATOMIC_LOCK_FAIL() .set_EQ(l_quad), "EQ Atomic Halt timeout"); for ( auto& ex : l_ex_vector ) { fapi2::ATTR_CHIP_UNIT_POS_Type l_cme_id = 0; FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, ex, l_cme_id)); FAPI_DBG("Halting CME %d", l_cme_id ); uint64_t l_cme_base_address = getCmeBaseAddress (l_cme_id); l_rc = ppe_halt(l_chip, l_cme_base_address); FAPI_ASSERT_NOEXIT(!l_rc, fapi2::CACHE_STOPCLKS_CME_HALT_TIMEOUT() .set_EX(ex), "CME Halt timeout"); } #endif //if a core is only in special wakeup and asserting pm_exit, //then setting 6,7 of SICR will cause pm_exit to drop and //the core will re-enter a power saving state FAPI_DBG("Prevent Core-L2 Quiesce from removing PM_EXIT CME_SCOM_LMCR[22]"); FAPI_TRY(putScom(l_quad, (l_attr_chip_unit_pos < 2) ? EX_0_CME_SCOM_LMCR_OR : EX_1_CME_SCOM_LMCR_OR, (BIT64(22)))); FAPI_DBG("Assert Core-L2/CC Quiesces via CME_SCOM_SICR[6,8]/[7,9]"); FAPI_TRY(putScom(l_quad, (l_attr_chip_unit_pos < 2) ? EX_0_CME_SCOM_SICR_OR : EX_1_CME_SCOM_SICR_OR, (BIT64(6 + (l_attr_chip_unit_pos % 2)) | BIT64(8 + (l_attr_chip_unit_pos % 2))))); } } FAPI_DBG("Assert pm_mux_disable to get PCB Mux from CME via SLAVE_CONFIG[7]"); FAPI_TRY(getScom(i_target, C_SLAVE_CONFIG_REG, l_data64)); FAPI_TRY(putScom(i_target, C_SLAVE_CONFIG_REG, DATA_SET(7))); FAPI_DBG("Override possible PPM write protection to CME via CPPM_CPMMR[1]"); FAPI_TRY(putScom(i_target, C_CPPM_CPMMR_OR, MASK_SET(1))); FAPI_DBG("Assert chiplet fence via NET_CTRL0[18]"); FAPI_TRY(putScom(i_target, C_NET_CTRL0_WOR, MASK_SET(18))); // ------------------------------- // Stop core clocks // ------------------------------- FAPI_DBG("Clear all SCAN_REGION_TYPE bits"); FAPI_TRY(putScom(i_target, C_SCAN_REGION_TYPE, MASK_ZERO)); if(i_sync_stop_quad_clk) { FAPI_DBG("Stop core clocks(all but pll) via CLK_REGION in SLAVE mode"); l_data64 = (p9hcd::CLK_STOP_CMD_SLAVE | p9hcd::CLK_REGION_ALL_BUT_PLL | p9hcd::CLK_THOLD_ALL); FAPI_TRY(putScom(i_target, C_CLK_REGION, l_data64)); } else { FAPI_DBG("Stop core clocks(all but pll) via CLK_REGION"); l_data64 = (p9hcd::CLK_STOP_CMD | p9hcd::CLK_REGION_ALL_BUT_PLL | p9hcd::CLK_THOLD_ALL); FAPI_TRY(putScom(i_target, C_CLK_REGION, l_data64)); FAPI_DBG("Poll for core clocks stopped via CPLT_STAT0[8]"); l_loops1ms = 1E6 / CORE_CLK_STOP_POLLING_HW_NS_DELAY; do { fapi2::delay(CORE_CLK_STOP_POLLING_HW_NS_DELAY, CORE_CLK_STOP_POLLING_SIM_CYCLE_DELAY); FAPI_TRY(getScom(i_target, C_CPLT_STAT0, l_data64)); } while((l_data64.getBit<8>() != 1) && ((--l_loops1ms) != 0)); FAPI_ASSERT((l_loops1ms != 0), fapi2::PMPROC_CORECLKSTOP_TIMEOUT().set_CORECPLTSTAT(l_data64), "Core Clock Stop Timeout"); FAPI_DBG("Check core clocks stopped via CLOCK_STAT_SL[4-13]"); FAPI_TRY(getScom(i_target, C_CLOCK_STAT_SL, l_data64)); FAPI_ASSERT((((~l_data64) & p9hcd::CLK_REGION_ALL_BUT_PLL) == 0), fapi2::PMPROC_CORECLKSTOP_FAILED().set_CORECLKSTAT(l_data64), "Core Clock Stop Failed"); FAPI_DBG("Core clocks stopped now"); } // ------------------------------- // Disable core clock sync // ------------------------------- FAPI_DBG("Drop core clock sync enable via CPPM_CACCR[15]"); FAPI_TRY(putScom(i_target, C_CPPM_CACCR_CLEAR, MASK_SET(15))); FAPI_DBG("Poll for core clock sync done to drop via CPPM_CACSR[13]"); l_loops1ms = 1E6 / CORE_CLK_SYNC_POLLING_HW_NS_DELAY; do { fapi2::delay(CORE_CLK_SYNC_POLLING_HW_NS_DELAY, CORE_CLK_SYNC_POLLING_SIM_CYCLE_DELAY); FAPI_TRY(getScom(i_target, C_CPPM_CACSR, l_data64)); } while((l_data64.getBit<13>() == 1) && ((--l_loops1ms) != 0)); FAPI_ASSERT((l_loops1ms != 0), fapi2::PMPROC_CORECLKSYNCDROP_TIMEOUT().set_COREPPMCACSR(l_data64), "Core Clock Sync Drop Timeout"); FAPI_DBG("Core clock sync done dropped"); // ------------------------------- // Fence up // ------------------------------- FAPI_DBG("Assert skew sense to skew adjust fence via NET_CTRL0[22]"); FAPI_TRY(putScom(i_target, C_NET_CTRL0_WOR, MASK_SET(22))); FAPI_DBG("Drop ABIST_SRAM_MODE_DC to support ABIST Recovery via BIST[1]"); FAPI_TRY(getScom(i_target, C_BIST, l_data64)); FAPI_TRY(putScom(i_target, C_BIST, DATA_UNSET(1))); FAPI_DBG("Assert vital fence via CPLT_CTRL1[3]"); FAPI_TRY(putScom(i_target, C_CPLT_CTRL1_OR, MASK_SET(3))); FAPI_DBG("Assert regional fences via CPLT_CTRL1[4-14]"); FAPI_TRY(putScom(i_target, C_CPLT_CTRL1_OR, p9hcd::CLK_REGION_ALL)); if (l_attr_sdisn_setup) { FAPI_DBG("DD1 Only: Drop sdis_n(flushing LCBES condition) vai CPLT_CONF0[34]"); FAPI_TRY(putScom(i_target, C_CPLT_CONF0_CLEAR, MASK_SET(34))); } // ------------------------------- // Disable VDM // ------------------------------- if (l_attr_vdm_enabled == fapi2::ENUM_ATTR_VDM_ENABLED_TRUE) { FAPI_DBG("Set VDM Disable via CPPM_VDMCR[1]"); FAPI_TRY(putScom(i_target, C_PPM_VDMCR_OR, MASK_SET(1))); FAPI_DBG("Drop VDM Poweron via CPPM_VDMCR[0]"); FAPI_TRY(putScom(i_target, C_PPM_VDMCR_CLEAR, MASK_SET(0))); } // ------------------------------- // Update stop history // ------------------------------- FAPI_DBG("Set core as stopped in STOP history register"); FAPI_TRY(putScom(i_target, C_PPM_SSHSRC, BIT64(0))); // ------------------------------- // Clean up // ------------------------------- FAPI_DBG("Return possible PPM write protection to CME via CPPM_CPMMR[1]"); FAPI_TRY(putScom(i_target, C_CPPM_CPMMR_CLEAR, MASK_SET(1))); FAPI_DBG("Drop pm_mux_disable to release PCB Mux via SLAVE_CONFIG[7]"); FAPI_TRY(getScom(i_target, C_SLAVE_CONFIG_REG, l_data64)); FAPI_TRY(putScom(i_target, C_SLAVE_CONFIG_REG, DATA_UNSET(7))); fapi_try_exit: FAPI_INF("<<p9_hcd_core_stopclocks"); return fapi2::current_err; }
errlHndl_t ServiceCommon::configureInterrupts( ConfigureMode i_mode) { errlHndl_t err = NULL; TargetHandleList procs; getTargetService().getAllChips(procs, TYPE_PROC); TargetHandleList::iterator it = procs.begin(); while(it != procs.end()) { uint64_t mask = 0; // clear GPIO interrupt type status register if(i_mode == UP) { err = putScom(*it, INTR_TYPE_LCL_ERR_STATUS_AND_REG, 0); } if(err) { break; } // unmask GPIO interrupt type mask = 0x8000000000000000ull; err = putScom(*it, (i_mode == UP ? INTR_TYPE_MASK_AND_REG : INTR_TYPE_MASK_OR_REG), i_mode == UP ? ~mask : mask); if(err) { break; } // set GPIO interrupt type mode - or if(i_mode == UP) { err = putScom(*it, INTR_TYPE_CONFIG_AND_REG, ~mask); } if(err) { break; } // enable/disable MCSes mask = 0; GP1::forEach(~0, &mask, &getPbGp2Mask); err = modifyScom(*it, GP2_REG, i_mode == UP ? mask : ~mask, i_mode == UP ? SCOM_OR : SCOM_AND); if(err) { break; } // enable attentions in ipoll mask mask = HostMask::nonHost(); mask |= HostMask::host(); // this doesn't have an and/or reg for some reason... err = modifyScom(*it, IPOLL::address, i_mode == UP ? ~mask : mask, i_mode == UP ? SCOM_AND : SCOM_OR); if(err) { break; } ++it; } return err; }
fapi2::ReturnCode ppe_single_step( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, const uint64_t i_base_address, const uint16_t i_Rs, uint64_t i_step_count) { fapi2::buffer<uint64_t> l_data64; fapi2::buffer<uint64_t> l_dbcr_save; fapi2::buffer<uint32_t> l_gpr31_save; fapi2::buffer<uint64_t> l_sprg0_save; FAPI_TRY(ppe_pollHaltState(i_target, i_base_address)); // Save SPRG0 i_Rs before getting dbcr FAPI_DBG("Save SPRG0"); FAPI_TRY(getScom(i_target, i_base_address + PPE_XIRAMDBG, l_data64), "Error in GETSCOM"); l_data64.extractToRight(l_sprg0_save, 32, 32); FAPI_DBG("Saved SPRG0 value : 0x%08llX", l_sprg0_save ); FAPI_DBG("Save i_Rs"); l_data64.flush<0>().insertFromRight(ppe_getMtsprInstruction(i_Rs, SPRG0), 0, 32); FAPI_DBG("getMtsprInstruction(%d, SPRG0): 0x%16llX", R31, l_data64 ); FAPI_TRY(ppe_RAMRead(i_target, i_base_address, l_data64, l_gpr31_save)); FAPI_DBG("Saved GPR31 value : 0x%08llX", l_gpr31_save ); FAPI_INF(" Read and Save DBCR"); FAPI_DBG("Move DBCR to i_Rs"); l_data64.flush<0>().insertFromRight(ppe_getMfsprInstruction(i_Rs, DBCR), 0, 32); FAPI_DBG("getMfsprInstruction(%d, DBCR): 0x%16llX", i_Rs, l_data64 ); FAPI_TRY(fapi2::putScom(i_target, i_base_address + PPE_XIRAMEDR, l_data64)); FAPI_DBG("Move i_Rs to SPRG0 : so now SPRG0 has DBCR value"); l_data64.flush<0>().insertFromRight(ppe_getMtsprInstruction(i_Rs, SPRG0), 0, 32); FAPI_DBG("getMtsprInstruction(%d, SPRG0): 0x%16llX", i_Rs, l_data64 ); FAPI_TRY(fapi2::putScom(i_target, i_base_address + PPE_XIRAMEDR, l_data64)); FAPI_DBG("Save SPRG0 i.e. DBCR"); FAPI_TRY(getScom(i_target, i_base_address + PPE_XIRAMDBG, l_data64), "Error in GETSCOM"); l_data64.extractToRight(l_dbcr_save, 32, 32); FAPI_DBG("Saved DBCR value : 0x%08llX", l_dbcr_save ); FAPI_DBG("clear DBCR[8] IACE and DBCR[12:13] DACE"); FAPI_TRY(ppe_update_dbcr(i_target, i_base_address, ANDIS_CONST, 0x0F73, R31)); //Restore i_Rs and SPRG0 before single step FAPI_DBG("Restore i_Rs"); l_data64.flush<0>().insertFromRight(ppe_getMfsprInstruction(i_Rs, SPRG0), 0, 32); FAPI_DBG("getMfsprInstruction(R31, SPRG0): 0x%16llX", l_data64 ); l_data64.insertFromRight(l_gpr31_save, 32, 32); FAPI_DBG("Final Instr + SPRG0: 0x%16llX", l_data64 ); //write sprg0 with address and ram mfsprg0 to i_Rs FAPI_TRY(fapi2::putScom(i_target, i_base_address + PPE_XIRAMGA, l_data64 )); FAPI_DBG("Restore SPRG0"); FAPI_TRY(ppe_pollHaltState(i_target, i_base_address)); FAPI_TRY(putScom(i_target, i_base_address + PPE_XIRAMDBG , l_sprg0_save), "Error in PUTSCOM"); while(i_step_count != 0) { FAPI_DBG(" Send Single step command via XCR...step count = 0x%16llx", i_step_count); l_data64.flush<0>().insertFromRight(p9hcd::SINGLE_STEP, 1, 3); FAPI_TRY(putScom(i_target, i_base_address + PPE_XIXCR, l_data64), "Error in PUTSCOM in XCR to generate Single Step condition"); --i_step_count; //Decrement step count FAPI_TRY(ppe_pollHaltState(i_target, i_base_address)); } // Save SPRG0 i_Rs before getting dbcr FAPI_DBG("Save SPRG0"); FAPI_TRY(getScom(i_target, i_base_address + PPE_XIRAMDBG, l_data64), "Error in GETSCOM"); l_data64.extractToRight(l_sprg0_save, 32, 32); FAPI_DBG("Saved SPRG0 value : 0x%08llX", l_sprg0_save ); FAPI_DBG("Save i_Rs"); l_data64.flush<0>().insertFromRight(ppe_getMtsprInstruction(i_Rs, SPRG0), 0, 32); FAPI_DBG("getMtsprInstruction(%d, SPRG0): 0x%16llX", R31, l_data64 ); FAPI_TRY(ppe_RAMRead(i_target, i_base_address, l_data64, l_gpr31_save)); FAPI_DBG("Saved GPR31 value : 0x%08llX", l_gpr31_save ); FAPI_INF(" Restore DBCR"); FAPI_INF(" Write orig. DBCR into SPRG0"); l_data64.flush<0>().insertFromRight(ppe_getMfsprInstruction(i_Rs, SPRG0), 0, 32); FAPI_DBG("getMfsprInstruction(%d, SPRG0): 0x%16llX", i_Rs, l_data64 ); l_data64.insertFromRight(l_dbcr_save, 32, 32); FAPI_DBG("Final Instr + SPRG0: 0x%16llX", l_data64 ); //write sprg0 with address and ram mfsprg0 to i_Rs FAPI_TRY(fapi2::putScom(i_target, i_base_address + PPE_XIRAMGA, l_data64 )); //then mtDBCR from i_Rs l_data64.flush<0>().insertFromRight(ppe_getMtsprInstruction(i_Rs, DBCR), 0, 32); FAPI_DBG("getMtsprInstruction(%d, DBCR): 0x%16llX", i_Rs, l_data64 ); FAPI_TRY(fapi2::putScom(i_target, i_base_address + PPE_XIRAMEDR, l_data64)); //Restore i_Rs and SPRG0 after dbcr updates FAPI_DBG("Restore i_Rs"); l_data64.flush<0>().insertFromRight(ppe_getMfsprInstruction(i_Rs, SPRG0), 0, 32); FAPI_DBG("getMfsprInstruction(R31, SPRG0): 0x%16llX", l_data64 ); l_data64.insertFromRight(l_gpr31_save, 32, 32); FAPI_DBG("Final Instr + SPRG0: 0x%16llX", l_data64 ); //write sprg0 with address and ram mfsprg0 to i_Rs FAPI_TRY(fapi2::putScom(i_target, i_base_address + PPE_XIRAMGA, l_data64 )); FAPI_DBG("Restore SPRG0"); FAPI_TRY(ppe_pollHaltState(i_target, i_base_address)); FAPI_TRY(putScom(i_target, i_base_address + PPE_XIRAMDBG , l_sprg0_save), "Error in GETSCOM"); fapi_try_exit: return fapi2::current_err; }