summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Vanderpool <vanderp@us.ibm.com>2017-09-21 15:09:51 -0500
committerJoshua Hunsberger <jahunsbe@us.ibm.com>2017-10-23 19:26:45 -0500
commitc1cbb9dc91c5560edb3db0619dc4f8baf85d6c1d (patch)
treec13c38a54494ca999d17d6f4fb8355b2c574747c
parentc517053d357a87f80ba8912cf8162d914309ab29 (diff)
downloadtalos-hcode-c1cbb9dc91c5560edb3db0619dc4f8baf85d6c1d.tar.gz
talos-hcode-c1cbb9dc91c5560edb3db0619dc4f8baf85d6c1d.zip
STOP: Core livelock buster - the sequel
Stop instructions on any cores that are running. The previous patch only activated if both cores were active Change-Id: Ibc89794eaf00242c932f307a9189ca376a9b2fba Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/46587 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Juan R. Medina <jrmedina@us.ibm.com> Reviewed-by: YUE DU <daviddu@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/p9_cme_iota_main.c199
1 files changed, 105 insertions, 94 deletions
diff --git a/import/chips/p9/procedures/ppe_closed/cme/p9_cme_iota_main.c b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_iota_main.c
index 41db59f7..46140b58 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/p9_cme_iota_main.c
+++ b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_iota_main.c
@@ -62,7 +62,7 @@ CmeStopRecord G_cme_stop_record __attribute__((section (".dump_ptr_stop"))) = {{
#if !DISABLE_PERIODIC_CORE_QUIESCE && (NIMBUS_DD_LEVEL == 20 || NIMBUS_DD_LEVEL == 21 || CUMULUS_DD_LEVEL == 10)
inline static
-void periodic_core_quiesce_workaround()
+void periodic_core_quiesce_workaround(uint32_t core_instruction_running)
{
uint32_t core;
uint32_t core_accessible;
@@ -85,20 +85,20 @@ void periodic_core_quiesce_workaround()
//0) in case in stop0/1 that we dont know about
PK_TRACE("PCQW: Assert block interrupt to PC via SICR[2/3]");
- out32(CME_LCL_SICR_OR, CME_MASK_BC << SHIFT32(3));
+ out32(CME_LCL_SICR_OR, core_instruction_running << SHIFT32(3));
PK_TRACE("PCQW: Waking up the core(pm_exit=1) via SICR[4/5]");
- out32(CME_LCL_SICR_OR, CME_MASK_BC << SHIFT32(5));
+ out32(CME_LCL_SICR_OR, core_instruction_running << SHIFT32(5));
CME_PM_EXIT_DELAY
PK_TRACE("PCQW: Polling for core wakeup(pm_active=0) via EINR[20/21]");
- while((in32(CME_LCL_EINR)) & (CME_MASK_BC << SHIFT32(21)));
+ while((in32(CME_LCL_EINR)) & (core_instruction_running << SHIFT32(21)));
//1) Acquire Pcb Mux
- core_accessible = ((~in32(CME_LCL_SISR)) >> SHIFT32(11)) & CME_MASK_BC;
+ core_accessible = ((~in32(CME_LCL_SISR)) >> SHIFT32(11)) & core_instruction_running;
PK_TRACE("PCQW: Request PCB Mux via SICR[10/11]");
out32(CME_LCL_SICR_OR, core_accessible << SHIFT32(11));
@@ -117,8 +117,11 @@ void periodic_core_quiesce_workaround()
for(core = CME_MASK_C0; core > 0; core--)
{
- CME_GETSCOM(RAS_STATUS, core, scom_data.value) ;
- maint_mode[core & 1] = scom_data.words.upper & THREAD_VECTOR;
+ if (core & core_instruction_running)
+ {
+ CME_GETSCOM(RAS_STATUS, core, scom_data.value) ;
+ maint_mode[core & 1] = scom_data.words.upper & THREAD_VECTOR;
+ }
}
@@ -135,29 +138,30 @@ void periodic_core_quiesce_workaround()
for(core = CME_MASK_C0; core > 0; core--)
{
-
+ if (core & core_instruction_running)
+ {
#else
- core = CME_MASK_BC;
+ core = core_instruction_running;
#endif
- // The SCOM can be delayed by traffic on PC on the SPR bus, so it is possible
- // to get a RC=4 (Address Error), which really indicates a timeout. Need to mask
- // this return code and retry until we get a clean return code
- saved_msr = mfmsr();
- mtmsr( saved_msr | MSR_SEM4); // Mask off timeout
+ // The SCOM can be delayed by traffic on PC on the SPR bus, so it is possible
+ // to get a RC=4 (Address Error), which really indicates a timeout. Need to mask
+ // this return code and retry until we get a clean return code
+ saved_msr = mfmsr();
+ mtmsr( saved_msr | MSR_SEM4); // Mask off timeout
- do
- {
- CME_PUTSCOM_NOP(DIRECT_CONTROLS, core, scom_data.value);
- }
- while ((mfmsr() & MSR_SIBRC) != 0);
+ do
+ {
+ CME_PUTSCOM_NOP(DIRECT_CONTROLS, core, scom_data.value);
+ }
+ while ((mfmsr() & MSR_SIBRC) != 0);
- mtmsr(saved_msr);
+ mtmsr(saved_msr);
#if NIMBUS_DD_LEVEL == 20 || DISABLE_CME_DUAL_CAST == 1
-
+ }
}
#endif
@@ -172,10 +176,11 @@ void periodic_core_quiesce_workaround()
for(core = CME_MASK_C0; core > 0; core--)
{
-
+ if (core & core_instruction_running)
+ {
#else
- core = CME_MASK_BC;
+ core = core_instruction_running;
#endif
@@ -186,35 +191,35 @@ void periodic_core_quiesce_workaround()
// 200us in 32ns timer ticks
#define QUIESCE_ABORT_TICKS 0x186A
- // Poll on THREAD_QUIESCE, LSU_QUIESCE, and NEST_ACTIVE.
- // If they do not quiesce in 200us abort the patch and restart the cores.
-
- do
- {
- CME_GETSCOM_AND(RAS_STATUS, core, scom_data.value);
-
- time_stamp[1] = in32(CME_LCL_TBR);
+ // Poll on THREAD_QUIESCE, LSU_QUIESCE, and NEST_ACTIVE.
+ // If they do not quiesce in 200us abort the patch and restart the cores.
- if (time_stamp[1] > time_stamp[0])
+ do
{
- G_cme_record.fit_record.core_quiesce_time_latest =
- time_stamp[1] - time_stamp[0];
+ CME_GETSCOM_AND(RAS_STATUS, core, scom_data.value);
+
+ time_stamp[1] = in32(CME_LCL_TBR);
+
+ if (time_stamp[1] > time_stamp[0])
+ {
+ G_cme_record.fit_record.core_quiesce_time_latest =
+ time_stamp[1] - time_stamp[0];
+ }
+ else
+ {
+ G_cme_record.fit_record.core_quiesce_time_latest =
+ 0xFFFFFFFF - time_stamp[0] + time_stamp[1] + 1;
+ }
}
- else
- {
- G_cme_record.fit_record.core_quiesce_time_latest =
- 0xFFFFFFFF - time_stamp[0] + time_stamp[1] + 1;
- }
- }
- while((((scom_data.words.upper& THREAD_VECTOR_CHECK) != THREAD_VECTOR_CHECK)
- || //THREAD_ and LSU_QUIESCE must be ones
- ((scom_data.words.lower& BIT64SH(32)))) // NEST_ACTIVE must be zero
- && !(sample_error = bad_error_present)
- && (G_cme_record.fit_record.core_quiesce_time_latest < QUIESCE_ABORT_TICKS) // 200us in 32ns timer ticks
- );
+ while((((scom_data.words.upper& THREAD_VECTOR_CHECK) != THREAD_VECTOR_CHECK)
+ || //THREAD_ and LSU_QUIESCE must be ones
+ ((scom_data.words.lower& BIT64SH(32)))) // NEST_ACTIVE must be zero
+ && !(sample_error = bad_error_present)
+ && (G_cme_record.fit_record.core_quiesce_time_latest < QUIESCE_ABORT_TICKS) // 200us in 32ns timer ticks
+ );
#if NIMBUS_DD_LEVEL == 20 || DISABLE_CME_DUAL_CAST == 1
-
+ }
}
#endif
@@ -233,53 +238,54 @@ void periodic_core_quiesce_workaround()
for(core = CME_MASK_C0; core > 0; core--)
{
-
- //5) Read SPATTN Scom Addr(20:31) = x0A98 to check for ATTN
- // (need to do this after all threads quiesce to close windows)
-
- CME_GETSCOM(SPATTN_READ, core, scom_data.value);
-
- if (fused_core_mode)
+ if (core & core_instruction_running)
{
- //Fused Core Mode
- // C0 vtid0=ltid0 bit1 -> tv.bit0
- // C0 vtid1=ltid2 bit9 -> tv.bit8
- // C0 vtid2=ltid4 bit17 -> tv.bit16
- // C0 vtid3=ltid6 bit25 -> tv.bit24
- //
- // C1 vtid0=ltid1 bit5 -> tv.bit0
- // C1 vtid1=ltid3 bit13 -> tv.bit8
- // C1 vtid2=ltid5 bit21 -> tv.bit16
- // C1 vtid3=ltid7 bit29 -> tv.bit24
- spattn_offset = ((core & 1) << 2) + 1; // C0:1, C1:5
- spattn[core & 1] = ((scom_data.words.upper & BIT32((0 + spattn_offset))) << spattn_offset) | //0
- ((scom_data.words.upper & BIT32((8 + spattn_offset))) << spattn_offset) | //8
- ((scom_data.words.upper & BIT32((16 + spattn_offset))) << spattn_offset) | //16
- ((scom_data.words.upper & BIT32((24 + spattn_offset))) << spattn_offset); //24
- }
- else
- {
- // Normal Mode
- // vtid0=ltid0 bit1 -> tv.bit0
- // vtid1=ltid1 bit5 -> tv.bit8
- // vtid2=ltid2 bit9 -> tv.bit16
- // vtid3=ltid3 bit13 -> tv.bit24
- spattn[core & 1] = ((scom_data.words.upper & BIT32(1)) << 1 ) | //0
- ((scom_data.words.upper & BIT32(5)) >> 3 ) | //8
- ((scom_data.words.upper & BIT32(9)) >> 7 ) | //16
- ((scom_data.words.upper & BIT32(13)) >> 11); //24
- }
+ //5) Read SPATTN Scom Addr(20:31) = x0A98 to check for ATTN
+ // (need to do this after all threads quiesce to close windows)
+ CME_GETSCOM(SPATTN_READ, core, scom_data.value);
+
+ if (fused_core_mode)
+ {
+ //Fused Core Mode
+ // C0 vtid0=ltid0 bit1 -> tv.bit0
+ // C0 vtid1=ltid2 bit9 -> tv.bit8
+ // C0 vtid2=ltid4 bit17 -> tv.bit16
+ // C0 vtid3=ltid6 bit25 -> tv.bit24
+ //
+ // C1 vtid0=ltid1 bit5 -> tv.bit0
+ // C1 vtid1=ltid3 bit13 -> tv.bit8
+ // C1 vtid2=ltid5 bit21 -> tv.bit16
+ // C1 vtid3=ltid7 bit29 -> tv.bit24
+ spattn_offset = ((core & 1) << 2) + 1; // C0:1, C1:5
+ spattn[core & 1] = ((scom_data.words.upper & BIT32((0 + spattn_offset))) << spattn_offset) | //0
+ ((scom_data.words.upper & BIT32((8 + spattn_offset))) << spattn_offset) | //8
+ ((scom_data.words.upper & BIT32((16 + spattn_offset))) << spattn_offset) | //16
+ ((scom_data.words.upper & BIT32((24 + spattn_offset))) << spattn_offset); //24
+ }
+ else
+ {
+ // Normal Mode
+ // vtid0=ltid0 bit1 -> tv.bit0
+ // vtid1=ltid1 bit5 -> tv.bit8
+ // vtid2=ltid2 bit9 -> tv.bit16
+ // vtid3=ltid3 bit13 -> tv.bit24
+ spattn[core & 1] = ((scom_data.words.upper & BIT32(1)) << 1 ) | //0
+ ((scom_data.words.upper & BIT32(5)) >> 3 ) | //8
+ ((scom_data.words.upper & BIT32(9)) >> 7 ) | //16
+ ((scom_data.words.upper & BIT32(13)) >> 11); //24
+ }
- //6) Write DIRECT_CONTROLS Scom Addr(20:31) = x0A9C
- // bit (3 + 8*T) where (T= thread) DC_CLEAR_MAINT for all threads
- // which were not in maintenance mode in step 1 AND do not have ATTN set in step 4
- scom_data.words.lower = 0;
- scom_data.words.upper =
- (THREAD_VECTOR & (~maint_mode[core & 1]) & (~spattn[core & 1])) >> 3;
- CME_PUTSCOM_NOP(DIRECT_CONTROLS, core, scom_data.value);
+ //6) Write DIRECT_CONTROLS Scom Addr(20:31) = x0A9C
+ // bit (3 + 8*T) where (T= thread) DC_CLEAR_MAINT for all threads
+ // which were not in maintenance mode in step 1 AND do not have ATTN set in step 4
+ scom_data.words.lower = 0;
+ scom_data.words.upper =
+ (THREAD_VECTOR & (~maint_mode[core & 1]) & (~spattn[core & 1])) >> 3;
+ CME_PUTSCOM_NOP(DIRECT_CONTROLS, core, scom_data.value);
+ }
}
PK_TRACE("FIT: Both Cores Started");
@@ -287,10 +293,10 @@ void periodic_core_quiesce_workaround()
//7) Drop pm_exit
PK_TRACE("PCQW: Drop pm_exit via SICR[4/5]");
- out32(CME_LCL_SICR_CLR, CME_MASK_BC << SHIFT32(5));
+ out32(CME_LCL_SICR_CLR, core_instruction_running << SHIFT32(5));
PK_TRACE("PCQW: Drop block interrupt to PC via SICR[2/3]");
- out32(CME_LCL_SICR_CLR, CME_MASK_BC << SHIFT32(3));
+ out32(CME_LCL_SICR_CLR, core_instruction_running << SHIFT32(3));
//8) Release Pcb Mux on Both Cores
@@ -333,6 +339,7 @@ void fit_handler()
uint32_t core_quiesce_cpmmr_disable;
uint32_t core;
+ uint32_t core_instr_running;
uint32_t scom_op;
data64_t scom_data;
@@ -372,14 +379,18 @@ void fit_handler()
// only run workaround if
// 1) both cores are enabled
- // 2) both cores are running
+ // 2) at least one core is running
// (stop entry clears the counter)
// 3) both cores doesnt have special_wakeup_done asserted
// (spwu_done clears the counter)
// 4) both core doesnt have cpmmr[2] asserted
// 5) no bad error occurs
+
+ // Get instruction running per core
+ core_instr_running = (in32_sh(CME_LCL_SISR) >> SHIFT64SH(47))& CME_MASK_BC;
+
if((G_cme_record.core_enabled == CME_MASK_BC) &&
- ((in32_sh(CME_LCL_SISR) & BITS64SH(46, 2)) == BITS64SH(46, 2)) &&
+ (core_instr_running != 0) &&
(!(in32(CME_LCL_SISR) & BITS32(16, 2))) &&
(!core_quiesce_cpmmr_disable) &&
(!bad_error_present))
@@ -391,7 +402,7 @@ void fit_handler()
else
{
G_cme_record.fit_record.core_quiesce_fit_trigger = 0;
- periodic_core_quiesce_workaround();
+ periodic_core_quiesce_workaround(core_instr_running);
}
}
OpenPOWER on IntegriCloud