summaryrefslogtreecommitdiffstats
path: root/import
diff options
context:
space:
mode:
authorBrian Vanderpool <vanderp@us.ibm.com>2017-03-04 15:02:46 -0600
committerhostboot <hostboot@us.ibm.com>2018-08-22 17:54:30 -0500
commit2770649588ff569e119cf489b13069d44a88aeee (patch)
treebc0200fc7e0403f73c343f1b90e220527b390794 /import
parent0d334632a4fc4a4e0e3a27606b25f5bf84195bda (diff)
downloadtalos-hcode-2770649588ff569e119cf489b13069d44a88aeee.tar.gz
talos-hcode-2770649588ff569e119cf489b13069d44a88aeee.zip
STOP: PCBMux Savior version 2 + TLBIE workaround
1. When the SGPE is scanning the cache, set the PM_DISBLE bits in SLAVE_CONFIG 2. Before the CME request the PCBMUX, mask return codes, do a dummy read to the PPM, unmask return codes, request the mux, poll for completion and then do a read to CPLT_STAT afterwards 3. TLBIE fix - save LPIDs, ram with dummy value, do TLBIE quiesce, restore LPIDS Change-Id: I6523ce1f9ffc168602ef3fb5584245e809e4b256 Original-Change-Id: I058c745aa442107d4af6e4331659d796399b11ed Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/37509 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: AMIT KUMAR <akumar3@us.ibm.com> Reviewed-by: Michael S. Floyd <mfloyd@us.ibm.com> Reviewed-by: Gregory S. Still <stillgs@us.ibm.com>
Diffstat (limited to 'import')
-rwxr-xr-ximport/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c312
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h13
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_entry.c5
3 files changed, 324 insertions, 6 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 f9733582..66f89b96 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
@@ -48,6 +48,223 @@
extern CmeStopRecord G_cme_stop_record;
+
+void prepare_for_ramming (uint32_t core)
+{
+ uint64_t scom_data;
+ PK_TRACE("LPID Assert block interrupt to PC via SICR[2/3]");
+ out32(CME_LCL_SICR_OR, core << SHIFT32(3));
+
+ PK_TRACE("LPID Waking up the core(pm_exit=1) via SICR[4/5]");
+ out32(CME_LCL_SICR_OR, core << SHIFT32(5));
+
+ PKTRACE("LPID Polling for core wakeup(pm_active=0) via EINR[20/21]");
+
+ while((in32(CME_LCL_EINR)) & (core << SHIFT32(21)));
+
+ // Now core thinks its awake and ramming is allowed
+ scom_data = (BIT64(7) | BIT64(15) | BIT64(23) | BIT64(31));
+ PKTRACE ("writing %X to direct controls", (uint32_t) (scom_data >> 32));
+ PK_TRACE("RAMMING Put in core maintenance mode via direct controls");
+ CME_PUTSCOM(DIRECT_CONTROLS, core, scom_data);
+ //CME_PUTSCOM(DIRECT_CONTROLS, core, BIT64(7) | BIT64(15) | BIT64(23) | BIT64(31));
+
+ PK_TRACE("RAMMING Activate thread0-3 for RAM via THREAD_INFO 18-21");
+ CME_PUTSCOM(THREAD_INFO, core, BITS64(18, 4));
+
+ CME_GETSCOM(THREAD_INFO, core, CME_SCOM_AND, scom_data);
+ PKTRACE("THREAD_INFO core 0x%X 0x%X", core, (uint32_t) (scom_data & 0xFFFFFFFF));
+
+
+ PK_TRACE("LPID Enable RAM mode via RAM_MODEREG[0]");
+ CME_PUTSCOM(RAM_MODEREG, core, BIT64(0));
+
+ PKTRACE("LPID Set SPR mode to LT0-7 via SPR_MODE[20-27]");
+ CME_PUTSCOM(SPR_MODE, core, BITS64(20, 8));
+
+ if (core & CME_MASK_C0)
+ {
+ PKTRACE("LPID Set SPRC to scratch0 for core0 via SCOM_SPRC");
+ CME_PUTSCOM(SCOM_SPRC, CME_MASK_C0, 0);
+ }
+
+ if (core & CME_MASK_C1)
+ {
+ PKTRACE("LPID Set SPRC to scratch1 for core1 via SCOM_SPRC");
+ CME_PUTSCOM(SCOM_SPRC, CME_MASK_C1, BIT64(60));
+ }
+}
+
+uint16_t ram_read_lpid( uint32_t core, uint32_t thread )
+{
+ uint64_t scom_data = 0;
+ PK_TRACE_INF("RAM: mfspr lpidr, gpr0 via RAM_CTRL");
+ CME_PUTSCOM(RAM_CTRL, core, RAM_MFSPR_LPIDR_GPR0 | (((uint64_t) thread) << 62));
+
+ PKTRACE("LPID RAM: mtspr sprd , gpr0 via RAM_CTRL");
+ CME_PUTSCOM(RAM_CTRL, core, RAM_MTSPR_SPRD_GPR0 | (((uint64_t) thread) << 62));
+
+ if (core & CME_MASK_C0)
+ {
+ CME_GETSCOM(SCRACTH0, CME_MASK_C0, CME_SCOM_AND, scom_data);
+ }
+
+ if (core & CME_MASK_C1)
+ {
+ CME_GETSCOM(SCRACTH1, CME_MASK_C1, CME_SCOM_AND, scom_data);
+ }
+
+ PKTRACE("RAMMING LPID read for core 0x%X 0x%X", core, (uint32_t) (scom_data & 0xFFFFFFFF));
+
+ if (scom_data > 0xFFF )
+ {
+ PKTRACE("RAMMING ERROR Unexpected LPID core %d : 0x%lX 0xFFF", core, scom_data);
+ pk_halt();
+ }
+
+ return ((uint16_t) scom_data);
+}
+
+
+void ram_write_lpid( uint32_t core, uint32_t thread, uint16_t lpid )
+{
+
+ PKTRACE("LPID2 Writing LPID to 0x%X for core 0x%X thread %d", lpid, core, thread);
+
+ if (core & CME_MASK_C0)
+ {
+ PK_TRACE("LPID Set SPRC to scratch0 for core0 via SCOM_SPRC");
+ CME_PUTSCOM(SCOM_SPRC, CME_MASK_C0, 0);
+ CME_PUTSCOM(SCRACTH0, CME_MASK_C0, (uint64_t) lpid);
+ }
+
+ if (core & CME_MASK_C1)
+ {
+ PK_TRACE("LPID Set SPRC to scratch1 for core1 via SCOM_SPRC");
+ CME_PUTSCOM(SCOM_SPRC, CME_MASK_C1, BIT64(60));
+ CME_PUTSCOM(SCRACTH1, CME_MASK_C1, (uint64_t) lpid);
+ }
+
+ PK_TRACE("LPID RAM: mfspr sprd , gpr0 via RAM_CTRL");
+ CME_PUTSCOM(RAM_CTRL, core, RAM_MFSPR_SPRD_GPR0 | (((uint64_t) thread) << 62));
+
+ PK_TRACE("RAM: mtspr lpidr, gpr0 via RAM_CTRL");
+ CME_PUTSCOM(RAM_CTRL, core, RAM_MTSPR_LPIDR_GPR0 | (((uint64_t) thread) << 62));
+}
+
+
+void turn_off_ram_mode (uint32_t core)
+{
+ uint64_t scom_data;
+
+ PK_TRACE("LPID Disable thread0-3 for RAM via THREAD_INFO");
+ CME_PUTSCOM(THREAD_INFO, core, 0);
+
+ PK_TRACE("LPID Disable RAM mode via RAM_MODEREG");
+ CME_PUTSCOM(RAM_MODEREG, core, 0);
+
+ PK_TRACE("LPID Clear scratch/spr used in RAM");
+ CME_PUTSCOM(SPR_MODE, core, 0);
+ CME_PUTSCOM(SCOM_SPRC, core, 0);
+
+ if (core & CME_MASK_C0)
+ {
+ CME_PUTSCOM(SCRACTH0, CME_MASK_C0, 0);
+ }
+
+ if (core & CME_MASK_C1)
+ {
+ CME_PUTSCOM(SCRACTH1, CME_MASK_C1, 0);
+ }
+
+ PK_TRACE("LPID Clear core maintenance mode via direct controls");
+ scom_data = (BIT64(3) | BIT64(11) | BIT64(19) | BIT64(27));
+ PKTRACE("LPID Clear core maintenance mode via direct controls %X", (uint32_t) (scom_data >> 32));
+ CME_PUTSCOM(DIRECT_CONTROLS, core, scom_data);
+ //CME_PUTSCOM(DIRECT_CONTROLS, core, BIT64(3) | BIT64(11) | BIT64(19) | BIT64(27));
+
+ PK_TRACE("LPID Drop pm_exit via SICR[4/5]");
+ out32(CME_LCL_SICR_CLR, core << SHIFT32(5));
+
+ PKTRACE("LPID Polling for core to stop(pm_active=1) via EINR[20/21]");
+
+ while((~(in32(CME_LCL_EINR))) & (core << SHIFT32(21)));
+
+ PKTRACE("LPID Clear pm_active status via EISR[20/21]");
+ out32(CME_LCL_EISR_CLR, core << SHIFT32(21));
+
+ PK_TRACE("LPID Drop block interrupt to PC via SICR[2/3]");
+ out32(CME_LCL_SICR_CLR, core << SHIFT32(3));
+
+}
+
+
+void p9_cme_acquire_pcbmux(uint32_t core, uint32_t check)
+{
+
+ PK_TRACE("Request PCB mux via SICR[10/11]");
+
+#ifdef HW405292_NDD1_PCBMUX_SAVIOR
+ p9_cme_pcbmux_savior_prologue(core);
+#endif
+ out32(CME_LCL_SICR_OR, core << SHIFT32(11));
+
+ // Poll Infinitely for PCB Mux Grant
+ // MF: change watchdog timer in pk to ensure forward progress
+ while((core & (in32(CME_LCL_SISR) >> SHIFT32(11))) != core);
+
+ if (check != 0)
+ {
+#ifdef HW405292_NDD1_PCBMUX_SAVIOR
+ p9_cme_pcbmux_savior_epilogue(core);
+#endif
+ }
+
+ PK_TRACE_INF("S: PCB Mux Granted C[%d]", core);
+
+}
+
+void p9_cme_release_pcbmux(uint32_t core)
+{
+
+ out32(CME_LCL_SICR_CLR, core << SHIFT32(11));
+
+ while((core & ~(in32(CME_LCL_SISR) >> SHIFT32(11))) != core);
+
+}
+
+#ifdef HW405292_NDD1_PCBMUX_SAVIOR
+
+void p9_cme_pcbmux_savior_prologue(uint32_t core)
+{
+ uint32_t old_msr = 0;
+ uint32_t new_msr = 0;
+ uint64_t scom_data = 0;
+
+ old_msr = mfmsr();
+ new_msr = old_msr | 0x7F000000;
+ mtmsr(new_msr);
+ CME_GETSCOM(0x8F0002, core, CME_SCOM_AND, scom_data);
+ mtmsr(old_msr);
+}
+
+void p9_cme_pcbmux_savior_epilogue(uint32_t core)
+{
+ uint64_t scom_data = 0;
+ uint32_t old_msr = 0;
+ uint32_t new_msr = 0;
+
+ // Read the value from core CPLT_STAT0. Ignore the data
+ old_msr = mfmsr();
+ new_msr = old_msr | 0x7F000000;
+ mtmsr(new_msr);
+ CME_GETSCOM(0x00000100, core, CME_SCOM_EQ, scom_data);
+ mtmsr(old_msr);
+
+}
+
+#endif
+
int
p9_cme_stop_entry()
{
@@ -70,6 +287,14 @@ p9_cme_stop_entry()
data64_t scom_data = {0};
ppm_pig_t pig = {0};
+#if HW402407_NDD1_TLBIE_STOP_WORKAROUND
+
+ uint32_t thread = 0;
+ uint16_t lpid_c0[4] = {0, 0, 0, 0};
+ uint16_t lpid_c1[4] = {0, 0, 0, 0};
+
+#endif // tlbie stop workaround
+
//--------------------------------------------------------------------------
PK_TRACE_INF("+++++ +++++ BEGIN OF STOP ENTRY +++++ +++++");
//--------------------------------------------------------------------------
@@ -233,8 +458,7 @@ p9_cme_stop_entry()
PK_TRACE_INF("+++++ +++++ STOP LEVEL 2 ENTRY +++++ +++++");
//----------------------------------------------------------------------
- PK_TRACE("Request PCB mux via SICR[10/11]");
- out32(CME_LCL_SICR_OR, core << SHIFT32(11));
+ p9_cme_acquire_pcbmux(core, 1);
PK_TRACE("Pulse STOP entry acknowledgement to PC via SICR[0/1]");
out32(CME_LCL_SICR_OR, core << SHIFT32(1));
@@ -278,11 +502,42 @@ p9_cme_stop_entry()
PK_TRACE_DBG("Check: core[%d] target_lv[%d] deeper_lv[%d] deeper_core[%d]",
core, target_level, deeper_level, deeper_core);
- // Poll Infinitely for PCB Mux Grant
- // MF: change watchdog timer in pk to ensure forward progress
- while((core & (in32(CME_LCL_SISR) >> SHIFT32(11))) != core);
+#if HW402407_NDD1_TLBIE_STOP_WORKAROUND
+
+// 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)
+ {
+ lpid_c0[thread] = ram_read_lpid(CME_MASK_C0, thread);
+ PKTRACE("c0lpid %X thread %X", (uint32_t) lpid_c0[thread], thread);
+ ram_write_lpid(CME_MASK_C0, thread, POWMAN_RESERVED_LPID);
+
+ if (ram_read_lpid(CME_MASK_C0, thread) != POWMAN_RESERVED_LPID)
+ {
+ asm("trap");
+ }
+ }
+
+ if (core & CME_MASK_C1)
+ {
+ lpid_c1[thread] = ram_read_lpid(CME_MASK_C1, thread);
+ PKTRACE("c1lpid %X thread %X", (uint32_t) lpid_c1[thread], thread);
+ ram_write_lpid(CME_MASK_C1, thread, POWMAN_RESERVED_LPID);
+
+ if (ram_read_lpid(CME_MASK_C1, thread) != POWMAN_RESERVED_LPID)
+ {
+ asm("trap");
+ }
+ }
+ }
+
+// turn_off_ram_mode (core);
+
- PK_TRACE_INF("SE2.A: PCB Mux Granted");
+#endif // tlbie stop workaround
//=============================
MARK_TRAP(SE_QUIESCE_CORE_INTF)
@@ -313,6 +568,51 @@ p9_cme_stop_entry()
PK_TRACE_INF("SE2.B: Interfaces Quiesced");
+#if HW402407_NDD1_TLBIE_STOP_WORKAROUND
+
+// Restore thread's LPIDs
+
+// prepare_for_ramming(core);
+
+ for (thread = 0; thread < 4; 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]);
+ }
+ }
+
+
+ // Read back and check
+ for (thread = 0; thread < 4; thread++ )
+ {
+ if (core & CME_MASK_C0)
+ {
+ if (ram_read_lpid(CME_MASK_C0, thread) != lpid_c0[thread])
+ {
+ asm("trap");
+ }
+ }
+
+ if (core & CME_MASK_C1)
+ {
+ if (ram_read_lpid(CME_MASK_C1, thread) != lpid_c1[thread])
+ {
+ asm("trap");
+ }
+ }
+ }
+
+ turn_off_ram_mode (core);
+
+
+#endif // tlbie stop workaround
+
//==========================
MARK_TRAP(SE_STOP_CORE_CLKS)
//==========================
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h
index 6a186d67..7aa7a0ad 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h
@@ -87,6 +87,8 @@ extern "C" {
#define EQ_HANG_PULSE_6_REG 0x100F0026
#define EQ_NET_CTRL0_WAND 0x100F0041
#define EQ_NET_CTRL0_WOR 0x100F0042
+
+#define C_SLAVE_CONFIG 0x200F001E
#define C_NET_CTRL0 0x200F0040
#define C_NET_CTRL0_WAND 0x200F0041
#define C_NET_CTRL0_WOR 0x200F0042
@@ -203,6 +205,12 @@ enum SGPE_STOP_EVENT_LEVELS
LEVEL_EQ_BASE = 11
};
+enum SGPE_SLAVE_CONFIG_BITS
+{
+ SLAVE_CONFIG_PM_DISABLE = BIT64(6),
+ SLAVE_CONFIG_PM_MUX_DISABLE = BIT64(7)
+};
+
enum SGPE_STOP_CME_FLAGS
{
CME_TRACE_ENABLE = BIT32(4),
@@ -295,6 +303,11 @@ typedef struct
uint64_t data;
} SgpeScomRestore;
+#if HW405292_NDD1_PCBMUX_FENCE_FIX
+void p9_sgpe_set_slvcfg_pm_disable(uint32_t);
+void p9_sgpe_clear_slvcfg_pm_disable(uint32_t);
+#endif
+
/// SGPE to PGPE IPC handlers
void p9_sgpe_ipc_pgpe_ctrl_stop_updates(ipc_msg_t* cmd, void* arg);
void p9_sgpe_ipc_pgpe_suspend_stop(ipc_msg_t* cmd, void* arg);
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_entry.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_entry.c
index c7d1672b..c56c0b14 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_entry.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_entry.c
@@ -875,6 +875,11 @@ p9_sgpe_stop_entry()
PK_TRACE_INF("SE11.D: Cache Clock Stopped");
+#if HW405292_NDD1_PCBMUX_FENCE_FIX
+ // Gate the PCBMux request so scanning doesn't cause random requests
+ p9_sgpe_set_slvcfg_pm_disable(qloop);
+#endif
+
//=========================================
MARK_TAG(SE_POWER_OFF_CACHE, (32 >> qloop))
//=========================================
OpenPOWER on IntegriCloud