Skip to content

Commit

Permalink
STOP: PCBMux Savior version 2 + TLBIE workaround
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
vanderp authored and op-jenkins committed Aug 22, 2018
1 parent 0d33463 commit 2770649
Show file tree
Hide file tree
Showing 3 changed files with 324 additions and 6 deletions.
312 changes: 306 additions & 6 deletions import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand All @@ -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 +++++ +++++");
//--------------------------------------------------------------------------
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
//==========================
Expand Down
13 changes: 13 additions & 0 deletions import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
//=========================================
Expand Down

0 comments on commit 2770649

Please sign in to comment.