diff options
| author | Yue Du <daviddu@us.ibm.com> | 2017-05-17 11:50:49 -0500 |
|---|---|---|
| committer | hostboot <hostboot@us.ibm.com> | 2018-08-22 17:54:57 -0500 |
| commit | 8d6afc6481854413dacd0ff50e5f148b845b2778 (patch) | |
| tree | 0aa2e25e5d618ff3ecd2efa4c3cf7688306731c2 | |
| parent | 6b56b1459f58e779f53611577186bc8d49054283 (diff) | |
| download | talos-hcode-8d6afc6481854413dacd0ff50e5f148b845b2778.tar.gz talos-hcode-8d6afc6481854413dacd0ff50e5f148b845b2778.zip | |
STOP: NDD2 daul cast workaround
Change-Id: I27e924dd5a1ddc2725b35e66ed8a8ce2ac8cb98a
Original-Change-Id: I447a8343ee212ee24db8a1ccef22cc28f4e80d7f
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/40640
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: BRIAN D. VICTOR <brian.d.victor1@ibm.com>
Reviewed-by: Gregory S. Still <stillgs@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
| -rwxr-xr-x | import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c | 1545 |
1 files changed, 789 insertions, 756 deletions
diff --git a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c index d14dac75..85c32319 100755 --- a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c +++ b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c @@ -217,11 +217,13 @@ p9_cme_stop_entry() int entry_ongoing = 1; uint8_t target_level = 0; uint8_t deeper_level = 0; + uint32_t deeper_core = 0; +#if !SKIP_ENTRY_CATCHUP uint8_t origin_level = 0; uint32_t origin_core = 0; - uint32_t deeper_core = 0; - uint32_t core_aborted = 0; uint32_t core_catchup = 0; +#endif + uint32_t core_aborted = 0; uint32_t core_stop1 = 0; uint32_t core_index = 0; uint32_t core_mask = 0; @@ -289,1064 +291,1095 @@ p9_cme_stop_entry() MARK_TAG(BEGINSCOPE_STOP_ENTRY, core) //=================================== - do // while(0) loop for stop flow control +#if NIMBUS_DD_LEVEL == 2 || DISABLE_CME_DUAL_CAST == 1 + + uint32_t dual_core = core; + uint32_t single_core = CME_MASK_C0; + + // NDD2: dual cast workaround loop start + for(; single_core; single_core = single_core >> 1) { + if (single_core & dual_core) + { + core = single_core; + } + else + { + continue; + } - // Read SISR for pm_state_cX - pm_states = in32_sh(CME_LCL_SISR); - - // entry: req_level = target stop level - // act_level = current stop level - // running = FALSE, TRUE if aborted - // stopped: req_level = act_level = target and current stop level - // (if<=5) - // running = FALSE - // exit/abort: req_level = requested stop level - // act_level = latest stop level - // running = FALSE - // running: req_level = act_level = 0 - // running = TRUE - // pm_active AND running : req_level = New requested stop level - // pm_active AND !running : req_level = Not possible, - // ignore false re-entry - // !pm_active AND running : req_level = 0 by exit, - // not changing req_level - // !pm_active AND !running : req_level = Current req_level - - for (core_mask = 2; core_mask; core_mask--) +#endif + + do // while(0) loop for stop flow control { - if (core & core_mask) - { - core_index = core_mask & 1; - G_cme_stop_record.req_level[core_index] = - (pm_states & BITS64SH((36 + (core_index << 2)), 4)) >> - SHIFT64SH((39 + (core_index << 2))); - if (G_cme_stop_record.req_level[core_index] == STOP_LEVEL_1) + // Read SISR for pm_state_cX + pm_states = in32_sh(CME_LCL_SISR); + + // entry: req_level = target stop level + // act_level = current stop level + // running = FALSE, TRUE if aborted + // stopped: req_level = act_level = target and current stop level + // (if<=5) + // running = FALSE + // exit/abort: req_level = requested stop level + // act_level = latest stop level + // running = FALSE + // running: req_level = act_level = 0 + // running = TRUE + // pm_active AND running : req_level = New requested stop level + // pm_active AND !running : req_level = Not possible, + // ignore false re-entry + // !pm_active AND running : req_level = 0 by exit, + // not changing req_level + // !pm_active AND !running : req_level = Current req_level + + for (core_mask = 2; core_mask; core_mask--) + { + if (core & core_mask) { - G_cme_stop_record.act_level[core_index] = STOP_LEVEL_1; - core_stop1 |= core_mask; - } + core_index = core_mask & 1; + G_cme_stop_record.req_level[core_index] = + (pm_states & BITS64SH((36 + (core_index << 2)), 4)) >> + SHIFT64SH((39 + (core_index << 2))); - if ((pCmeImgHdr->g_cme_mode_flags & CME_STOP_11_TO_8_BIT_POS) && - (G_cme_stop_record.req_level[core_index] >= STOP_LEVEL_11)) - { - G_cme_stop_record.req_level[core_index] = STOP_LEVEL_8; - } + if (G_cme_stop_record.req_level[core_index] == STOP_LEVEL_1) + { + G_cme_stop_record.act_level[core_index] = STOP_LEVEL_1; + core_stop1 |= core_mask; + } - if ((pCmeImgHdr->g_cme_mode_flags & CME_STOP_8_TO_5_BIT_POS) && - (G_cme_stop_record.req_level[core_index] >= STOP_LEVEL_8 && - G_cme_stop_record.req_level[core_index] < STOP_LEVEL_11)) - { - G_cme_stop_record.req_level[core_index] = STOP_LEVEL_5; - } + if ((pCmeImgHdr->g_cme_mode_flags & CME_STOP_11_TO_8_BIT_POS) && + (G_cme_stop_record.req_level[core_index] >= STOP_LEVEL_11)) + { + G_cme_stop_record.req_level[core_index] = STOP_LEVEL_8; + } - if ((pCmeImgHdr->g_cme_mode_flags & CME_STOP_5_TO_4_BIT_POS) && - (G_cme_stop_record.req_level[core_index] >= STOP_LEVEL_5 && - G_cme_stop_record.req_level[core_index] < STOP_LEVEL_8)) - { - G_cme_stop_record.req_level[core_index] = STOP_LEVEL_4; - } + if ((pCmeImgHdr->g_cme_mode_flags & CME_STOP_8_TO_5_BIT_POS) && + (G_cme_stop_record.req_level[core_index] >= STOP_LEVEL_8 && + G_cme_stop_record.req_level[core_index] < STOP_LEVEL_11)) + { + G_cme_stop_record.req_level[core_index] = STOP_LEVEL_5; + } - if ((pCmeImgHdr->g_cme_mode_flags & CME_STOP_4_TO_2_BIT_POS) && - (G_cme_stop_record.req_level[core_index] == STOP_LEVEL_4)) - { - G_cme_stop_record.req_level[core_index] = STOP_LEVEL_2; + if ((pCmeImgHdr->g_cme_mode_flags & CME_STOP_5_TO_4_BIT_POS) && + (G_cme_stop_record.req_level[core_index] >= STOP_LEVEL_5 && + G_cme_stop_record.req_level[core_index] < STOP_LEVEL_8)) + { + G_cme_stop_record.req_level[core_index] = STOP_LEVEL_4; + } + + if ((pCmeImgHdr->g_cme_mode_flags & CME_STOP_4_TO_2_BIT_POS) && + (G_cme_stop_record.req_level[core_index] == STOP_LEVEL_4)) + { + G_cme_stop_record.req_level[core_index] = STOP_LEVEL_2; + } } } - } - PK_TRACE_DBG("Check: Stop Levels Request[%d %d] Actual[%d, %d]", - G_cme_stop_record.req_level[0], - G_cme_stop_record.req_level[1], - G_cme_stop_record.act_level[0], - G_cme_stop_record.act_level[1]); + PK_TRACE_DBG("Check: Stop Levels Request[%d %d] Actual[%d, %d]", + G_cme_stop_record.req_level[0], + G_cme_stop_record.req_level[1], + G_cme_stop_record.act_level[0], + G_cme_stop_record.act_level[1]); - // Mark core as to be stopped - G_cme_stop_record.core_running &= ~core; + // Mark core as to be stopped + G_cme_stop_record.core_running &= ~core; - // Request PCB Mux + // Request PCB Mux #if HW405292_NDD1_PCBMUX_SAVIOR - p9_cme_pcbmux_savior_prologue(core); + p9_cme_pcbmux_savior_prologue(core); #endif - PK_TRACE("Request PCB mux via SICR[10/11]"); - out32(CME_LCL_SICR_OR, core << SHIFT32(11)); + PK_TRACE("Request PCB mux via SICR[10/11]"); + out32(CME_LCL_SICR_OR, core << SHIFT32(11)); - // Poll Infinitely for PCB Mux Grant - while((core & (in32(CME_LCL_SISR) >> SHIFT32(11))) != core); + // Poll Infinitely for PCB Mux Grant + while((core & (in32(CME_LCL_SISR) >> SHIFT32(11))) != core); - PK_TRACE("PCB Mux Granted on Core[%d]", core); + PK_TRACE("PCB Mux Granted on Core[%d]", core); #if HW405292_NDD1_PCBMUX_SAVIOR - p9_cme_pcbmux_savior_epilogue(core); + p9_cme_pcbmux_savior_epilogue(core); #endif - // Stop 1 + // Stop 1 + + if(core_stop1) + { + PK_TRACE_DBG("Check: core[%d] core_stop1[%d]", core, core_stop1); - if(core_stop1) - { - PK_TRACE_DBG("Check: core[%d] core_stop1[%d]", core, core_stop1); #if HW386841_NDD1_DSL_STOP1_FIX - //---------------------------------------------------------------------- - PK_TRACE("+++++ +++++ STOP LEVEL 1 ENTRY +++++ +++++"); - //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + PK_TRACE("+++++ +++++ STOP LEVEL 1 ENTRY +++++ +++++"); + //---------------------------------------------------------------------- - // Note: Only Stop1 requires pulsing entry ack to pc, - // thus this is NDD1 only as well. - PK_TRACE("Pulse STOP entry acknowledgement to PC via SICR[0/1]"); - out32(CME_LCL_SICR_OR, core_stop1 << SHIFT32(1)); - out32(CME_LCL_SICR_CLR, core_stop1 << SHIFT32(1)); + // Note: Only Stop1 requires pulsing entry ack to pc, + // thus this is NDD1 only as well. + PK_TRACE("Pulse STOP entry acknowledgement to PC via SICR[0/1]"); + out32(CME_LCL_SICR_OR, core_stop1 << SHIFT32(1)); + out32(CME_LCL_SICR_CLR, core_stop1 << SHIFT32(1)); - // Removed: Do not want users to become accustomed to - // seeing Stop1 reflected in Stop History on DD1 - /* - PK_TRACE("Update STOP history: in core stop level 1"); - scom_data.words.lower = 0; - scom_data.words.upper = SSH_ACT_LV1_COMPLETE; - CME_PUTSCOM(PPM_SSHSRC, core_stop1, scom_data.value); - */ - - core = core & ~core_stop1; + // Removed: Do not want users to become accustomed to + // seeing Stop1 reflected in Stop History on DD1 + /* + PK_TRACE("Update STOP history: in core stop level 1"); + scom_data.words.lower = 0; + scom_data.words.upper = SSH_ACT_LV1_COMPLETE; + CME_PUTSCOM(PPM_SSHSRC, core_stop1, scom_data.value); + */ - if (!core) - { - // not catchup or catchup with stop2, terminates - entry_ongoing = 0; + core = core & ~core_stop1; - // otherwise, go back to origin core and continue - if (origin_core && (origin_level > STOP_LEVEL_2)) + if (!core) { - core = origin_core; - target_level = origin_level; - entry_ongoing = 1; - } + // not catchup or catchup with stop2, terminates + entry_ongoing = 0; - break; - } +#if !SKIP_ENTRY_CATCHUP + + // otherwise, go back to origin core and continue + if (origin_core && (origin_level > STOP_LEVEL_2)) + { + core = origin_core; + target_level = origin_level; + entry_ongoing = 1; + } + +#endif + + break; + } #else - // Nap should be done by hardware when auto_stop1 is enabled - // Halt on error if target STOP level == 1(Nap) - PK_TRACE_ERR("ERROR: Stop 1 Requested to CME When AUTO_STOP1 Enabled, HALT CME!"); - PK_PANIC(CME_STOP_ENTRY_WITH_AUTO_NAP); + // Nap should be done by hardware when auto_stop1 is enabled + // Halt on error if target STOP level == 1(Nap) + PK_TRACE_ERR("ERROR: Stop 1 Requested to CME When AUTO_STOP1 Enabled, HALT CME!"); + PK_PANIC(CME_STOP_ENTRY_WITH_AUTO_NAP); #endif - } - - //---------------------------------------------------------------------- - PK_TRACE("+++++ +++++ STOP LEVEL 2 ENTRY +++++ +++++"); - //---------------------------------------------------------------------- + } - // set target_level from pm_state for both cores or just one core - target_level = (core == CME_MASK_C0) ? G_cme_stop_record.req_level[0] : - G_cme_stop_record.req_level[1]; + //---------------------------------------------------------------------- + PK_TRACE("+++++ +++++ STOP LEVEL 2 ENTRY +++++ +++++"); + //---------------------------------------------------------------------- - // If both cores are going into STOP but targeting different levels, - if ((core == CME_MASK_BC) && - (G_cme_stop_record.req_level[0] != G_cme_stop_record.req_level[1])) - { - // set target_level to the lighter level targeted by one core - // set deeper_level to the deeper level targeted by deeper core - deeper_level = G_cme_stop_record.req_level[0]; - deeper_core = CME_MASK_C0; + // set target_level from pm_state for both cores or just one core + target_level = (core == CME_MASK_C0) ? G_cme_stop_record.req_level[0] : + G_cme_stop_record.req_level[1]; - if (G_cme_stop_record.req_level[0] < G_cme_stop_record.req_level[1]) + // If both cores are going into STOP but targeting different levels, + if ((core == CME_MASK_BC) && + (G_cme_stop_record.req_level[0] != G_cme_stop_record.req_level[1])) { - target_level = G_cme_stop_record.req_level[0]; - deeper_level = G_cme_stop_record.req_level[1]; - deeper_core = CME_MASK_C1; - } - } + // set target_level to the lighter level targeted by one core + // set deeper_level to the deeper level targeted by deeper core + deeper_level = G_cme_stop_record.req_level[0]; + deeper_core = CME_MASK_C0; - PK_TRACE("Update STOP history: in transition of entry"); - // Set req_level_level to target_level of either both or just one core - scom_data.words.lower = 0; - scom_data.words.upper = (SSH_REQ_LEVEL_UPDATE | - (((uint32_t)target_level) << SHIFT32(7))); - CME_PUTSCOM(PPM_SSHSRC, core, scom_data.value); + if (G_cme_stop_record.req_level[0] < G_cme_stop_record.req_level[1]) + { + target_level = G_cme_stop_record.req_level[0]; + deeper_level = G_cme_stop_record.req_level[1]; + deeper_core = CME_MASK_C1; + } + } - // Set req_level_level to deeper_level for deeper core - if (deeper_core) - { + PK_TRACE("Update STOP history: in transition of entry"); + // Set req_level_level to target_level of either both or just one core scom_data.words.lower = 0; scom_data.words.upper = (SSH_REQ_LEVEL_UPDATE | - (((uint32_t)deeper_level) << SHIFT32(7))); - CME_PUTSCOM(PPM_SSHSRC, deeper_core, scom_data.value); - } + (((uint32_t)target_level) << SHIFT32(7))); + CME_PUTSCOM(PPM_SSHSRC, core, scom_data.value); + + // Set req_level_level to deeper_level for deeper core + if (deeper_core) + { + scom_data.words.lower = 0; + scom_data.words.upper = (SSH_REQ_LEVEL_UPDATE | + (((uint32_t)deeper_level) << SHIFT32(7))); + CME_PUTSCOM(PPM_SSHSRC, deeper_core, scom_data.value); + } - PK_TRACE_DBG("Check: core[%d] target_lv[%d] deeper_lv[%d] deeper_core[%d]", - core, target_level, deeper_level, deeper_core); + PK_TRACE_DBG("Check: core[%d] target_lv[%d] deeper_lv[%d] deeper_core[%d]", + core, target_level, deeper_level, deeper_core); - // Permanent workaround for HW407385 + // Permanent workaround for HW407385 - PK_TRACE("HW407385: Assert block interrupt to PC via SICR[2/3]"); - out32(CME_LCL_SICR_OR, core << SHIFT32(3)); + PK_TRACE("HW407385: Assert block interrupt to PC via SICR[2/3]"); + out32(CME_LCL_SICR_OR, core << SHIFT32(3)); - PK_TRACE("HW407385: Waking up the core(pm_exit=1) via SICR[4/5]"); - out32(CME_LCL_SICR_OR, core << SHIFT32(5)); + PK_TRACE("HW407385: Waking up the core(pm_exit=1) via SICR[4/5]"); + out32(CME_LCL_SICR_OR, core << SHIFT32(5)); - PK_TRACE("HW407385: Polling for core wakeup(pm_active=0) via EINR[20/21]"); + PK_TRACE("HW407385: Polling for core wakeup(pm_active=0) via EINR[20/21]"); - while((in32(CME_LCL_EINR)) & (core << SHIFT32(21))); + while((in32(CME_LCL_EINR)) & (core << SHIFT32(21))); - // end of HW407385 + // end of HW407385 #if HW402407_NDD1_TLBIE_STOP_WORKAROUND - // Save thread's LPIDs and overwrite with POWMAN_RESERVED_LPID - prepare_for_ramming(core); + // Save thread's LPIDs and overwrite with POWMAN_RESERVED_LPID + prepare_for_ramming(core); - for (thread = 0; thread < 4; thread++ ) - { - if (core & CME_MASK_C0) + for (thread = 0; thread < 4; thread++ ) { - lpid_c0[thread] = ram_read_lpid(CME_MASK_C0, thread); - PK_TRACE("c0lpid %X thread %X", (uint32_t) lpid_c0[thread], thread); - } + if (core & CME_MASK_C0) + { + lpid_c0[thread] = ram_read_lpid(CME_MASK_C0, thread); + PK_TRACE("c0lpid %X thread %X", (uint32_t) lpid_c0[thread], thread); + } - if (core & CME_MASK_C1) - { - lpid_c1[thread] = ram_read_lpid(CME_MASK_C1, thread); - PK_TRACE("c1lpid %X thread %X", (uint32_t) lpid_c1[thread], thread); + if (core & CME_MASK_C1) + { + lpid_c1[thread] = ram_read_lpid(CME_MASK_C1, thread); + PK_TRACE("c1lpid %X thread %X", (uint32_t) lpid_c1[thread], thread); + } } - } - for (thread = 0; thread < 4; thread++ ) - { - if (core & CME_MASK_C0) + for (thread = 0; thread < 4; thread++ ) { - ram_write_lpid(CME_MASK_C0, thread, POWMAN_RESERVED_LPID); + if (core & CME_MASK_C0) + { + ram_write_lpid(CME_MASK_C0, thread, POWMAN_RESERVED_LPID); #if HW402407_PARANOID_LPID_MODE - if (ram_read_lpid(CME_MASK_C0, thread) != POWMAN_RESERVED_LPID) - { - PK_TRACE_ERR("ERROR: C0 READ LPID not equal to expected value. HALT CME!"); - PK_PANIC(CME_STOP_ENTRY_BAD_LPID_ERROR); - } + if (ram_read_lpid(CME_MASK_C0, thread) != POWMAN_RESERVED_LPID) + { + PK_TRACE_ERR("ERROR: C0 READ LPID not equal to expected value. HALT CME!"); + PK_PANIC(CME_STOP_ENTRY_BAD_LPID_ERROR); + } #endif - } + } - if (core & CME_MASK_C1) - { - ram_write_lpid(CME_MASK_C1, thread, POWMAN_RESERVED_LPID); + if (core & CME_MASK_C1) + { + ram_write_lpid(CME_MASK_C1, thread, POWMAN_RESERVED_LPID); #if HW402407_PARANOID_LPID_MODE - if (ram_read_lpid(CME_MASK_C1, thread) != POWMAN_RESERVED_LPID) - { - PK_TRACE_ERR("ERROR: C1 READ LPID not equal to expected value. HALT CME!"); - PK_PANIC(CME_STOP_ENTRY_BAD_LPID_ERROR); - } + if (ram_read_lpid(CME_MASK_C1, thread) != POWMAN_RESERVED_LPID) + { + PK_TRACE_ERR("ERROR: C1 READ LPID not equal to expected value. HALT CME!"); + PK_PANIC(CME_STOP_ENTRY_BAD_LPID_ERROR); + } #endif + } } - } #endif // tlbie stop workaround - PK_TRACE_INF("SE.2A: Core[%d] PCB Mux Granted", core); + PK_TRACE_INF("SE.2A: Core[%d] PCB Mux Granted", core); - //============================= - MARK_TRAP(SE_QUIESCE_CORE_INTF) - //============================= + //============================= + MARK_TRAP(SE_QUIESCE_CORE_INTF) + //============================= - PK_TRACE("Assert halt STOP override disable via LMCR[14/15]"); - out32(CME_LCL_LMCR_OR, (core << SHIFT32(15))); + PK_TRACE("Assert halt STOP override disable via LMCR[14/15]"); + out32(CME_LCL_LMCR_OR, (core << SHIFT32(15))); #if SPWU_AUTO - PK_TRACE("Assert auto special wakeup disable via LMCR[12/13]"); - out32(CME_LCL_LMCR_OR, (core << SHIFT32(13))); + PK_TRACE("Assert auto special wakeup disable via LMCR[12/13]"); + out32(CME_LCL_LMCR_OR, (core << SHIFT32(13))); #endif #if HW402407_NDD1_TLBIE_STOP_WORKAROUND - // Need to wait for any pending TLBIEs to complete - PPE_WAIT_CORE_CYCLES(2000) + // Need to wait for any pending TLBIEs to complete + PPE_WAIT_CORE_CYCLES(2000) #endif - PK_TRACE("Assert core-L2 + core-CC quiesces via SICR[6/7,8/9]"); - out32(CME_LCL_SICR_OR, (core << SHIFT32(7)) | (core << SHIFT32(9))); + PK_TRACE("Assert core-L2 + core-CC quiesces via SICR[6/7,8/9]"); + out32(CME_LCL_SICR_OR, (core << SHIFT32(7)) | (core << SHIFT32(9))); - PK_TRACE("Poll for L2 interface quiesced via SISR[30/31]"); + PK_TRACE("Poll for L2 interface quiesced via SISR[30/31]"); - do - { - lclr_data = in32(CME_LCL_SISR); - } - while((lclr_data & core) != core); + do + { + lclr_data = in32(CME_LCL_SISR); + } + while((lclr_data & core) != core); - // Waits quiesce done for at least 512 core cycles - PPE_WAIT_CORE_CYCLES(512) + // Waits quiesce done for at least 512 core cycles + PPE_WAIT_CORE_CYCLES(512) - PK_TRACE_INF("SE.2B: Interfaces Quiesced"); + PK_TRACE_INF("SE.2B: Interfaces Quiesced"); #if HW402407_NDD1_TLBIE_STOP_WORKAROUND - // Restore thread's LPIDs + // Restore thread's LPIDs - for (thread = 0; thread < 4; thread++ ) - { - if (core & CME_MASK_C0) + for (thread = 0; thread < 4; thread++ ) { - ram_write_lpid(CME_MASK_C0, thread, lpid_c0[thread]); - } + if (core & CME_MASK_C0) + { + ram_write_lpid(CME_MASK_C0, thread, lpid_c0[thread]); + } - if (core & CME_MASK_C1) - { - ram_write_lpid(CME_MASK_C1, thread, lpid_c1[thread]); + if (core & CME_MASK_C1) + { + ram_write_lpid(CME_MASK_C1, thread, lpid_c1[thread]); + } } - } #if HW402407_PARANOID_LPID_MODE - // Read back and check - for (thread = 0; thread < 4; thread++ ) - { - if (core & CME_MASK_C0) + // Read back and check + for (thread = 0; thread < 4; thread++ ) { - if (ram_read_lpid(CME_MASK_C0, thread) != lpid_c0[thread]) + if (core & CME_MASK_C0) { - PK_TRACE_ERR("ERROR: Core0 READ LPID not equal to expected value. HALT CME!"); - PK_PANIC(CME_STOP_ENTRY_BAD_LPID_ERROR); + if (ram_read_lpid(CME_MASK_C0, thread) != lpid_c0[thread]) + { + PK_TRACE_ERR("ERROR: Core0 READ LPID not equal to expected value. HALT CME!"); + PK_PANIC(CME_STOP_ENTRY_BAD_LPID_ERROR); + } } - } - if (core & CME_MASK_C1) - { - if (ram_read_lpid(CME_MASK_C1, thread) != lpid_c1[thread]) + if (core & CME_MASK_C1) { - PK_TRACE_ERR("ERROR: Core1 READ LPID not equal to expected value. HALT CME!"); - PK_PANIC(CME_STOP_ENTRY_BAD_LPID_ERROR); + if (ram_read_lpid(CME_MASK_C1, thread) != lpid_c1[thread]) + { + PK_TRACE_ERR("ERROR: Core1 READ LPID not equal to expected value. HALT CME!"); + PK_PANIC(CME_STOP_ENTRY_BAD_LPID_ERROR); + } } } - } #endif - turn_off_ram_mode (core); + turn_off_ram_mode (core); #endif // tlbie stop workaround - // Permanent workaround for HW407385 + // Permanent workaround for HW407385 - PK_TRACE("HW407385: Drop pm_exit via SICR[4/5]"); - out32(CME_LCL_SICR_CLR, core << SHIFT32(5)); + PK_TRACE("HW407385: Drop pm_exit via SICR[4/5]"); + out32(CME_LCL_SICR_CLR, core << SHIFT32(5)); - PK_TRACE("HW407385: Polling for core to stop(pm_active=1) via EINR[20/21]"); + PK_TRACE("HW407385: Polling for core to stop(pm_active=1) via EINR[20/21]"); - while((~(in32(CME_LCL_EINR))) & (core << SHIFT32(21))); + while((~(in32(CME_LCL_EINR))) & (core << SHIFT32(21))); - PK_TRACE("HW407385: Clear pm_active status via EISR[20/21]"); - out32(CME_LCL_EISR_CLR, core << SHIFT32(21)); + PK_TRACE("HW407385: Clear pm_active status via EISR[20/21]"); + out32(CME_LCL_EISR_CLR, core << SHIFT32(21)); - PK_TRACE("HW407385: Drop block interrupt to PC via SICR[2/3]"); - out32(CME_LCL_SICR_CLR, core << SHIFT32(3)); + PK_TRACE("HW407385: Drop block interrupt to PC via SICR[2/3]"); + out32(CME_LCL_SICR_CLR, core << SHIFT32(3)); - // end of HW407385 + // end of HW407385 - //========================== - MARK_TRAP(SE_STOP_CORE_CLKS) - //========================== + //========================== + MARK_TRAP(SE_STOP_CORE_CLKS) + //========================== - PK_TRACE("Assert core chiplet fence via NET_CTRL0[18]"); - CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(18)); + PK_TRACE("Assert core chiplet fence via NET_CTRL0[18]"); + CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(18)); - PK_TRACE("Clear SCAN_REGION_TYPE prior to stop core clocks"); - CME_PUTSCOM(C_SCAN_REGION_TYPE, core, 0); + PK_TRACE("Clear SCAN_REGION_TYPE prior to stop core clocks"); + CME_PUTSCOM(C_SCAN_REGION_TYPE, core, 0); #if NIMBUS_DD_LEVEL == 1 - // NDD1: Core Global Xstop FIR - if (core & CME_MASK_C0) - { - CME_GETSCOM(0x20040000, CME_MASK_C0, CME_SCOM_AND, scom_data.value); - - if (scom_data.value) + // NDD1: Core Global Xstop FIR + if (core & CME_MASK_C0) { - PK_TRACE_ERR("ERROR: Core[%d] GLOBAL XSTOP[%x] DETECTED. HALT CME!", - core, scom_data.words.upper); - PK_PANIC(CME_STOP_ENTRY_XSTOP_ERROR); - } - } + CME_GETSCOM(0x20040000, CME_MASK_C0, CME_SCOM_AND, scom_data.value); - if (core & CME_MASK_C1) - { - CME_GETSCOM(0x20040000, CME_MASK_C1, CME_SCOM_AND, scom_data.value); + if (scom_data.value) + { + PK_TRACE_ERR("ERROR: Core[%d] GLOBAL XSTOP[%x] DETECTED. HALT CME!", + core, scom_data.words.upper); + PK_PANIC(CME_STOP_ENTRY_XSTOP_ERROR); + } + } - if (scom_data.value) + if (core & CME_MASK_C1) { - PK_TRACE_ERR("ERROR: Core[%d] GLOBAL XSTOP[%x] DETECTED. HALT CME!", - core, scom_data.words.upper); - PK_PANIC(CME_STOP_ENTRY_XSTOP_ERROR); + CME_GETSCOM(0x20040000, CME_MASK_C1, CME_SCOM_AND, scom_data.value); + + if (scom_data.value) + { + PK_TRACE_ERR("ERROR: Core[%d] GLOBAL XSTOP[%x] DETECTED. HALT CME!", + core, scom_data.words.upper); + PK_PANIC(CME_STOP_ENTRY_XSTOP_ERROR); + } } - } #endif - PK_TRACE("Stop Core Clocks via CLK_REGION"); - CME_PUTSCOM(C_CLK_REGION, core, - (CLK_STOP_CMD | CLK_REGION_ALL_BUT_PLL | CLK_THOLD_ALL)); + PK_TRACE("Stop Core Clocks via CLK_REGION"); + CME_PUTSCOM(C_CLK_REGION, core, + (CLK_STOP_CMD | CLK_REGION_ALL_BUT_PLL | CLK_THOLD_ALL)); - PK_TRACE("Poll for core clocks stopped via CPLT_STAT0[8]"); + PK_TRACE("Poll for core clocks stopped via CPLT_STAT0[8]"); - do - { - CME_GETSCOM(C_CPLT_STAT0, core, CME_SCOM_AND, scom_data.value); - } - while(!(scom_data.words.upper & BIT32(8))); + do + { + CME_GETSCOM(C_CPLT_STAT0, core, CME_SCOM_AND, scom_data.value); + } + while(!(scom_data.words.upper & BIT32(8))); - PK_TRACE("Check core clock is stopped via CLOCK_STAT_SL[4-13]"); - CME_GETSCOM(C_CLOCK_STAT_SL, core, CME_SCOM_AND, scom_data.value); + PK_TRACE("Check core clock is stopped via CLOCK_STAT_SL[4-13]"); + CME_GETSCOM(C_CLOCK_STAT_SL, core, CME_SCOM_AND, scom_data.value); - if (((~scom_data.value) & CLK_REGION_ALL_BUT_PLL) != 0) - { - PK_TRACE_ERR("ERROR: Core Clock Stop Failed. HALT CME!"); - PK_PANIC(CME_STOP_ENTRY_STOPCLK_FAILED); - } - - PK_TRACE_INF("SE.2C: Core Clock Stopped"); + if (((~scom_data.value) & CLK_REGION_ALL_BUT_PLL) != 0) + { + PK_TRACE_ERR("ERROR: Core Clock Stop Failed. HALT CME!"); + PK_PANIC(CME_STOP_ENTRY_STOPCLK_FAILED); + } - //============================== - MARK_TRAP(SE_STOP_CORE_GRID) - //============================== + PK_TRACE_INF("SE.2C: Core Clock Stopped"); - PK_TRACE("Drop clock sync enable before switch to refclk via CACCR[15]"); - CME_PUTSCOM(CPPM_CACCR_CLR, core, BIT64(15)); + //============================== + MARK_TRAP(SE_STOP_CORE_GRID) + //============================== - PK_TRACE("Poll for clock sync done to drop via CACSR[13]"); + PK_TRACE("Drop clock sync enable before switch to refclk via CACCR[15]"); + CME_PUTSCOM(CPPM_CACCR_CLR, core, BIT64(15)); - do - { - CME_GETSCOM(CPPM_CACSR, core, CME_SCOM_OR, scom_data.value); - } - while(scom_data.words.upper & BIT32(13)); + PK_TRACE("Poll for clock sync done to drop via CACSR[13]"); - p9_cme_analog_control(core, ANALOG_DISABLE); + do + { + CME_GETSCOM(CPPM_CACSR, core, CME_SCOM_OR, scom_data.value); + } + while(scom_data.words.upper & BIT32(13)); - PK_TRACE("Switch glsmux to refclk to save clock grid power via CGCR[3]"); - CME_PUTSCOM(C_PPM_CGCR, core, 0); + p9_cme_analog_control(core, ANALOG_DISABLE); - PK_TRACE("Assert skew sense to skewadjust fence via NET_CTRL0[22]"); - CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(22)); + PK_TRACE("Switch glsmux to refclk to save clock grid power via CGCR[3]"); + CME_PUTSCOM(C_PPM_CGCR, core, 0); - PK_TRACE("Drop ABIST_SRAM_MODE_DC to support ABIST Recovery via BIST[1]"); - CME_GETSCOM(C_BIST, core, CME_SCOM_AND, scom_data.value); - scom_data.words.upper &= ~BIT32(1); - CME_PUTSCOM(C_BIST, core, scom_data.value); + PK_TRACE("Assert skew sense to skewadjust fence via NET_CTRL0[22]"); + CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(22)); - PK_TRACE("Assert vital fence via CPLT_CTRL1[3]"); - CME_PUTSCOM(C_CPLT_CTRL1_OR, core, BIT64(3)); + PK_TRACE("Drop ABIST_SRAM_MODE_DC to support ABIST Recovery via BIST[1]"); + CME_GETSCOM(C_BIST, core, CME_SCOM_AND, scom_data.value); + scom_data.words.upper &= ~BIT32(1); + CME_PUTSCOM(C_BIST, core, scom_data.value); - PK_TRACE("Assert regional fences via CPLT_CTRL1[4-13]"); - CME_PUTSCOM(C_CPLT_CTRL1_OR, core, BITS64(4, 11)); + PK_TRACE("Assert vital fence via CPLT_CTRL1[3]"); + CME_PUTSCOM(C_CPLT_CTRL1_OR, core, BIT64(3)); - PK_TRACE("Drop sdis_n(flushing LCBES condition) via CPLT_CONF0[34]"); - CME_PUTSCOM(C_CPLT_CONF0_CLEAR, core, BIT64(34)); + PK_TRACE("Assert regional fences via CPLT_CTRL1[4-13]"); + CME_PUTSCOM(C_CPLT_CTRL1_OR, core, BITS64(4, 11)); - // Allow queued scoms to complete to Core EPS before switching to Core PPM - sync(); + // Allow queued scoms to complete to Core EPS before switching to Core PPM + sync(); - PK_TRACE("Copy PECE CME sample to PPM Shadow via PECES"); + PK_TRACE("Drop sdis_n(flushing LCBES condition) via CPLT_CONF0[34]"); + CME_PUTSCOM(C_CPLT_CONF0_CLEAR, core, BIT64(34)); - if (core & CME_MASK_C0) - { - scom_data.value = in64(CME_LCL_PECESR0); - CME_PUTSCOM(CPPM_PECES, CME_MASK_C0, scom_data.value); - G_cme_stop_record.act_level[0] = STOP_LEVEL_2; - } + PK_TRACE("Copy PECE CME sample to PPM Shadow via PECES"); - if (core & CME_MASK_C1) - { - scom_data.value = in64(CME_LCL_PECESR1); - CME_PUTSCOM(CPPM_PECES, CME_MASK_C1, scom_data.value); - G_cme_stop_record.act_level[1] = STOP_LEVEL_2; - } + if (core & CME_MASK_C0) + { + scom_data.value = in64(CME_LCL_PECESR0); + CME_PUTSCOM(CPPM_PECES, CME_MASK_C0, scom_data.value); + G_cme_stop_record.act_level[0] = STOP_LEVEL_2; + } - PK_TRACE_INF("SE.2D: Clock Sync Dropped"); + if (core & CME_MASK_C1) + { + scom_data.value = in64(CME_LCL_PECESR1); + CME_PUTSCOM(CPPM_PECES, CME_MASK_C1, scom_data.value); + G_cme_stop_record.act_level[1] = STOP_LEVEL_2; + } - //=========================== - MARK_TAG(SE_STOP2_DONE, core) - //=========================== + PK_TRACE_INF("SE.2D: Clock Sync Dropped"); - PK_TRACE("Update STOP history: in core stop level 2"); - // Check if STOP level 2 reaches the target for both or one core - entry_ongoing = - target_level == STOP_LEVEL_2 ? - STOP_TRANS_COMPLETE : STOP_TRANS_ENTRY; + //=========================== + MARK_TAG(SE_STOP2_DONE, core) + //=========================== - scom_data.words.lower = 0; - scom_data.words.upper = (SSH_ACT_LV2_COMPLETE | - (((uint32_t)entry_ongoing) << SHIFT32(3))); - CME_PUTSCOM(PPM_SSHSRC, core, scom_data.value); + PK_TRACE("Update STOP history: in core stop level 2"); + // Check if STOP level 2 reaches the target for both or one core + entry_ongoing = + target_level == STOP_LEVEL_2 ? + STOP_TRANS_COMPLETE : STOP_TRANS_ENTRY; - // If both cores targeting different levels - // deeper core should have at least deeper stop level than 2 - // but only need to modify deeper core history if another one was done - if (deeper_core && !entry_ongoing) - { scom_data.words.lower = 0; - scom_data.words.upper = SSH_ACT_LV2_CONTINUE; - CME_PUTSCOM(PPM_SSHSRC, deeper_core, scom_data.value); - - // from now on, proceed with only deeper core - core = deeper_core; - target_level = deeper_level; - deeper_level = 0; - deeper_core = 0; - entry_ongoing = 1; - } + scom_data.words.upper = (SSH_ACT_LV2_COMPLETE | + (((uint32_t)entry_ongoing) << SHIFT32(3))); + CME_PUTSCOM(PPM_SSHSRC, core, scom_data.value); + + // If both cores targeting different levels + // deeper core should have at least deeper stop level than 2 + // but only need to modify deeper core history if another one was done + if (deeper_core && !entry_ongoing) + { + scom_data.words.lower = 0; + scom_data.words.upper = SSH_ACT_LV2_CONTINUE; + CME_PUTSCOM(PPM_SSHSRC, deeper_core, scom_data.value); + + // from now on, proceed with only deeper core + core = deeper_core; + target_level = deeper_level; + deeper_level = 0; + deeper_core = 0; + entry_ongoing = 1; + } #if !SKIP_ENTRY_CATCHUP - if (catchup_ongoing) - { - // Y = 2 eo = 0 same if X = 2 - // Y > 2 eo = 1 c=c t=t same if X = 2 - // if X > 2 eo = 1 - // if Y = 2 c=o t=o - // else (Y > 2) c=2 - // if X != Y (X = Y: dl=0 dc=0 t=t) - // dl=o dc=o (X > Y) - // if X < Y - // dl=t dc=c t=o - if (origin_level > STOP_LEVEL_2) + if (catchup_ongoing) { - if (target_level == STOP_LEVEL_2) - { - core = origin_core; - target_level = origin_level; - } - else + // Y = 2 eo = 0 same if X = 2 + // Y > 2 eo = 1 c=c t=t same if X = 2 + // if X > 2 eo = 1 + // if Y = 2 c=o t=o + // else (Y > 2) c=2 + // if X != Y (X = Y: dl=0 dc=0 t=t) + // dl=o dc=o (X > Y) + // if X < Y + // dl=t dc=c t=o + if (origin_level > STOP_LEVEL_2) { - if (origin_level != target_level) + if (target_level == STOP_LEVEL_2) { - deeper_core = origin_core; - deeper_level = origin_level; - - if (origin_level < target_level) + core = origin_core; + target_level = origin_level; + } + else + { + if (origin_level != target_level) { - deeper_core = core; - deeper_level = target_level; - target_level = origin_level; + deeper_core = origin_core; + deeper_level = origin_level; + + if (origin_level < target_level) + { + deeper_core = core; + deeper_level = target_level; + target_level = origin_level; + } } + + core = CME_MASK_BC; } - core = CME_MASK_BC; + entry_ongoing = 1; } - entry_ongoing = 1; + break; } - break; - } - - core_catchup = (in32(CME_LCL_EISR) & BITS32(20, 2)) >> SHIFT32(21); - core_catchup = core_catchup & G_cme_record.core_enabled & - G_cme_stop_record.core_running; + core_catchup = (in32(CME_LCL_EISR) & BITS32(20, 2)) >> SHIFT32(21); + core_catchup = core_catchup & G_cme_record.core_enabled & + G_cme_stop_record.core_running; - if (core_catchup) - { - out32(CME_LCL_EISR_CLR, core_catchup << SHIFT32(21)); - origin_core = core; - origin_level = target_level; - core = core_catchup; - catchup_ongoing = 1; - - //======================== - MARK_TAG(SE_CATCHUP, core) - //======================== - } + if (core_catchup) + { + out32(CME_LCL_EISR_CLR, core_catchup << SHIFT32(21)); + origin_core = core; + origin_level = target_level; + core = core_catchup; + catchup_ongoing = 1; + + //======================== + MARK_TAG(SE_CATCHUP, core) + //======================== + } - PK_TRACE_DBG("Catch: core[%d] running[%d] core_catchup[%d] origin_core[%d]", - core, G_cme_stop_record.core_running, core_catchup, origin_core); + PK_TRACE_DBG("Catch: core[%d] running[%d] core_catchup[%d] origin_core[%d]", + core, G_cme_stop_record.core_running, core_catchup, origin_core); #endif - } - while(catchup_ongoing); - - do - { + } + while(catchup_ongoing); - // If we are done at STOP level 2 - if (!entry_ongoing) + do { - break; - } - //=========================== - MARK_TRAP(SE_IS0_BEGIN) - //=========================== + // If we are done at STOP level 2 + if (!entry_ongoing) + { + break; + } + + //=========================== + MARK_TRAP(SE_IS0_BEGIN) + //=========================== #if !SKIP_ABORT - out32(CME_LCL_EIMR_CLR, (core << SHIFT32(13)) | - (core << SHIFT32(15)) | - (core << SHIFT32(17))); - sync(); - out32(CME_LCL_EIMR_OR, (BITS32(12, 6) | BITS32(20, 2))); + out32(CME_LCL_EIMR_CLR, (core << SHIFT32(13)) | + (core << SHIFT32(15)) | + (core << SHIFT32(17))); + sync(); + out32(CME_LCL_EIMR_OR, (BITS32(12, 6) | BITS32(20, 2))); #endif - //=================== - MARK_TRAP(SE_IS0_END) - //=================== + //=================== + MARK_TRAP(SE_IS0_END) + //=================== - core_aborted = core & G_cme_stop_record.core_running; - core = core & ~G_cme_stop_record.core_running; + core_aborted = core & G_cme_stop_record.core_running; + core = core & ~G_cme_stop_record.core_running; - PK_TRACE_DBG("Abort: core[%d] running[%d] core_aborted[%d]", - core, G_cme_stop_record.core_running, core_aborted); + PK_TRACE_DBG("Abort: core[%d] running[%d] core_aborted[%d]", + core, G_cme_stop_record.core_running, core_aborted); - if (!core) - { - core |= core_aborted; - entry_ongoing = 0; - break; - } + if (!core) + { + core |= core_aborted; + entry_ongoing = 0; + break; + } - if (core_aborted && deeper_core) - { - if (core_aborted != deeper_core) + if (core_aborted && deeper_core) { - target_level = deeper_level; + if (core_aborted != deeper_core) + { + target_level = deeper_level; + } + + deeper_core = 0; } - deeper_core = 0; - } + PK_TRACE_DBG("Check: core[%d] deeper_core[%d] target_level[%d] deeper_level[%d]", + core, deeper_core, target_level, deeper_level); + + //---------------------------------------------------------------------- + PK_TRACE("+++++ +++++ STOP LEVEL 3 ENTRY +++++ +++++"); + //---------------------------------------------------------------------- - PK_TRACE_DBG("Check: core[%d] deeper_core[%d] target_level[%d] deeper_level[%d]", - core, deeper_core, target_level, deeper_level); + if (target_level == 3) + { + /* + //========================== + MARK_TAG(SE_CORE_VMIN, core) + //========================== + + PK_TRACE("SE3.a"); + // Enable IVRM if not already + + PK_TRACE("SE3.b"); + + // Drop to Vmin + if(core & CME_MASK_C0) + { + G_cme_stop_record.act_level[0] = STOP_LEVEL_3; + } + + if(core & CME_MASK_C1) + { + G_cme_stop_record.act_level[1] = STOP_LEVEL_3; + } + + //=========================== + MARK_TAG(SE_STOP3_DONE, core) + //=========================== + + PK_TRACE("SE3.c"); + // Update Stop History: In Core Stop Level 3 + scom_data.words.lower = 0; + scom_data.words.upper = SSH_ACT_LV3_COMPLETE; + CME_PUTSCOM(PPM_SSHSRC, core, scom_data.value); + */ + // If both cores targeting different levels + // deeper core should have at least deeper stop level than 3 + // only need to modify deeper core history if another one was done + if (deeper_core) + { + /* + scom_data.words.lower = 0; + scom_data.words.upper = SSH_ACT_LV3_CONTINUE; + CME_PUTSCOM(PPM_SSHSRC, deeper_core, scom_data.value); + */ + // from now on, proceed with only deeper core + core = deeper_core; + target_level = deeper_level; + deeper_level = 0; + deeper_core = 0; + entry_ongoing = 1; + } + else + { + entry_ongoing = 0; + } - //---------------------------------------------------------------------- - PK_TRACE("+++++ +++++ STOP LEVEL 3 ENTRY +++++ +++++"); - //---------------------------------------------------------------------- + // If we are done at STOP level 3 + if (!entry_ongoing) + { + break; + } + } - if (target_level == 3) - { - /* - //========================== - MARK_TAG(SE_CORE_VMIN, core) - //========================== + //---------------------------------------------------------------------- + PK_TRACE("+++++ +++++ STOP LEVEL 4 ENTRY +++++ +++++"); + //---------------------------------------------------------------------- - PK_TRACE("SE3.a"); - // Enable IVRM if not already + //=============================== + MARK_TAG(SE_POWER_OFF_CORE, core) + //=============================== - PK_TRACE("SE3.b"); + PK_TRACE("Assert PCB fence via NET_CTRL0[25]"); + CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(25)); - // Drop to Vmin - if(core & CME_MASK_C0) - { - G_cme_stop_record.act_level[0] = STOP_LEVEL_3; - } + PK_TRACE("Assert electrical fence via NET_CTRL0[26]"); + CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(26)); - if(core & CME_MASK_C1) - { - G_cme_stop_record.act_level[1] = STOP_LEVEL_3; - } + PK_TRACE("Assert vital thold via NET_CTRL0[16]"); + CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(16)); - //=========================== - MARK_TAG(SE_STOP3_DONE, core) - //=========================== +#if !STOP_PRIME - PK_TRACE("SE3.c"); - // Update Stop History: In Core Stop Level 3 - scom_data.words.lower = 0; - scom_data.words.upper = SSH_ACT_LV3_COMPLETE; - CME_PUTSCOM(PPM_SSHSRC, core, scom_data.value); - */ - // If both cores targeting different levels - // deeper core should have at least deeper stop level than 3 - // only need to modify deeper core history if another one was done - if (deeper_core) + // NDD2: OOB bits wired to SISR + // not implemented in DD1 + // bit0 is System checkstop + // bit1 is Recoverable Error + // bit2 is Special Attention + // bit3 is Core Checkstop + if (((core & CME_MASK_C0) && (in32(CME_LCL_SISR) & BITS32(12, 4))) || + ((core & CME_MASK_C1) && (in32_sh(CME_LCL_SISR) & BITS64SH(60, 4)))) { - /* - scom_data.words.lower = 0; - scom_data.words.upper = SSH_ACT_LV3_CONTINUE; - CME_PUTSCOM(PPM_SSHSRC, deeper_core, scom_data.value); - */ - // from now on, proceed with only deeper core - core = deeper_core; - target_level = deeper_level; - deeper_level = 0; - deeper_core = 0; - entry_ongoing = 1; + PK_TRACE_INF("WARNING: Xstop/Attn/Recov Present, Skip Core Power Off"); } else { - entry_ongoing = 0; - } - - // If we are done at STOP level 3 - if (!entry_ongoing) - { - break; - } - } - - //---------------------------------------------------------------------- - PK_TRACE("+++++ +++++ STOP LEVEL 4 ENTRY +++++ +++++"); - //---------------------------------------------------------------------- + PK_TRACE("Drop vdd_pfet_val/sel_override/regulation_finger_en via PFCS[4,5,8]"); + // vdd_pfet_val/sel_override = 0 (disbaled) + // vdd_pfet_regulation_finger_en = 0 (controled by FSM) + CME_PUTSCOM(PPM_PFCS_CLR, core, BIT64(4) | BIT64(5) | BIT64(8)); - //=============================== - MARK_TAG(SE_POWER_OFF_CORE, core) - //=============================== + PK_TRACE("Power off core VDD via PFCS[0-1]"); + // vdd_pfet_force_state = 01 (Force Voff) + CME_PUTSCOM(PPM_PFCS_OR, core, BIT64(1)); - PK_TRACE("Assert PCB fence via NET_CTRL0[25]"); - CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(25)); + PK_TRACE("Poll for vdd_pfets_disabled_sense via PFSNS[1]"); - PK_TRACE("Assert electrical fence via NET_CTRL0[26]"); - CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(26)); - - PK_TRACE("Assert vital thold via NET_CTRL0[16]"); - CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(16)); - -#if !STOP_PRIME + do + { + CME_GETSCOM(PPM_PFSNS, core, CME_SCOM_AND, scom_data.value); + } + while(!(scom_data.words.upper & BIT32(1))); - // NDD2: OOB bits wired to SISR - // not implemented in DD1 - // bit0 is System checkstop - // bit1 is Recoverable Error - // bit2 is Special Attention - // bit3 is Core Checkstop - if (((core & CME_MASK_C0) && (in32(CME_LCL_SISR) & BITS32(12, 4))) || - ((core & CME_MASK_C1) && (in32_sh(CME_LCL_SISR) & BITS64SH(60, 4)))) - { - PK_TRACE_INF("WARNING: Xstop/Attn/Recov Present, Skip Core Power Off"); - } - else - { - PK_TRACE("Drop vdd_pfet_val/sel_override/regulation_finger_en via PFCS[4,5,8]"); - // vdd_pfet_val/sel_override = 0 (disbaled) - // vdd_pfet_regulation_finger_en = 0 (controled by FSM) - CME_PUTSCOM(PPM_PFCS_CLR, core, BIT64(4) | BIT64(5) | BIT64(8)); + PK_TRACE("Turn off force voff via PFCS[0-1]"); + // vdd_pfet_force_state = 00 (Nop) + CME_PUTSCOM(PPM_PFCS_CLR, core, BITS64(0, 2)); - PK_TRACE("Power off core VDD via PFCS[0-1]"); - // vdd_pfet_force_state = 01 (Force Voff) - CME_PUTSCOM(PPM_PFCS_OR, core, BIT64(1)); + PK_TRACE_INF("SE.4A: Core[%d] Powered Off", core); + } - PK_TRACE("Poll for vdd_pfets_disabled_sense via PFSNS[1]"); +#endif - do + if (core & CME_MASK_C0) { - CME_GETSCOM(PPM_PFSNS, core, CME_SCOM_AND, scom_data.value); + G_cme_stop_record.act_level[0] = STOP_LEVEL_4; } - while(!(scom_data.words.upper & BIT32(1))); - PK_TRACE("Turn off force voff via PFCS[0-1]"); - // vdd_pfet_force_state = 00 (Nop) - CME_PUTSCOM(PPM_PFCS_CLR, core, BITS64(0, 2)); + if (core & CME_MASK_C1) + { + G_cme_stop_record.act_level[1] = STOP_LEVEL_4; + } - PK_TRACE_INF("SE.4A: Core[%d] Powered Off", core); - } + //=========================== + MARK_TAG(SE_STOP4_DONE, core) + //=========================== -#endif + PK_TRACE("Update STOP history: in core stop level 4"); + // Check if STOP level 4 reaches the target for both or one core + entry_ongoing = + target_level == STOP_LEVEL_4 ? STOP_TRANS_COMPLETE : + STOP_TRANS_ENTRY; - if (core & CME_MASK_C0) - { - G_cme_stop_record.act_level[0] = STOP_LEVEL_4; - } + scom_data.words.lower = 0; + scom_data.words.upper = (SSH_ACT_LV4_COMPLETE | + (((uint32_t)entry_ongoing) << SHIFT32(3))); + CME_PUTSCOM(PPM_SSHSRC, core, scom_data.value); - if (core & CME_MASK_C1) - { - G_cme_stop_record.act_level[1] = STOP_LEVEL_4; - } + // If both cores targeting different levels + // deeper core should have at least deeper stop level than 4 + // only need to modify deeper core history if another one was done + if (deeper_core && !entry_ongoing) + { + scom_data.words.lower = 0; + scom_data.words.upper = SSH_ACT_LV4_CONTINUE; + CME_PUTSCOM(PPM_SSHSRC, deeper_core, scom_data.value); - //=========================== - MARK_TAG(SE_STOP4_DONE, core) - //=========================== - - PK_TRACE("Update STOP history: in core stop level 4"); - // Check if STOP level 4 reaches the target for both or one core - entry_ongoing = - target_level == STOP_LEVEL_4 ? STOP_TRANS_COMPLETE : - STOP_TRANS_ENTRY; - - scom_data.words.lower = 0; - scom_data.words.upper = (SSH_ACT_LV4_COMPLETE | - (((uint32_t)entry_ongoing) << SHIFT32(3))); - CME_PUTSCOM(PPM_SSHSRC, core, scom_data.value); - - // If both cores targeting different levels - // deeper core should have at least deeper stop level than 4 - // only need to modify deeper core history if another one was done - if (deeper_core && !entry_ongoing) - { - scom_data.words.lower = 0; - scom_data.words.upper = SSH_ACT_LV4_CONTINUE; - CME_PUTSCOM(PPM_SSHSRC, deeper_core, scom_data.value); - - // from now on, proceed with only deeper core - core = deeper_core; - target_level = deeper_level; - deeper_level = 0; - deeper_core = 0; - entry_ongoing = 1; - } + // from now on, proceed with only deeper core + core = deeper_core; + target_level = deeper_level; + deeper_level = 0; + deeper_core = 0; + entry_ongoing = 1; + } - // If we are done at STOP level 4 - if (!entry_ongoing) - { - break; - } + // If we are done at STOP level 4 + if (!entry_ongoing) + { + break; + } - //=========================== - MARK_TRAP(SE_IS1_BEGIN) - //=========================== + //=========================== + MARK_TRAP(SE_IS1_BEGIN) + //=========================== #if !SKIP_ABORT - out32(CME_LCL_EIMR_CLR, (core << SHIFT32(13)) | - (core << SHIFT32(15)) | - (core << SHIFT32(17))); - sync(); - out32(CME_LCL_EIMR_OR, (BITS32(12, 6) | BITS32(20, 2))); + out32(CME_LCL_EIMR_CLR, (core << SHIFT32(13)) | + (core << SHIFT32(15)) | + (core << SHIFT32(17))); + sync(); + out32(CME_LCL_EIMR_OR, (BITS32(12, 6) | BITS32(20, 2))); #endif - //=================== - MARK_TRAP(SE_IS1_END) - //=================== - - core_aborted = core & G_cme_stop_record.core_running; - core = core & ~G_cme_stop_record.core_running; + //=================== + MARK_TRAP(SE_IS1_END) + //=================== - PK_TRACE_DBG("Abort: core[%d] running[%d] core_aborted[%d]", - core, G_cme_stop_record.core_running, core_aborted); + core_aborted = core & G_cme_stop_record.core_running; + core = core & ~G_cme_stop_record.core_running; - if (!core) - { - core |= core_aborted; - entry_ongoing = 0; - break; - } + PK_TRACE_DBG("Abort: core[%d] running[%d] core_aborted[%d]", + core, G_cme_stop_record.core_running, core_aborted); - if (core_aborted && deeper_core) - { - if (core_aborted != deeper_core) + if (!core) { - target_level = deeper_level; + core |= core_aborted; + entry_ongoing = 0; + break; } - deeper_core = 0; - } + if (core_aborted && deeper_core) + { + if (core_aborted != deeper_core) + { + target_level = deeper_level; + } - PK_TRACE_DBG("Check: core[%d] deeper_core[%d] target_level[%d] deeper_level[%d]", - core, deeper_core, target_level, deeper_level); + deeper_core = 0; + } + + PK_TRACE_DBG("Check: core[%d] deeper_core[%d] target_level[%d] deeper_level[%d]", + core, deeper_core, target_level, deeper_level); - //---------------------------------------------------------------------- - PK_TRACE("+++++ +++++ STOP LEVEL 5-7 ENTRY +++++ +++++"); - //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + PK_TRACE("+++++ +++++ STOP LEVEL 5-7 ENTRY +++++ +++++"); + //---------------------------------------------------------------------- // NDD1 workaround to save cme image size #if NIMBUS_DD_LEVEL != 1 - if ((G_cme_stop_record.req_level[0] >= STOP_LEVEL_8) && - (G_cme_stop_record.req_level[1] >= STOP_LEVEL_8)) - { + if ((G_cme_stop_record.req_level[0] >= STOP_LEVEL_8) && + (G_cme_stop_record.req_level[1] >= STOP_LEVEL_8)) + { - //================================ - MARK_TAG(SE_PURGE_L2, CME_MASK_BC) - //================================ + //================================ + MARK_TAG(SE_PURGE_L2, CME_MASK_BC) + //================================ - PK_TRACE("Assert L2+NCU purge and NCU tlbie quiesce via SICR[18,21,22]"); - // insert tlbie quiesce before ncu purge to avoid window condition - // of ncu traffic still happening when purging starts - // Note: chtm purge and drop tlbie quiesce will be done in SGPE - out32(CME_LCL_SICR_OR, BIT32(18) | BIT32(21)); - out32(CME_LCL_SICR_OR, BIT32(22)); + PK_TRACE("Assert L2+NCU purge and NCU tlbie quiesce via SICR[18,21,22]"); + // insert tlbie quiesce before ncu purge to avoid window condition + // of ncu traffic still happening when purging starts + // Note: chtm purge and drop tlbie quiesce will be done in SGPE + out32(CME_LCL_SICR_OR, BIT32(18) | BIT32(21)); + out32(CME_LCL_SICR_OR, BIT32(22)); - PK_TRACE("Poll for purged done via EISR[22,23]"); + PK_TRACE("Poll for purged done via EISR[22,23]"); - do - { + do + { #if !SKIP_L2_PURGE_ABORT - if (!core_aborted && - (in32(CME_LCL_EINR) & BITS32(12, 6))) - { - if (in32(CME_LCL_EINR) & - (((core & CME_MASK_C0) ? BIT32(12) : 0) | BIT32(14) | BIT32(16))) + if (!core_aborted && + (in32(CME_LCL_EINR) & BITS32(12, 6))) { - core_aborted |= CME_MASK_C0; - } + if (in32(CME_LCL_EINR) & + (((core & CME_MASK_C0) ? BIT32(12) : 0) | BIT32(14) | BIT32(16))) + { + core_aborted |= CME_MASK_C0; + } - if (in32(CME_LCL_EINR) & - (((core & CME_MASK_C1) ? BIT32(13) : 0) | BIT32(15) | BIT32(17))) - { - core_aborted |= CME_MASK_C1; - } + if (in32(CME_LCL_EINR) & + (((core & CME_MASK_C1) ? BIT32(13) : 0) | BIT32(15) | BIT32(17))) + { + core_aborted |= CME_MASK_C1; + } - if (core_aborted) - { - //======================================= - MARK_TAG(SE_PURGE_L2_ABORT, core_aborted) - //======================================= + if (core_aborted) + { + //======================================= + MARK_TAG(SE_PURGE_L2_ABORT, core_aborted) + //======================================= - PK_TRACE_INF("Abort: L2+NCU purge aborted by core[%d]", core_aborted); - out32(CME_LCL_SICR_OR, BIT32(19) | BIT32(23)); + PK_TRACE_INF("Abort: L2+NCU purge aborted by core[%d]", core_aborted); + out32(CME_LCL_SICR_OR, BIT32(19) | BIT32(23)); + } } - } #endif + } + while((in32(CME_LCL_EISR) & BITS32(22, 2)) != BITS32(22, 2)); + + PK_TRACE("Drop L2+NCU purges and their possible aborts via SICR[18,19,22,23]"); + out32(CME_LCL_SICR_CLR, (BITS32(18, 2) | BITS32(22, 2))); + + PK_TRACE_INF("SE.5A: L2 and NCU Purged"); + + //=================================================================== + MARK_TAG(SE_PURGE_L2_DONE, core_aborted ? core_aborted : CME_MASK_BC) + //=================================================================== + + // 1) if core = 3 aborted = 1, core = 2(sgpe handoff) aborted (cme wakeup) + // 2) if core = 1 aborted = 1, core = 0(break) aborted (cme wakeup) + // 3) if core = 2 aborted = 3, core = 0(break) aborted (cme/sgpe wakeup) + // 4) if core = 1 aborted = 2, core = 1(sgpe handoff) aborted (sgpe wakeup) + // for case 3) and 4) on the other core already handoff to sgpe + // if rgwu or spwu, fine because it will be sgpe wakeup + // if pc, there wont be sgpe wakeup due to notify bug, + // so ignore this case for abortion. otherwise, + // for case 3) core is waking up by tag along with another core + // but leave stop8 record at sgpe + // for case 4) l2 is not purged and sgpe will do stop8 + if (core != (core_aborted & core)) + { + core &= ~core_aborted; + } + else + { + break; + } } - while((in32(CME_LCL_EISR) & BITS32(22, 2)) != BITS32(22, 2)); - - PK_TRACE("Drop L2+NCU purges and their possible aborts via SICR[18,19,22,23]"); - out32(CME_LCL_SICR_CLR, (BITS32(18, 2) | BITS32(22, 2))); - - PK_TRACE_INF("SE.5A: L2 and NCU Purged"); - - //=================================================================== - MARK_TAG(SE_PURGE_L2_DONE, core_aborted ? core_aborted : CME_MASK_BC) - //=================================================================== - - // 1) if core = 3 aborted = 1, core = 2(sgpe handoff) aborted (cme wakeup) - // 2) if core = 1 aborted = 1, core = 0(break) aborted (cme wakeup) - // 3) if core = 2 aborted = 3, core = 0(break) aborted (cme/sgpe wakeup) - // 4) if core = 1 aborted = 2, core = 1(sgpe handoff) aborted (sgpe wakeup) - // for case 3) and 4) on the other core already handoff to sgpe - // if rgwu or spwu, fine because it will be sgpe wakeup - // if pc, there wont be sgpe wakeup due to notify bug, - // so ignore this case for abortion. otherwise, - // for case 3) core is waking up by tag along with another core - // but leave stop8 record at sgpe - // for case 4) l2 is not purged and sgpe will do stop8 - if (core != (core_aborted & core)) - { - core &= ~core_aborted; - } - else - { - break; - } - } #endif - //============================= - MARK_TAG(SE_SGPE_HANDOFF, core) - //============================= + //============================= + MARK_TAG(SE_SGPE_HANDOFF, core) + //============================= - PK_TRACE("Update STOP history: in core stop level 5"); - scom_data.words.lower = 0; - scom_data.words.upper = SSH_ACT_LV5_COMPLETE; - CME_PUTSCOM(PPM_SSHSRC, core, scom_data.value); + PK_TRACE("Update STOP history: in core stop level 5"); + scom_data.words.lower = 0; + scom_data.words.upper = SSH_ACT_LV5_COMPLETE; + CME_PUTSCOM(PPM_SSHSRC, core, scom_data.value); #if DEBUG_RUNTIME_STATE_CHECK - if (core & CME_MASK_C0) - { - CME_GETSCOM(CPPM_CPMMR, CME_MASK_C0, CME_SCOM_AND, scom_data.value); - - if ((scom_data.words.upper & BIT32(13))) + if (core & CME_MASK_C0) { - PKTRACE("ERROR.A0: C0 notify was already set?"); - pk_halt(); + CME_GETSCOM(CPPM_CPMMR, CME_MASK_C0, CME_SCOM_AND, scom_data.value); - } - } + if ((scom_data.words.upper & BIT32(13))) + { + PKTRACE("ERROR.A0: C0 notify was already set?"); + pk_halt(); - if (core & CME_MASK_C1) - { - CME_GETSCOM(CPPM_CPMMR, CME_MASK_C1, CME_SCOM_AND, scom_data.value); + } + } - if ((scom_data.words.upper & BIT32(13))) + if (core & CME_MASK_C1) { - PKTRACE("ERROR.A1: C1 notify was already set?"); - pk_halt(); + CME_GETSCOM(CPPM_CPMMR, CME_MASK_C1, CME_SCOM_AND, scom_data.value); + + if ((scom_data.words.upper & BIT32(13))) + { + PKTRACE("ERROR.A1: C1 notify was already set?"); + pk_halt(); + } } - } #endif - PK_TRACE("Send PCB interrupt per core via PIG, select irq type via CPMMR[10]"); + PK_TRACE("Send PCB interrupt per core via PIG, select irq type via CPMMR[10]"); - for (core_mask = 2; core_mask; core_mask--) - { - if (core & core_mask) + for (core_mask = 2; core_mask; core_mask--) { - core_index = core_mask & 1; - - if (G_cme_stop_record.req_level[core_index] >= STOP_LEVEL_8) + if (core & core_mask) { - CME_PUTSCOM(CPPM_CPMMR_OR, core_mask, BIT64(10)); - pig.fields.req_intr_type = PIG_TYPE3; - G_cme_stop_record.core_blockpc |= core; - } - else - { - CME_PUTSCOM(CPPM_CPMMR_CLR, core_mask, BIT64(10)); - pig.fields.req_intr_type = PIG_TYPE2; - G_cme_stop_record.core_blockpc &= ~core; - } + core_index = core_mask & 1; - pig.fields.req_intr_payload = G_cme_stop_record.req_level[core_index]; - CME_PUTSCOM(PPM_PIG, core_mask, pig.value); - G_cme_stop_record.core_stopgpe |= core; - G_cme_stop_record.act_level[core_index] = STOP_LEVEL_5; + if (G_cme_stop_record.req_level[core_index] >= STOP_LEVEL_8) + { + CME_PUTSCOM(CPPM_CPMMR_OR, core_mask, BIT64(10)); + pig.fields.req_intr_type = PIG_TYPE3; + G_cme_stop_record.core_blockpc |= core; + } + else + { + CME_PUTSCOM(CPPM_CPMMR_CLR, core_mask, BIT64(10)); + pig.fields.req_intr_type = PIG_TYPE2; + G_cme_stop_record.core_blockpc &= ~core; + } + + pig.fields.req_intr_payload = G_cme_stop_record.req_level[core_index]; + CME_PUTSCOM(PPM_PIG, core_mask, pig.value); + G_cme_stop_record.core_stopgpe |= core; + G_cme_stop_record.act_level[core_index] = STOP_LEVEL_5; + } } - } #if NIMBUS_DD_LEVEL != 1 - PK_TRACE("Drop PPM_WRITE_DISABLE via CPMMR[0]"); - CME_PUTSCOM(CPPM_CPMMR_CLR, core, BIT64(0)); + PK_TRACE("Drop PPM_WRITE_DISABLE via CPMMR[0]"); + CME_PUTSCOM(CPPM_CPMMR_CLR, core, BIT64(0)); #endif - PK_TRACE_DBG("Switch Core PPM wakeup to STOP-GPE via CPMMR[13]"); - CME_PUTSCOM(CPPM_CPMMR_OR, core, BIT64(13)); + PK_TRACE_DBG("Switch Core PPM wakeup to STOP-GPE via CPMMR[13]"); + CME_PUTSCOM(CPPM_CPMMR_OR, core, BIT64(13)); #if DEBUG_RUNTIME_STATE_CHECK - if (core & CME_MASK_C0) - { - CME_GETSCOM(CPPM_CPMMR, CME_MASK_C0, CME_SCOM_AND, scom_data.value); - - if (!(scom_data.words.upper & BIT32(13))) + if (core & CME_MASK_C0) { - PKTRACE("ERROR.B0: C0 notify fail to set"); - pk_halt(); + CME_GETSCOM(CPPM_CPMMR, CME_MASK_C0, CME_SCOM_AND, scom_data.value); - } - } + if (!(scom_data.words.upper & BIT32(13))) + { + PKTRACE("ERROR.B0: C0 notify fail to set"); + pk_halt(); - if (core & CME_MASK_C1) - { - CME_GETSCOM(CPPM_CPMMR, CME_MASK_C1, CME_SCOM_AND, scom_data.value); + } + } - if (!(scom_data.words.upper & BIT32(13))) + if (core & CME_MASK_C1) { - PKTRACE("ERROR.B1: C1 notify fail to set"); - pk_halt(); + CME_GETSCOM(CPPM_CPMMR, CME_MASK_C1, CME_SCOM_AND, scom_data.value); + + if (!(scom_data.words.upper & BIT32(13))) + { + PKTRACE("ERROR.B1: C1 notify fail to set"); + pk_halt(); + } } - } #endif - PK_TRACE("Clear special wakeup after wakeup_notify = 1 since it is edge triggered"); - out32(CME_LCL_EISR_CLR, core << SHIFT32(15)); + PK_TRACE("Clear special wakeup after wakeup_notify = 1 since it is edge triggered"); + out32(CME_LCL_EISR_CLR, core << SHIFT32(15)); + + PK_TRACE_INF("SE.5B: Core[%d] Handed off to SGPE", core); - PK_TRACE_INF("SE.5B: Core[%d] Handed off to SGPE", core); + } + while(0); + + //-------------------------------------------------------------------------- + PK_TRACE("+++++ +++++ END OF STOP ENTRY +++++ +++++"); + //-------------------------------------------------------------------------- + +#if NIMBUS_DD_LEVEL == 2 || DISABLE_CME_DUAL_CAST == 1 + // NDD2: dual cast workaround loop end } - while(0); - //-------------------------------------------------------------------------- - PK_TRACE("+++++ +++++ END OF STOP ENTRY +++++ +++++"); - //-------------------------------------------------------------------------- +#endif //============================ MARK_TRAP(ENDSCOPE_STOP_ENTRY) |

