From f3d82eaa4d8c8181bb2f13b47f6ae67c1e553c1d Mon Sep 17 00:00:00 2001 From: Yue Du Date: Wed, 29 Aug 2018 22:24:08 -0500 Subject: Self Save: Added support for SPR self save in CME hcode(func ver) Key_Cronus_Test=PM_REGRESS Change-Id: I890e2f8ee2fc50214ad84a37ff8098807fe6cd60 CQ: SW454956 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/65480 Tested-by: Jenkins Server Tested-by: FSP CI Jenkins Tested-by: Cronus HW CI Dev-Ready: Gregory S. Still Reviewed-by: Gregory S. Still Reviewed-by: YUE DU Reviewed-by: Jennifer A. Stofer --- .../ppe_closed/cme/stop_cme/p9_cme_stop_exit.c | 395 +++++++++++---------- 1 file changed, 216 insertions(+), 179 deletions(-) (limited to 'import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_exit.c') diff --git a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_exit.c b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_exit.c index 9fbac710..b83624ec 100644 --- a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_exit.c +++ b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_exit.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HCODE Project */ /* */ -/* COPYRIGHT 2015,2018 */ +/* COPYRIGHT 2015,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -46,6 +46,7 @@ extern CmeStopRecord G_cme_stop_record; extern CmeRecord G_cme_record; +uint64_t G_spattn_mask = 0; #if HW386841_NDD1_DSL_STOP1_FIX @@ -511,7 +512,6 @@ p9_cme_stop_exit() uint32_t core = 0; uint32_t core_mask = 0; uint32_t core_spattn = 0; - uint64_t spattn_mask = 0; data64_t scom_data = {0}; #if !SPWU_AUTO uint32_t spwu_stop = 0; @@ -1052,271 +1052,308 @@ p9_cme_stop_exit() #if !SKIP_SELF_RESTORE - PK_TRACE("Assert block interrupt to PC via SICR[2/3]"); - out32(G_CME_LCL_SICR_OR, core << SHIFT32(3)); + p9_cme_stop_self_execute(core, SPR_SELF_RESTORE); - PK_TRACE_PERF("SF.RS: Self Restore Prepare, Core Waking up(pm_exit=1) via SICR[4/5]"); - out32(G_CME_LCL_SICR_OR, core << SHIFT32(5)); - - CME_PM_EXIT_DELAY - - PK_TRACE("Polling for core wakeup(pm_active=0) via EINR[20/21]"); + //========================== + MARK_TRAP(SX_SRESET_THREADS) + //========================== - while((in32(G_CME_LCL_EINR)) & (core << SHIFT32(21))); + PK_TRACE("Poll for core stop again(pm_active=1)"); - scom_data.value = pCmeImgHdr->g_cme_cpmr_PhyAddr & BITS64(13, 30); //HRMOR[13:42] + while((~(in32(G_CME_LCL_EINR))) & (core << SHIFT32(21))) + { + core_spattn = (in32_sh(CME_LCL_SISR) >> SHIFT64SH(33)) & core; -#if NIMBUS_DD_LEVEL == 10 -#if !SKIP_RAM_HRMOR + if (core_spattn) + { + PK_TRACE_ERR("ERROR: Core[%d] Special Attention Detected. Gard Core!", core_spattn); + CME_STOP_CORE_ERROR_HANDLER(core, core_spattn, CME_STOP_EXIT_SELF_RES_SPATTN); - PK_TRACE("Activate thread0 for RAM via THREAD_INFO[18]"); - CME_PUTSCOM(THREAD_INFO, core, BIT64(18)); + PK_TRACE("Release PCB Mux back on Core via SICR[10/11]"); + out32(G_CME_LCL_SICR_CLR, core_spattn << SHIFT32(11)); - PK_TRACE("Enable RAM mode via RAM_MODEREG[0]"); - CME_PUTSCOM(RAM_MODEREG, core, BIT64(0)); + while((core_spattn & ~(in32(G_CME_LCL_SISR) >> SHIFT32(11))) != core_spattn); - PK_TRACE("Set SPR mode to LT0-7 via SPR_MODE[20-27]"); - CME_PUTSCOM(SPR_MODE, core, BITS64(20, 8)); + PK_TRACE("PCB Mux Released on Core[%d]", core_spattn); + } - for (core_mask = 2; core_mask; core_mask--) - { - if (core & core_mask) + if (!core) { - PK_TRACE_DBG("Set SPRC to scratch for core[%d] via SCOM_SPRC", core_mask); - CME_PUTSCOM(SCOM_SPRC, core_mask, ((core_mask & 1) ? BIT64(60) : 0)); - PK_TRACE_DBG("Load SCRATCH0 with HOMER+2MB address %x", scom_data.value); - -#if EPM_P9_TUNING +#if NIMBUS_DD_LEVEL == 20 || DISABLE_CME_DUAL_CAST == 1 - CME_PUTSCOM((SCRATCH0 + (core_mask & 1)), core_mask, 0xA200000); + continue; #else - CME_PUTSCOM((SCRATCH0 + (core_mask & 1)), core_mask, scom_data.value); + if (d2u4_flag) + { + p9_cme_stop_exit_end((CME_MASK_BC - deeper_core), spwu_stop); + } + + return; #endif + } } - PK_TRACE("RAM: mfspr sprd , gpr0 via RAM_CTRL"); - CME_PUTSCOM(RAM_CTRL, core, RAM_MFSPR_SPRD_GPR0); - - PK_TRACE("RAM: mtspr hrmor, gpr0 via RAM_CTRL"); - CME_PUTSCOM(RAM_CTRL, core, RAM_MTSPR_HRMOR_GPR0); - - PK_TRACE("Disable thread0 for RAM via THREAD_INFO"); - CME_PUTSCOM(THREAD_INFO, core, 0); + PK_TRACE_PERF("SF.RS: Self Restore Completed, Core Stopped Again(pm_exit=0/pm_active=1)"); - PK_TRACE("Disable RAM mode via RAM_MODEREG"); - CME_PUTSCOM(RAM_MODEREG, core, 0); + p9_cme_stop_self_cleanup(core); - PK_TRACE("Clear scratch/spr used in RAM"); - CME_PUTSCOM(SPR_MODE, core, 0); - CME_PUTSCOM(SCOM_SPRC, core, 0); +#endif - if (core & CME_MASK_C0) + if (d2u4_flag) { - CME_PUTSCOM(SCRATCH0, CME_MASK_C0, 0); + core = CME_MASK_BC; } + } - if (core & CME_MASK_C1) - { - CME_PUTSCOM(SCRATCH1, CME_MASK_C1, 0); - } + p9_cme_stop_exit_end(core, spwu_stop); + +#if NIMBUS_DD_LEVEL == 20 || DISABLE_CME_DUAL_CAST == 1 + + // NDD2: dual cast workaround loop end + } #endif -// Nimbus DD2+ -#else -#if SMF_SUPPORT_ENABLE + //=========================== + MARK_TRAP(ENDSCOPE_STOP_EXIT) + //=========================== -#if EPM_P9_TUNING + return; +} - CME_PUTSCOM(URMOR, core, 0xA200000); +void +p9_cme_stop_self_cleanup(uint32_t core) +{ + data64_t scom_data; -#else + //Cleaning up thread scratch register after self restore. + if( CME_MASK_C0 & core ) + { + CME_PUTSCOM(SCRATCH0, CME_MASK_C0, 0); + } - PK_TRACE_INF("Core Wakes Up, Write URMOR with HOMER address"); - CME_PUTSCOM(URMOR, core, scom_data.value); + if( CME_MASK_C1 & core ) + { + CME_PUTSCOM(SCRATCH1, CME_MASK_C1, 0); + } -#endif + PK_TRACE("Restore SPATTN after self-restore"); + CME_PUTSCOM(SPATTN_MASK, core, G_spattn_mask); -#endif + PK_TRACE("Always Unfreeze IMA (by clearing bit 34) in case the CHTM is enabled to sample it"); + CME_GETSCOM(IMA_EVENT_MASK, core, scom_data.value); + CME_PUTSCOM(IMA_EVENT_MASK, core, scom_data.value & ~BIT64(34)); -#if EPM_P9_TUNING + PK_TRACE("Drop block interrupt to PC via SICR[2/3]"); + out32(G_CME_LCL_SICR_CLR, core << SHIFT32(3)); - CME_PUTSCOM(HRMOR, core, 0xA200000); + PK_TRACE("Clear pm_active status via EISR[20/21]"); + out32(G_CME_LCL_EISR_CLR, core << SHIFT32(21)); -#else +} - PK_TRACE_PERF("Core Wakes Up, Write HRMOR with HOMER address"); - // Must not set bit 15 in HRMOR - scom_data.words.upper = scom_data.words.upper & ~BIT32(15); - CME_PUTSCOM(HRMOR, core, scom_data.value); +void +p9_cme_stop_self_execute(uint32_t core, uint32_t i_saveRestore ) +{ + uint32_t core_mask; + data64_t scom_data; + cmeHeader_t* pCmeImgHdr = (cmeHeader_t*)(CME_SRAM_HEADER_ADDR); + scom_data.value = pCmeImgHdr->g_cme_cpmr_PhyAddr & BITS64(13, 30); //HRMOR[13:42] -#endif + PK_TRACE("Assert block interrupt to PC via SICR[2/3]"); -#endif + out32(G_CME_LCL_SICR_OR, core << SHIFT32(3)); - PK_TRACE("Save off and mask SPATTN before self-restore"); - CME_GETSCOM(SPATTN_MASK, core, spattn_mask); - CME_PUTSCOM(SPATTN_MASK, core, BITS64(0, 64)); + PK_TRACE_PERF("SF.RS: Self Restore Prepare, Core Waking up(pm_exit=1) via SICR[4/5]"); + out32(G_CME_LCL_SICR_OR, core << SHIFT32(5)); -#if !DISABLE_CORE_XSTOP_INJECTION + CME_PM_EXIT_DELAY - PK_TRACE("Read WKUP_ERR_INJECT_MODE via CPMMR[8]"); + PK_TRACE("Polling for core wakeup(pm_active=0) via EINR[20/21]"); - for (core_mask = 2; core_mask; core_mask--) - { - if (core & core_mask) - { - CME_GETSCOM(CPPM_CPMMR, core_mask, scom_data.value); + while((in32(G_CME_LCL_EINR)) & (core << SHIFT32(21))); - if (scom_data.words.upper & BIT32(8)) - { - PK_TRACE_INF("WARNING: Injecting a core[%d] xstop via C_LFIR[11]", core); - CME_PUTSCOM(C_LFIR_OR, core_mask, BIT64(11)); - } - } - } +#if NIMBUS_DD_LEVEL == 10 +#if !SKIP_RAM_HRMOR -#endif + PK_TRACE("Activate thread0 for RAM via THREAD_INFO[18]"); + CME_PUTSCOM(THREAD_INFO, core, BIT64(18)); - for (core_mask = 2; core_mask; core_mask--) - { - if (core & core_mask) - { - CME_GETSCOM(CPPM_CPMMR, core_mask, scom_data.value); + PK_TRACE("Enable RAM mode via RAM_MODEREG[0]"); + CME_PUTSCOM(RAM_MODEREG, core, BIT64(0)); - if (scom_data.words.upper & BIT32(3)) - { - scom_data.value = BIT64(59); - } - else - { - scom_data.value = 0; - } + PK_TRACE("Set SPR mode to LT0-7 via SPR_MODE[20-27]"); + CME_PUTSCOM(SPR_MODE, core, BITS64(20, 8)); - //Writing thread scratch register to - // 1. Init Runtime wakeup mode for core. - // 2. Signal Self Save Restore code for restore operation. - CME_PUTSCOM(SCRATCH0, core_mask, scom_data.value); - CME_PUTSCOM(SCRATCH1, core_mask, scom_data.value); - CME_PUTSCOM(SCRATCH2, core_mask, scom_data.value); - CME_PUTSCOM(SCRATCH3, core_mask, scom_data.value); - } - } + for (core_mask = 2; core_mask; core_mask--) + { + if (core & core_mask) + { + PK_TRACE_DBG("Set SPRC to scratch for core[%d] via SCOM_SPRC", core_mask); + CME_PUTSCOM(SCOM_SPRC, core_mask, ((core_mask & 1) ? BIT64(60) : 0)); - PK_TRACE_PERF("SF.RS: Self Restore Kickoff, S-Reset All Core Threads"); + PK_TRACE_DBG("Load SCRATCH0 with HOMER+2MB address %x", scom_data.value); - // Disable interrupts around the sreset to polling check to not miss the self-restore - wrteei(0); - CME_PUTSCOM(DIRECT_CONTROLS, core, - BIT64(4) | BIT64(12) | BIT64(20) | BIT64(28)); - sync(); +#if EPM_P9_TUNING - PK_TRACE("Poll for instruction running before drop pm_exit"); + CME_PUTSCOM((SCRATCH0 + (core_mask & 1)), core_mask, 0xA200000); - while((~(in32_sh(CME_LCL_SISR))) & (core << SHIFT64SH(47))); +#else + CME_PUTSCOM((SCRATCH0 + (core_mask & 1)), core_mask, scom_data.value); - wrteei(1); +#endif - //========================== - MARK_TRAP(SX_SRESET_THREADS) - //========================== + } + } - PK_TRACE("Allow threads to run(pm_exit=0)"); - out32(G_CME_LCL_SICR_CLR, core << SHIFT32(5)); + PK_TRACE("RAM: mfspr sprd , gpr0 via RAM_CTRL"); + CME_PUTSCOM(RAM_CTRL, core, RAM_MFSPR_SPRD_GPR0); - PK_TRACE("Poll for core stop again(pm_active=1)"); + PK_TRACE("RAM: mtspr hrmor, gpr0 via RAM_CTRL"); + CME_PUTSCOM(RAM_CTRL, core, RAM_MTSPR_HRMOR_GPR0); - while((~(in32(G_CME_LCL_EINR))) & (core << SHIFT32(21))) - { - core_spattn = (in32_sh(CME_LCL_SISR) >> SHIFT64SH(33)) & core; + PK_TRACE("Disable thread0 for RAM via THREAD_INFO"); + CME_PUTSCOM(THREAD_INFO, core, 0); - if (core_spattn) - { - PK_TRACE_ERR("ERROR: Core[%d] Special Attention Detected. Gard Core!", core_spattn); - CME_STOP_CORE_ERROR_HANDLER(core, core_spattn, CME_STOP_EXIT_SELF_RES_SPATTN); + PK_TRACE("Disable RAM mode via RAM_MODEREG"); + CME_PUTSCOM(RAM_MODEREG, core, 0); - PK_TRACE("Release PCB Mux back on Core via SICR[10/11]"); - out32(G_CME_LCL_SICR_CLR, core_spattn << SHIFT32(11)); + PK_TRACE("Clear scratch/spr used in RAM"); + CME_PUTSCOM(SPR_MODE, core, 0); + CME_PUTSCOM(SCOM_SPRC, core, 0); - while((core_spattn & ~(in32(G_CME_LCL_SISR) >> SHIFT32(11))) != core_spattn); + if (core & CME_MASK_C0) + { + CME_PUTSCOM(SCRATCH0, CME_MASK_C0, 0); + } - PK_TRACE("PCB Mux Released on Core[%d]", core_spattn); - } + if (core & CME_MASK_C1) + { + CME_PUTSCOM(SCRATCH1, CME_MASK_C1, 0); + } - if (!core) - { +#endif +// Nimbus DD2+ +#else -#if NIMBUS_DD_LEVEL == 20 || DISABLE_CME_DUAL_CAST == 1 +#if SMF_SUPPORT_ENABLE - continue; +#if EPM_P9_TUNING + CME_PUTSCOM(URMOR, core, 0xA200000); + CME_PUTSCOM(HRMOR, core, 0xA200000); #else - if (d2u4_flag) - { - p9_cme_stop_exit_end((CME_MASK_BC - deeper_core), spwu_stop); - } + CME_PUTSCOM(URMOR, core, scom_data.value); + PK_TRACE_INF("SMF core wakes up, write URMOR with HOMER address" ); + scom_data.words.upper = scom_data.words.upper & ~BIT32(15); - return; + if( SPR_SELF_SAVE == i_saveRestore ) + { + scom_data.value = pCmeImgHdr->g_cme_unsec_cpmr_PhyAddr & BITS64(13, 30); //Unsecure HOMER + PKTRACE("SMF core self save, write un-secure HOMER address"); + } -#endif + CME_PUTSCOM(HRMOR, core, scom_data.value); - } - } +#endif //EPM_P9_TUNING - for (core_mask = 2; core_mask; core_mask--) - { - if (core & core_mask) - { - //Cleaning up thread scratch register after self restore. - CME_PUTSCOM(SCRATCH0, core_mask, 0); - CME_PUTSCOM(SCRATCH1, core_mask, 0); - CME_PUTSCOM(SCRATCH2, core_mask, 0); - CME_PUTSCOM(SCRATCH3, core_mask, 0); - } - } +#else //SMF Not supported - PK_TRACE_PERF("SF.RS: Self Restore Completed, Core Stopped Again(pm_exit=0/pm_active=1)"); +#if EPM_P9_TUNING - PK_TRACE("Restore SPATTN after self-restore"); - CME_PUTSCOM(SPATTN_MASK, core, spattn_mask); + CME_PUTSCOM(HRMOR, core, 0xA200000); +#else - PK_TRACE("Always Unfreeze IMA (by clearing bit 34) in case the CHTM is enabled to sample it"); - CME_GETSCOM(IMA_EVENT_MASK, core, scom_data.value); - CME_PUTSCOM(IMA_EVENT_MASK, core, scom_data.value & ~BIT64(34)); + PK_TRACE_INF("Non SMF core wakes up, write HRMOR with HOMER address"); + scom_data.words.upper = scom_data.words.upper & ~BIT32(15); + CME_PUTSCOM(HRMOR, core, scom_data.value); - PK_TRACE("Drop block interrupt to PC via SICR[2/3]"); - out32(G_CME_LCL_SICR_CLR, core << SHIFT32(3)); +#endif //EPM_P9_TUNING - PK_TRACE("Clear pm_active status via EISR[20/21]"); - out32(G_CME_LCL_EISR_CLR, core << SHIFT32(21)); +#endif //SMF_SUPPORT_ENABLE -#endif +#endif //Nimbus DD2+ - if (d2u4_flag) + PK_TRACE("Save off and mask SPATTN before self-restore"); + CME_GETSCOM(SPATTN_MASK, core, G_spattn_mask); + CME_PUTSCOM(SPATTN_MASK, core, BITS64(0, 64)); + +#if !DISABLE_CORE_XSTOP_INJECTION + + PK_TRACE("Read WKUP_ERR_INJECT_MODE via CPMMR[8]"); + + for (core_mask = 2; core_mask; core_mask--) + { + if (core & core_mask) + { + CME_GETSCOM(CPPM_CPMMR, core_mask, scom_data.value); + + if (scom_data.words.upper & BIT32(8)) { - core = CME_MASK_BC; + PK_TRACE_INF("WARNING: Injecting a core[%d] xstop via C_LFIR[11]", core); + CME_PUTSCOM(C_LFIR_OR, core_mask, BIT64(11)); } - } - p9_cme_stop_exit_end(core, spwu_stop); + if( SPR_SELF_SAVE == i_saveRestore ) + { + //Writing thread scratch register to + //Signal Self Save Restore code for save operation. + scom_data.words.upper = 0; + scom_data.words.lower = 1; + } + else + { + //Writing thread scratch register to + // 1. Init Runtime wakeup mode for core. + // 2. Signal Self Save Restore code for restore operation. -#if NIMBUS_DD_LEVEL == 20 || DISABLE_CME_DUAL_CAST == 1 + if (scom_data.words.upper & BIT32(3)) + { + scom_data.value = BIT64(59); + } + else + { + scom_data.value = 0; + } + } - // NDD2: dual cast workaround loop end + if( CME_MASK_C0 & core_mask ) + { + CME_PUTSCOM(SCRATCH0, CME_MASK_C0, scom_data.value); + } + + if( CME_MASK_C1 & core_mask ) + { + CME_PUTSCOM(SCRATCH1, CME_MASK_C1, scom_data.value); + } + } } #endif - //=========================== - MARK_TRAP(ENDSCOPE_STOP_EXIT) - //=========================== + PK_TRACE_PERF("SF.RS: Self Restore Kickoff, S-Reset All Core Threads"); + + // Disable interrupts around the sreset to polling check to not miss the self-restore + wrteei(0); + + CME_PUTSCOM(DIRECT_CONTROLS, core, + BIT64(4) | BIT64(12) | BIT64(20) | BIT64(28)); + sync(); + + //**DISABLE CHECK FOR instruction running to avoid race condition** + //PK_TRACE_INF("Poll for instruction running before drop pm_exit"); + //while((~(in32_sh(CME_LCL_SISR))) & (core << SHIFT64SH(47))); + + wrteei(1); + + PK_TRACE_INF("Allow threads to run(pm_exit=0)"); + out32(G_CME_LCL_SICR_CLR, core << SHIFT32(5)); - return; } -- cgit v1.2.1