diff options
Diffstat (limited to 'import/chips/p9/procedures/ppe_closed/cme')
8 files changed, 314 insertions, 138 deletions
diff --git a/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.c b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.c index 375724c8..253490c1 100644 --- a/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.c +++ b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.c @@ -51,8 +51,10 @@ const uint64_t ext_irq_vectors_cme[NUM_EXT_IRQ_PRTY_LEVELS][2] = { /* 0: IDX_PRTY_VEC 1: IDX_MASK_VEC */ { - IRQ_VEC_PRTY0_CME, - IRQ_VEC_PRTY8_CME | /* 0: IDX_PRTY_LVL_HIPRTY */ + IRQ_VEC_PRTY0_CME, /* 0: IDX_PRTY_LVL_HIPRTY */ + IRQ_VEC_PRTY10_CME | + IRQ_VEC_PRTY9_CME | + IRQ_VEC_PRTY8_CME | IRQ_VEC_PRTY7_CME | IRQ_VEC_PRTY6_CME | IRQ_VEC_PRTY5_CME | @@ -63,8 +65,10 @@ const uint64_t ext_irq_vectors_cme[NUM_EXT_IRQ_PRTY_LEVELS][2] = IRQ_VEC_PRTY0_CME }, { - IRQ_VEC_PRTY1_CME, - IRQ_VEC_PRTY8_CME | /* 1: IDX_PRTY_LVL_BCE_DB3 */ + IRQ_VEC_PRTY1_CME, /* 1: IDX_PRTY_LVL_DB3 */ + IRQ_VEC_PRTY10_CME | + IRQ_VEC_PRTY9_CME | + IRQ_VEC_PRTY8_CME | IRQ_VEC_PRTY7_CME | IRQ_VEC_PRTY6_CME | IRQ_VEC_PRTY5_CME | @@ -74,8 +78,10 @@ const uint64_t ext_irq_vectors_cme[NUM_EXT_IRQ_PRTY_LEVELS][2] = IRQ_VEC_PRTY1_CME }, { - IRQ_VEC_PRTY2_CME, - IRQ_VEC_PRTY8_CME | /* 2: IDX_PRTY_LVL_WAKE_DB2 */ + IRQ_VEC_PRTY2_CME, /* 2: IDX_PRTY_LVL_DB2 */ + IRQ_VEC_PRTY10_CME | + IRQ_VEC_PRTY9_CME | + IRQ_VEC_PRTY8_CME | IRQ_VEC_PRTY7_CME | IRQ_VEC_PRTY6_CME | IRQ_VEC_PRTY5_CME | @@ -84,8 +90,10 @@ const uint64_t ext_irq_vectors_cme[NUM_EXT_IRQ_PRTY_LEVELS][2] = IRQ_VEC_PRTY2_CME }, { - IRQ_VEC_PRTY3_CME, - IRQ_VEC_PRTY8_CME | /* 3: IDX_PRTY_LVL_STOP */ + IRQ_VEC_PRTY3_CME, /* 3: IDX_PRTY_LVL_SPWU */ + IRQ_VEC_PRTY10_CME | + IRQ_VEC_PRTY9_CME | + IRQ_VEC_PRTY8_CME | IRQ_VEC_PRTY7_CME | IRQ_VEC_PRTY6_CME | IRQ_VEC_PRTY5_CME | @@ -93,34 +101,55 @@ const uint64_t ext_irq_vectors_cme[NUM_EXT_IRQ_PRTY_LEVELS][2] = IRQ_VEC_PRTY3_CME }, { - IRQ_VEC_PRTY4_CME, - IRQ_VEC_PRTY8_CME | /* 4: IDX_PRTY_LVL_DB1 */ + IRQ_VEC_PRTY4_CME, /* 4: IDX_PRTY_LVL_WAKE */ + IRQ_VEC_PRTY10_CME | + IRQ_VEC_PRTY9_CME | + IRQ_VEC_PRTY8_CME | IRQ_VEC_PRTY7_CME | IRQ_VEC_PRTY6_CME | IRQ_VEC_PRTY5_CME | IRQ_VEC_PRTY4_CME }, { - IRQ_VEC_PRTY5_CME, - IRQ_VEC_PRTY8_CME | /* 5: IDX_PRTY_LVL_DB0 */ + IRQ_VEC_PRTY5_CME, /* 5: IDX_PRTY_LVL_STOP */ + IRQ_VEC_PRTY10_CME | + IRQ_VEC_PRTY9_CME | + IRQ_VEC_PRTY8_CME | IRQ_VEC_PRTY7_CME | IRQ_VEC_PRTY6_CME | IRQ_VEC_PRTY5_CME }, { - IRQ_VEC_PRTY6_CME, - IRQ_VEC_PRTY8_CME | /* 6: IDX_PRTY_LVL_INTERCME_IN0 */ + IRQ_VEC_PRTY6_CME, /* 6: IDX_PRTY_LVL_DB1 */ + IRQ_VEC_PRTY10_CME | + IRQ_VEC_PRTY9_CME | + IRQ_VEC_PRTY8_CME | IRQ_VEC_PRTY7_CME | IRQ_VEC_PRTY6_CME }, + { - IRQ_VEC_PRTY7_CME, - IRQ_VEC_PRTY8_CME | /* 7: IDX_PRTY_LVL_PMCR */ + IRQ_VEC_PRTY7_CME, /* 7: IDX_PRTY_LVL_DB0 */ + IRQ_VEC_PRTY10_CME | + IRQ_VEC_PRTY9_CME | + IRQ_VEC_PRTY8_CME | IRQ_VEC_PRTY7_CME }, + + { + IRQ_VEC_PRTY8_CME, /* 8: IDX_PRTY_LVL_INTERCME_IN0 */ + IRQ_VEC_PRTY10_CME | + IRQ_VEC_PRTY9_CME | + IRQ_VEC_PRTY8_CME + }, + { + IRQ_VEC_PRTY9_CME, /* 9: IDX_PRTY_LVL_PMCR */ + IRQ_VEC_PRTY10_CME | + IRQ_VEC_PRTY9_CME + }, { - IRQ_VEC_PRTY8_CME, - IRQ_VEC_PRTY8_CME /* 8: IDX_PRTY_LVL_DISABLED */ + IRQ_VEC_PRTY10_CME, /* 10: IDX_PRTY_LVL_DISABLED */ + IRQ_VEC_PRTY10_CME } }; diff --git a/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.h b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.h index fc60c76b..ca56f2fe 100644 --- a/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.h +++ b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.h @@ -65,37 +65,43 @@ // Priority Levels #define IDX_PRTY_LVL_HIPRTY 0 -#define IDX_PRTY_LVL_BCE_DB3 1 -#define IDX_PRTY_LVL_WAKE_DB2 2 -#define IDX_PRTY_LVL_STOP 3 -#define IDX_PRTY_LVL_DB1 4 -#define IDX_PRTY_LVL_DB0 5 -#define IDX_PRTY_LVL_INTERCME_IN0 6 -#define IDX_PRTY_LVL_PMCR 7 -#define IDX_PRTY_LVL_DISABLED 8 +#define IDX_PRTY_LVL_DB3 1 +#define IDX_PRTY_LVL_DB2 2 +#define IDX_PRTY_LVL_SPWU 3 +#define IDX_PRTY_LVL_WAKE 4 +#define IDX_PRTY_LVL_STOP 5 +#define IDX_PRTY_LVL_DB1 6 +#define IDX_PRTY_LVL_DB0 7 +#define IDX_PRTY_LVL_INTERCME_IN0 8 +#define IDX_PRTY_LVL_PMCR 9 +#define IDX_PRTY_LVL_DISABLED 10 #define IDX_PRTY_VEC 0 #define IDX_MASK_VEC 1 -#define NUM_EXT_IRQ_PRTY_LEVELS (uint8_t)(9) +#define NUM_EXT_IRQ_PRTY_LEVELS (uint8_t)(11) extern const uint64_t ext_irq_vectors_cme[NUM_EXT_IRQ_PRTY_LEVELS][2]; // Group0: Non-task hi-prty IRQs #define IRQ_VEC_PRTY0_CME (uint64_t)(0xFE00000000000000) -// Group1: BCE+DB3 +// Group1: DB3 #define IRQ_VEC_PRTY1_CME (uint64_t)(0x0030000000000000) -// Group2: WAKE+DB2 -#define IRQ_VEC_PRTY2_CME (uint64_t)(0x000FF00000000000) -// Group3: STOP -#define IRQ_VEC_PRTY3_CME (uint64_t)(0x00000C0000000000) -// Group4: DB1 -#define IRQ_VEC_PRTY4_CME (uint64_t)(0x0000000000C00000) -// Group5: DB0 -#define IRQ_VEC_PRTY5_CME (uint64_t)(0x000000000C000000) -// Group6: INTERCME_IN0 -#define IRQ_VEC_PRTY6_CME (uint64_t)(0x0100000000000000) -// Group7: PMCR -#define IRQ_VEC_PRTY7_CME (uint64_t)(0x0000000030000000) -// Group8: We should never detect these -#define IRQ_VEC_PRTY8_CME (uint64_t)(0x00C003FFC33FFFFF) +// Group2: DB2 +#define IRQ_VEC_PRTY2_CME (uint64_t)(0x0000300000000000) +// Group3: SPWU +#define IRQ_VEC_PRTY3_CME (uint64_t)(0x0003000000000000) +// Group4: WAKE +#define IRQ_VEC_PRTY4_CME (uint64_t)(0x000CC00000000000) +// Group5: STOP +#define IRQ_VEC_PRTY5_CME (uint64_t)(0x00000C0000000000) +// Group6: DB1 +#define IRQ_VEC_PRTY6_CME (uint64_t)(0x0000000000C00000) +// Group7: DB0 +#define IRQ_VEC_PRTY7_CME (uint64_t)(0x000000000C000000) +// Group8: INTERCME_IN0 +#define IRQ_VEC_PRTY8_CME (uint64_t)(0x0100000000000000) +// Group9: PMCR +#define IRQ_VEC_PRTY9_CME (uint64_t)(0x0000000030000000) +// Group10: We should never detect these +#define IRQ_VEC_PRTY10_CME (uint64_t)(0x00C003FFC33FFFFF) // This should be 0xFFFFFFFFFFFFFFFF #define IRQ_VEC_PRTY_CHECK ( IRQ_VEC_PRTY0_CME | \ @@ -106,7 +112,9 @@ extern const uint64_t ext_irq_vectors_cme[NUM_EXT_IRQ_PRTY_LEVELS][2]; IRQ_VEC_PRTY5_CME | \ IRQ_VEC_PRTY6_CME | \ IRQ_VEC_PRTY7_CME | \ - IRQ_VEC_PRTY8_CME ) + IRQ_VEC_PRTY8_CME | \ + IRQ_VEC_PRTY9_CME | \ + IRQ_VEC_PRTY10_CME ) extern uint8_t g_current_prty_level; extern uint8_t g_eimr_stack[NUM_EXT_IRQ_PRTY_LEVELS]; diff --git a/import/chips/p9/procedures/ppe_closed/cme/p9_cme_main.c b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_main.c index 3f9a9912..723a740e 100644 --- a/import/chips/p9/procedures/ppe_closed/cme/p9_cme_main.c +++ b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_main.c @@ -60,14 +60,14 @@ IRQ_HANDLER(p9_cme_stop_exit_handler, (void*) & (G_cme_stop_record.sem[1])) //CMEHW_IRQ_PC_INTR_PENDING_C0 IRQ_HANDLER(p9_cme_stop_exit_handler, (void*) & (G_cme_stop_record.sem[1])) //CMEHW_IRQ_PC_INTR_PENDING_C1 +IRQ_HANDLER(p9_cme_stop_spwu_handler, (void*) & (G_cme_stop_record.sem[1])) +//CMEHW_IRQ_SPECIAL_WAKEUP_C0 +IRQ_HANDLER(p9_cme_stop_spwu_handler, (void*) & (G_cme_stop_record.sem[1])) +//CMEHW_IRQ_SPECIAL_WAKEUP_C1 IRQ_HANDLER(p9_cme_stop_exit_handler, (void*) & (G_cme_stop_record.sem[1])) //CMEHW_IRQ_REG_WAKEUP_C0 IRQ_HANDLER(p9_cme_stop_exit_handler, (void*) & (G_cme_stop_record.sem[1])) //CMEHW_IRQ_REG_WAKEUP_C1 -IRQ_HANDLER(p9_cme_stop_exit_handler, (void*) & (G_cme_stop_record.sem[1])) -//CMEHW_IRQ_SPECIAL_WAKEUP_C0 -IRQ_HANDLER(p9_cme_stop_exit_handler, (void*) & (G_cme_stop_record.sem[1])) -//CMEHW_IRQ_SPECIAL_WAKEUP_C1 IRQ_HANDLER(p9_cme_stop_db2_handler, 0) //CMEHW_IRQ_DOORBELL2_C0 IRQ_HANDLER(p9_cme_stop_db2_handler, 0) //CMEHW_IRQ_DOORBELL2_C1 IRQ_HANDLER(p9_cme_stop_enter_handler, (void*) & (G_cme_stop_record.sem[0])) diff --git a/import/chips/p9/procedures/ppe_closed/cme/pk_app_cfg.h b/import/chips/p9/procedures/ppe_closed/cme/pk_app_cfg.h index 4fd3cc7c..4313ddd7 100644 --- a/import/chips/p9/procedures/ppe_closed/cme/pk_app_cfg.h +++ b/import/chips/p9/procedures/ppe_closed/cme/pk_app_cfg.h @@ -34,43 +34,27 @@ /// \brief Application specific overrides go here. /// -// @todo RTC 161182 -#define HW386841_DD1_PLS_SRR1_DSL_STOP1_FIX 0 -#define TEST_ONLY_BCE_IRR 0 +/// @todo RTC 161182 -// -------------------- - -#ifndef EPM_P9_TUNING - #define EPM_P9_TUNING 0 +#if NIMBUS_DD_LEVEL == 1 + #define HW386841_DD1_PLS_SRR1_DSL_STOP1_FIX 0 #endif -#define STOP_PRIME 0 -#define SKIP_ABORT 0 -#define SKIP_L2_PURGE_ABORT 0 -#define SKIP_ENTRY_CATCHUP 0 -#define SKIP_EXIT_CATCHUP 0 -#define SKIP_ARRAYINIT 0 -#define SKIP_SCAN0 0 -#define SKIP_INITF 0 -#define SKIP_SELF_RESTORE 0 -#define SKIP_RAM_HRMOR 0 +// -------------------- #if EPM_P9_TUNING - #define SPWU_AUTO 1 - #define SKIP_BCE_SCAN_RING 1 - #define SKIP_BCE_SCOM_RESTORE 1 - #define EPM_BROADSIDE_SCAN0 0 -#else - #define SPWU_AUTO 0 - #define SKIP_BCE_SCAN_RING 0 + // EPM use broadside RTX instead of BCE + #undef SKIP_BCE_SCAN_RING + #define SKIP_BCE_SCAN_RING 1 + + #undef SKIP_BCE_SCOM_RESTORE #define SKIP_BCE_SCOM_RESTORE 1 - #define EPM_BROADSIDE_SCAN0 0 + + #define PK_TRACE_BUFFER_WRAP_MARKER 1 #endif // -------------------- -#define PK_TRACE_LEVEL 2 - #if PK_TRACE_LEVEL == 0 /*No TRACEs*/ #define PK_TRACE_ENABLE 0 #define PK_KERNEL_TRACE_ENABLE 0 @@ -86,44 +70,22 @@ #define PK_KERNEL_TRACE_ENABLE 1 #endif -#if EPM_P9_TUNING - #define PK_TRACE_BUFFER_WRAP_MARKER 1 -#endif -#define PK_TRACE_TIMER_OUTPUT 0 - -// -------------------- - -#define SIMICS_TUNING 0 -#define USE_SIMICS_IO 0 -#define DEV_DEBUG 1 - // -------------------- -// Force CME and GPE tasks to use the unified interrupt handler. -#define UNIFIED_IRQ_HANDLER_CME - -// This application will use the external timebase register -// (comment this line out to use the decrementer as timebase) -#define APPCFG_USE_EXT_TIMEBASE - // If we are using the external timebase then assume // a frequency of 37.5Mhz. Otherwise, the default is to use -// the decrementer as a timebase and assume a frequency of -// 600MHz +// the decrementer as a timebase and assume a frequency of 600MHz // In product code, this value will be IPL-time configurable. + #ifdef APPCFG_USE_EXT_TIMEBASE #define PPE_TIMEBASE_HZ 37500000 #else #define PPE_TIMEBASE_HZ 600000000 -#endif /* APPCFG_USE_EXT_TIMEBASE */ +#endif // -------------------- /// This file provides architecture-specific symbol names for each interrupt #include "cmehw_interrupts.h" -/// This application will statically initialize it's external interrupt table -/// using the table defined in pk_app_irq_table.c. -#define STATIC_IRQ_TABLE - #endif /*__PK_APP_CFG_H__*/ diff --git a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop.h b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop.h index 247dec5e..3f61152d 100644 --- a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop.h +++ b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop.h @@ -119,6 +119,40 @@ #define PERV_OPCG_CAPT2 0x20030012 #define PERV_CPLT_STAT0 0x20000100 + +/// Macro to evaluate g_eimr_override +#if SPWU_AUTO +#define EVAL_EIMR_OVERRIDE(mask_irqs) \ + g_eimr_override &= ~(BITS64(12, 6) | BITS64(20, 2)); \ + mask_irqs.words.lower = 0; \ + mask_irqs.words.upper = \ + ((((~G_cme_stop_record.core_enabled) | \ + G_cme_stop_record.core_running | \ + G_cme_stop_record.core_stopgpe | \ + G_cme_stop_record.core_blockwu) & CME_MASK_BC) << SHIFT32(13)) | \ + ((((~G_cme_stop_record.core_enabled) | \ + G_cme_stop_record.core_running) & CME_MASK_BC) << SHIFT32(15)) | \ + ((((~G_cme_stop_record.core_enabled) | \ + G_cme_stop_record.core_running) & CME_MASK_BC) << SHIFT32(17)) | \ + (((~(G_cme_stop_record.core_enabled & \ + G_cme_stop_record.core_running)) & CME_MASK_BC) << SHIFT32(21)); \ + g_eimr_override |= mask_irqs.value; +#else +#define EVAL_EIMR_OVERRIDE(mask_irqs) \ + g_eimr_override &= ~(BITS64(12, 6) | BITS64(20, 2)); \ + mask_irqs.words.lower = 0; \ + mask_irqs.words.upper = \ + ((((~G_cme_stop_record.core_enabled) | \ + G_cme_stop_record.core_running | \ + G_cme_stop_record.core_stopgpe | \ + G_cme_stop_record.core_blockwu) & CME_MASK_BC) << SHIFT32(13)) | \ + ((((~G_cme_stop_record.core_enabled) | \ + G_cme_stop_record.core_running) & CME_MASK_BC) << SHIFT32(17)) | \ + (((~(G_cme_stop_record.core_enabled & \ + G_cme_stop_record.core_running)) & CME_MASK_BC) << SHIFT32(21)); \ + g_eimr_override |= mask_irqs.value; +#endif + /// Macro to update STOP History #define CME_STOP_UPDATE_HISTORY(core,gated,trans,req_l,act_l,req_e,act_e) \ hist.value = 0; \ @@ -273,6 +307,17 @@ typedef struct uint64_t data; } CmeScomRestore; +/// 64bits data +typedef union +{ + uint64_t value; + struct + { + uint32_t upper; + uint32_t lower; + } words; +} data64_t; + /// Stop Score Board Structure typedef struct { @@ -284,18 +329,16 @@ typedef struct // need to be a global state for aborting entry uint8_t act_level_c0; uint8_t act_level_c1; - // partial good configuration, - // todo: consider partial good changed during stop, + // target mask of enabled cores, used to filter 2bit core select in scom address uint32_t core_enabled; // whether core is in running state, - // need to be a global state for aborted entry detection and wakeup masking + // used for aborted entry detection or filter wakeup core select in scom address uint32_t core_running; - // core stop handoff to sgpe from cme - // need to be a global state for wakeup and pm_active masking + // core stop process handoff to sgpe from cme, used to mask pc_intr_pending uint32_t core_stopgpe; - // core in block wakeup mode + // core in block wakeup mode, can be used as core select in scom address or data uint32_t core_blockwu; - // core in special wakeup + // core in special wakeup, can be used as core select in scom address or data uint32_t core_in_spwu; // cme header attributes uint32_t header_flags; 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 6ec1b08e..886e2694 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 @@ -61,6 +61,7 @@ p9_cme_stop_entry() uint32_t core_aborted = 0; uint32_t core_catchup = 0; uint32_t core_stop1 = 0; + uint32_t core_raw = 0; uint32_t core; uint32_t loop; uint32_t pm_states; @@ -77,7 +78,14 @@ p9_cme_stop_entry() // Iow, which of the two cores, "left-0" or "right-1", updated their // STOP PM_STATE. If both have fired by the time we get to this point, // CME will do Daul-cast to both cores at the same time in entry flow. - core = (in32(CME_LCL_EISR) & BITS32(20, 2)) >> SHIFT32(21); + + // pm_active is edge trigger because its level can be phantom + // due to common-core constantly gives pm_active when core is stopped, + // reading from EINR for raw signal, ignore EISR if EINR signal is gone + core = (in32(CME_LCL_EISR) & BITS32(20, 2)); + core_raw = (in32(CME_LCL_EINR) & BITS32(20, 2)); + out32(CME_LCL_EISR_CLR, core); + core = (core & core_raw) >> SHIFT32(21); // filter with partial good and running core mask // core cannot enter stop if core is already stopped @@ -90,8 +98,9 @@ p9_cme_stop_entry() if (!core) { - PK_TRACE_INF("ERROR: No PM_ACTIVE Fired From a Running and Enabled Core. HALT CME!"); - pk_halt(); + // PM_ACTIVE can be phantom, only gives warning + PK_TRACE_INF("WARNING: No Valid PM_ACTIVE Signal Found. Return"); + return CME_STOP_SUCCESS; } //=================================== 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 9b73095f..6026d2f6 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 @@ -113,35 +113,26 @@ p9_cme_stop_exit() if (spwu_wake) { - PK_TRACE_INF("SX0.A: Assert Core[%d] Special Wakeup Done via SICR[16/17]", spwu_wake); - out32(CME_LCL_SICR_OR, spwu_wake << SHIFT32(17)); - } - -#endif - - if (!core) - { - -#if !SPWU_AUTO - - if (!spwu_wake) - { - -#endif - - PK_TRACE_INF("ERROR: No Wakeup Fired to a Stopped and Enabled Core. HALT CME!"); - pk_halt(); - -#if !SPWU_AUTO - - } - else + // Process special wakeup on a core that is already running + PK_TRACE_INF("SX0.A: Core[%d] pm_exit=1/EISR=0/EIPR=0/spwu_done=1", spwu_wake); + out32(CME_LCL_SICR_OR, spwu_wake << SHIFT32(5)); // assert pm_exit + out32(CME_LCL_EISR_CLR, spwu_wake << SHIFT32(15)); // clear spwu in EISR + out32(CME_LCL_EIPR_CLR, spwu_wake << SHIFT32(15)); // flip EIPR to falling edge + out32(CME_LCL_SICR_OR, spwu_wake << SHIFT32(17)); // assert spwu_done now + G_cme_stop_record.core_in_spwu |= spwu_wake; + + if (!core) { return CME_STOP_SUCCESS; } + } #endif + if (!core) + { + PK_TRACE_INF("ERROR: No Wakeup Fired to a Stopped and Enabled Core. HALT CME!"); + pk_halt(); } @@ -359,6 +350,8 @@ p9_cme_stop_exit() G_cme_stop_record.act_level_c0 : G_cme_stop_record.act_level_c1 ; + spwu_stop |= (core_catchup) & (wakeup >> 2); + PK_TRACE_INF("Catch: core[%d] running[%d] \ core_catchup[%d] catchup_level[%d]", core, G_cme_stop_record.core_running, @@ -462,6 +455,8 @@ p9_cme_stop_exit() G_cme_stop_record.act_level_c0 : G_cme_stop_record.act_level_c1 ; + spwu_stop |= (core_catchup) & (wakeup >> 2); + PK_TRACE_INF("Catch: core[%d] running[%d] \ core_catchup[%d] catchup_level[%d]", core, G_cme_stop_record.core_running, @@ -953,10 +948,14 @@ STOP1_EXIT: if (spwu_stop) { - PK_TRACE_INF("SX0.K: Assert SPWU Done on Core[%d] via SICR[16/17]", spwu_stop); // done = spwu + !pm_active + !core_chiplet_fence + !pcbmux_req + !pcbmux_grant // chiplet fence forces pm_active to zero - out32(CME_LCL_SICR_OR, spwu_stop << SHIFT32(17)); + // Note: pm_exit is asserted above for every core waking up including spwu + PK_TRACE_INF("SX0.K: Core[%d] EISR=0/EIPR=0/spwu_done=1", spwu_stop); + out32(CME_LCL_EISR_CLR, spwu_stop << SHIFT32(15)); // clear spwu in EISR + out32(CME_LCL_EIPR_CLR, spwu_stop << SHIFT32(15)); // flip EIPR to falling edge + out32(CME_LCL_SICR_OR, spwu_stop << SHIFT32(17)); // assert spwu_done now + G_cme_stop_record.core_in_spwu |= spwu_stop; } if ((core = (core & (~spwu_stop)))) diff --git a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_irq_handlers.c b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_irq_handlers.c index fcd938ee..73a71563 100644 --- a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_irq_handlers.c +++ b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_irq_handlers.c @@ -29,33 +29,159 @@ extern CmeStopRecord G_cme_stop_record; +// When take an Interrupt on falling edge of SPWU from a CPPM. +// 1) Read EINR to check if another one has been set +// in the meantime from the same core. If so abort. +// 2) Clear Special Wakeup Done to that CPPM. +// 3) Read GPMMR[1] to see if any Special Wakeup has been sent to active +// in the meantime. If so, set Special Wakeup Done again and abort. +// 4) Otherwise flip polarity of Special Wakeup in EISR and clear PM_EXIT +// (note for abort cases do not Do not flip polarity of Special Wakeup in EISR.) +void +p9_cme_stop_spwu_handler(void* arg, PkIrqId irq) +{ + MARK_TRAP(STOP_SPWU_HANDLER) + PK_TRACE_INF("SPWU Handler: %d", irq); + + PkMachineContext ctx; + int sem_post = 0; + uint32_t raw_spwu = (in32(CME_LCL_EISR) & BITS32(14, 2)) >> SHIFT32(15); + uint64_t scom_data; + + if (raw_spwu & CME_MASK_C0) + { + // if failing edge == spwu drop: + if (G_cme_stop_record.core_in_spwu & CME_MASK_C0) + { + PK_TRACE("Falling edge of spwu_c0, first clearing EISR"); + out32(CME_LCL_EISR_CLR, BIT32(14)); + + // if spwu asserts again before we drop spwu_done, do nothing, else: + if ((~(in32(CME_LCL_EINR))) & BIT32(14)) + { + PK_TRACE("SPWU drop confirmed, now dropping spwu_done"); + out32(CME_LCL_SICR_CLR, BIT32(16)); + + CME_GETSCOM(PPM_GPMMR, CME_MASK_C0, CME_SCOM_AND, scom_data); + + // if spwu has been re-asserted after spwu_done is dropped: + if (scom_data & BIT64(1)) + { + PK_TRACE("SPWU asserts again, re-asserting spwu_done"); + out32(CME_LCL_SICR_OR, BIT32(16)); + } + // if spwu truly dropped: + else + { + PK_TRACE("Flip EIPR to raising edge and drop pm_exit"); + out32(CME_LCL_EIPR_OR, BIT32(14)); + out32(CME_LCL_SICR_CLR, BIT32(4)); + + // Core0 is now out of spwu, allow pm_active + G_cme_stop_record.core_in_spwu &= ~CME_MASK_C0; + g_eimr_override &= ~IRQ_VEC_STOP_C0; + } + } + } + // raising edge, Note do not clear EISR as thread will read and clear: + else + { + PK_TRACE("Raising edge of spwu_c0, clear EISR later in exit thread"); + sem_post = 1; + } + } + + if (raw_spwu & CME_MASK_C1) + { + // if failing edge == spwu drop: + if (G_cme_stop_record.core_in_spwu & CME_MASK_C1) + { + PK_TRACE("Falling edge of spwu_c1, first clearing EISR"); + out32(CME_LCL_EISR_CLR, BIT32(15)); + + // if spwu asserts again before we drop spwu_done, do nothing, else: + if ((~(in32(CME_LCL_EINR))) & BIT32(15)) + { + PK_TRACE("SPWU drop confirmed, now dropping spwu_done"); + out32(CME_LCL_SICR_CLR, BIT32(17)); + + CME_GETSCOM(PPM_GPMMR, CME_MASK_C1, CME_SCOM_AND, scom_data); + + // if spwu has been re-asserted after spwu_done is dropped: + if (scom_data & BIT64(1)) + { + PK_TRACE("SPWU asserts again, re-asserting spwu_done"); + out32(CME_LCL_SICR_OR, BIT32(17)); + } + // if spwu truly dropped: + else + { + PK_TRACE("Flip EIPR to raising edge and drop pm_exit"); + out32(CME_LCL_EIPR_OR, BIT32(15)); + out32(CME_LCL_SICR_CLR, BIT32(5)); + + // Core1 is now out of spwu, allow pm_active + G_cme_stop_record.core_in_spwu &= ~CME_MASK_C1; + g_eimr_override &= ~IRQ_VEC_STOP_C1; + } + } + + } + // raising edge, Note do not clear EISR as thread will read and clear: + else + { + PK_TRACE("Raising edge of spwu_c1, clear EISR later in exit thread"); + sem_post = 1; + } + } + + if (sem_post) + { + out32(CME_LCL_EIMR_OR, BITS32(12, 6) | BITS32(20, 2)); + PK_TRACE_INF("Launching exit thread"); + pk_semaphore_post((PkSemaphore*)arg); + } + else + { + pk_irq_vec_restore(&ctx); + } +} + + + void p9_cme_stop_exit_handler(void* arg, PkIrqId irq) { MARK_TRAP(STOP_EXIT_HANDLER) - PK_TRACE_INF("SX-IRQ: %d", irq); + PK_TRACE_INF("SX Handler: %d", irq); out32(CME_LCL_EIMR_OR, BITS32(12, 6) | BITS32(20, 2)); pk_semaphore_post((PkSemaphore*)arg); } + + void p9_cme_stop_enter_handler(void* arg, PkIrqId irq) { MARK_TRAP(STOP_ENTER_HANDLER) - PK_TRACE_INF("SE-IRQ: %d", irq); + PK_TRACE_INF("SE Handler: %d", irq); out32(CME_LCL_EIMR_OR, BITS32(12, 6) | BITS32(20, 2)); pk_semaphore_post((PkSemaphore*)arg); } + + void p9_cme_stop_db1_handler(void* arg, PkIrqId irq) { PkMachineContext ctx; MARK_TRAP(STOP_DB1_HANDLER) - PK_TRACE_INF("DB1-IRQ: %d", irq); + PK_TRACE_INF("DB1 Handler: %d", irq); pk_irq_vec_restore(&ctx); } + + void p9_cme_stop_db2_handler(void* arg, PkIrqId irq) { @@ -63,7 +189,7 @@ p9_cme_stop_db2_handler(void* arg, PkIrqId irq) cppm_cmedb2_t db2c0, db2c1; MARK_TRAP(STOP_DB2_HANDLER) - PK_TRACE("DB2-IRQ: %d", irq); + PK_TRACE_INF("DB2 Handler: %d", irq); CME_GETSCOM(CPPM_CMEDB2, CME_MASK_C0, CME_SCOM_AND, db2c0.value); CME_GETSCOM(CPPM_CMEDB2, CME_MASK_C1, CME_SCOM_AND, db2c1.value); |