diff options
author | Yue Du <daviddu@us.ibm.com> | 2017-01-22 00:02:26 -0600 |
---|---|---|
committer | Joshua Hunsberger <jahunsbe@us.ibm.com> | 2017-10-23 18:00:49 -0500 |
commit | bed4c8cd7e1a9338f631426aeb3e19451b0bc641 (patch) | |
tree | 3959e6e1e4b11bc0e9d146c2fb1f95e3463d71aa /import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c | |
parent | ffa811767e629eb9a53f85d6c498ab1505fa8861 (diff) | |
download | talos-hcode-bed4c8cd7e1a9338f631426aeb3e19451b0bc641.tar.gz talos-hcode-bed4c8cd7e1a9338f631426aeb3e19451b0bc641.zip |
STOP: block wakeup (+ block entry since patch 15)
Change-Id: I6636b7f77842e9a5e07fffa0f908fb4d46e7d763
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/35205
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: BRIAN D. VICTOR <brian.d.victor1@ibm.com>
Reviewed-by: Brian T. Vanderpool <vanderp@us.ibm.com>
Reviewed-by: Gregory S. Still <stillgs@us.ibm.com>
Diffstat (limited to 'import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c')
-rw-r--r-- | import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c | 310 |
1 files changed, 256 insertions, 54 deletions
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c index 15a4954f..56b703a1 100644 --- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c +++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c @@ -46,12 +46,12 @@ SgpeStopRecord G_sgpe_stop_record __attribute__((section (".dump_ptrs"))) = {0, 0, 0, 0, 0, 0, 0} }, // group vectors - { {0, 0, 0, 0, 0}, + { + {0, 0, 0, 0}, {0, 0, 0, 0}, - {0, 0, 0}, - {0, 0, 0}, - {0, 0, 0}, - {0, 0, 0} + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0} }, // wof status {0, 0, 0, 0}, @@ -59,6 +59,144 @@ SgpeStopRecord G_sgpe_stop_record __attribute__((section (".dump_ptrs"))) = {{0, 0, 0}} }; + + +void +p9_sgpe_stop_suspend_msg_db1(uint32_t qloop, uint32_t msgid) +{ + uint32_t cstart = 0; + uint32_t cloop = 0; + uint32_t cmask = 0; + data64_t scom_data = {0}; + ppm_pig_t pig = {0}; + + for(cstart = 0; cstart < CORES_PER_QUAD; cstart += 2) + { + for(cloop = cstart, cmask = BIT32(((qloop << 2) + cstart)); + cloop < (cstart + CORES_PER_EX); + cloop++, cmask = cmask >> 1) + { + // find the first good core served by each active CME + if (G_sgpe_stop_record.group.core[VECTOR_CONFIG] & cmask) + { + break; + } + } + + // For each quad that is not in STOP 11, send doorbeel + if ((G_sgpe_stop_record.group.quad[VECTOR_ACTIVE] & BIT32(qloop)) && + (cloop != (cstart + CORES_PER_EX))) // if ex is partial good + { + scom_data.words.upper = msgid; + scom_data.words.lower = 0; + p9_dd1_db_unicast_wr(GPE_SCOM_ADDR_CORE(CPPM_CMEDB1, + ((qloop << 2) + cloop)), scom_data.value); + } + // otherwise send an ack pig on behalf of that quad(stop11 or partial bad) or ex (ex is partial bad) + else + { + if (cloop == (cstart + CORES_PER_EX)) + { + cloop = cstart; + } + + pig.fields.req_intr_payload = msgid >> 16; + pig.fields.req_intr_payload |= 0x080; // set bit 4 for ack package + pig.fields.req_intr_type = PIG_TYPE2; + GPE_PUTSCOM(GPE_SCOM_ADDR_CORE(PPM_PIG, ((qloop << 2) + cloop)), pig.value); + } + } +} + +void +p9_sgpe_stop_ipi_handler(void* arg, PkIrqId irq) +{ + PkMachineContext ctx; + uint32_t qloop = 0; + uint32_t action = 0; + uint32_t occflg = in32(OCB_OCCFLG) & BITS32(9, 4); + data64_t scom_data = {0}; + + PK_TRACE_DBG("IPI-IRQ: %d", irq); + // Clear ipi3_lo interrupt + out32(OCB_OISR1_CLR, BIT32(29)); + + // occflg[9]control + [11]exit/[12]entry(filter bit[10] here) + // bit[9] must be on to perform any operations below + // also verify we are doing at least one operation from entry/exit + // otherwise, even bit[9] is on, the requested operation is undefined + // thus cannot be performed(no error taking out when this happens) + if ((occflg & (~BIT32(10))) > BIT32(9)) + { + // msg[5-7] << occflg[10]enable + [11]exit/[12]entry (filter bit[9] here) + // msg[5] : perform block/unblock operation (enable/disable ignore stop func) + // msg[6] : perform exit block/unblock operation + // msg[7] : perform entry block/unblock operation + action = ((occflg & (~BIT32(9))) << 5); + + for (qloop = 0; qloop < MAX_QUADS; qloop++) + { + if (!(G_sgpe_stop_record.group.quad[VECTOR_CONFIG] & BIT32(qloop))) + { + continue; + } + + GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(QPPM_QCCR, qloop), scom_data.value); + + // target quad is to participate block/unblock exit + if (scom_data.words.upper & BIT32(10)) + { + action = action | BIT32(6); + + if (action & BIT32(5)) + { + G_sgpe_stop_record.group.quad[VECTOR_BLOCKX] |= BIT32(qloop); + } + else + { + G_sgpe_stop_record.group.quad[VECTOR_BLOCKX] &= ~BIT32(qloop); + } + } + // not participate exit, taking exit encoding bit out + else + { + action = action & (~BIT32(6)); + } + + // target quad is to participate block/unblock entry + if (scom_data.words.upper & BIT32(11)) + { + action = action | BIT32(7); + + if (action & BIT32(5)) + { + G_sgpe_stop_record.group.quad[VECTOR_BLOCKE] |= BIT32(qloop); + } + else + { + G_sgpe_stop_record.group.quad[VECTOR_BLOCKE] &= ~BIT32(qloop); + } + } + // not participate entry, taking entry encoding bit out + else + { + action = action & (~BIT32(7)); + } + + // if this quad participates either entry/exit for block/unlock + // send msg; otherwise skip the quad + if (action & BITS32(6, 2)) + { + p9_sgpe_stop_suspend_msg_db1(qloop, action); + } + } + } + + pk_irq_vec_restore(&ctx); +} + + + // PCB Interrupt Type2 // Payload // 0 - set = Hardware Exit | unset = Firmware Stop @@ -86,17 +224,20 @@ void p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq) { PkMachineContext ctx; - uint32_t cirq = 0; - uint32_t qirq = 0; - uint32_t cloop = 0; - uint32_t qloop = 0; - uint32_t cpending_t2 = 0; - uint32_t cpending_t3 = 0; - uint32_t qpending_t6 = 0; - uint32_t cpayload_t2 = 0; - uint32_t cpayload_t3 = 0; - uint32_t qpayload_t6 = 0; - uint64_t scom_data = 0; + uint32_t cirq = 0; + uint32_t qirq = 0; + uint32_t cloop = 0; + uint32_t qloop = 0; + uint32_t cpending_t2 = 0; + uint32_t cpending_t3 = 0; + uint32_t qpending_t6 = 0; + uint32_t cpayload_t2 = 0; + uint32_t cpayload_t3 = 0; + uint32_t qpayload_t6 = 0; + uint32_t suspend_mask = 0; + uint32_t suspend_index = 0; + uint32_t vector_index = 0; + data64_t scom_data = {0}; //========================= MARK_TRAP(STOP_PIG_HANDLER) @@ -136,19 +277,15 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq) } // clear group before analyzing input - G_sgpe_stop_record.group.qswu[VECTOR_ENTRY] = 0; G_sgpe_stop_record.group.core[VECTOR_ENTRY] = 0; - G_sgpe_stop_record.group.qswu[VECTOR_EXIT] = 0; + G_sgpe_stop_record.group.qswu[VECTOR_ENTRY] = 0; G_sgpe_stop_record.group.core[VECTOR_EXIT] = 0; - G_sgpe_stop_record.group.ex_l[VECTOR_EXIT] = 0; - G_sgpe_stop_record.group.ex_r[VECTOR_EXIT] = 0; - G_sgpe_stop_record.group.ex_b[VECTOR_EXIT] = 0; + G_sgpe_stop_record.group.qswu[VECTOR_EXIT] = 0; G_sgpe_stop_record.group.quad[VECTOR_EXIT] = 0; // loop all quads for(qloop = 0; qloop < MAX_QUADS; qloop++) { - // if no quad special wakeup, skip to core request if (qirq && (BIT32(qloop) & qpending_t6 & G_sgpe_stop_record.group.quad[VECTOR_CONFIG])) @@ -166,14 +303,15 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq) { PK_TRACE_DBG("Quad Already in Special Wakeup"); } + else if (G_sgpe_stop_record.group.quad[VECTOR_BLOCKX] & BIT32(qloop)) + { + PK_TRACE_DBG("Quad is in Block Wakeup Mode, Ignore Now"); + G_sgpe_stop_record.group.qswu[VECTOR_BLOCKX] |= BIT32(qloop); + } else { G_sgpe_stop_record.group.qswu[VECTOR_EXIT] |= BIT32(qloop); G_sgpe_stop_record.group.quad[VECTOR_EXIT] |= BIT32(qloop); - G_sgpe_stop_record.group.ex_l[VECTOR_EXIT] |= BIT32(qloop); - G_sgpe_stop_record.group.ex_r[VECTOR_EXIT] |= BIT32(qloop); - G_sgpe_stop_record.group.ex_b[VECTOR_EXIT] |= - BITS32((qloop << 1), 2); } } else @@ -181,8 +319,16 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq) PK_TRACE_DBG("Quad Drop Special Wakeup, Clearing Done"); GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(PPM_GPMMR_CLR, qloop), BIT64(0)); - G_sgpe_stop_record.group.qswu[VECTOR_ENTRY] |= BIT32(qloop); - G_sgpe_stop_record.group.qswu[VECTOR_CONFIG] &= ~BIT32(qloop); + if (G_sgpe_stop_record.group.quad[VECTOR_BLOCKE] & BIT32(qloop)) + { + PK_TRACE_DBG("Quad is in Block Entry Mode, Ignore Re-entry Now"); + G_sgpe_stop_record.group.qswu[VECTOR_BLOCKE] |= BIT32(qloop); + } + else + { + G_sgpe_stop_record.group.qswu[VECTOR_ENTRY] |= BIT32(qloop); + G_sgpe_stop_record.group.qswu[VECTOR_CONFIG] &= ~BIT32(qloop); + } } } @@ -194,7 +340,7 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq) } PK_TRACE_DBG("Quad[%d] Has Core Request:", qloop); - PK_TRACE_DBG("Now clv[%d][%d][%d][%d]", + PK_TRACE_DBG("Now Core Levels[%d][%d][%d][%d]", G_sgpe_stop_record.level[qloop][0], G_sgpe_stop_record.level[qloop][1], G_sgpe_stop_record.level[qloop][2], @@ -209,10 +355,10 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq) continue; } - // read payload on core has interrupt2 cpending cpayload_t2 = 0; cpayload_t3 = 0; + // read payload on core has interrupt2 cpending if (cpending_t2 & BIT32((qloop << 2) + cloop)) { cpayload_t2 = in32(OCB_OPIT2CN(((qloop << 2) + cloop))); @@ -227,8 +373,73 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq) PK_TRACE_INF("Core[%d] Type2 Payload [%x] Type3 Payload [%x]", ((qloop << 2) + cloop), cpayload_t2, cpayload_t3); + // if not hardware pig and is an suspend ack pig + if (((~cpayload_t2) & TYPE2_PAYLOAD_HARDWARE_WAKEUP) && + (cpayload_t2 & TYPE2_PAYLOAD_SUSPEND_ACK_MASK)) + { + for(suspend_mask = TYPE2_PAYLOAD_SUSPEND_EXIT_MASK, + vector_index = VECTOR_EXIT, + suspend_index = VECTOR_BLOCKX; + suspend_index > 0; + suspend_index--, + vector_index--, + suspend_mask = suspend_mask >> 1) + { + // if entry/exit is selected for performing suspend/unsuspend operation + if (cpayload_t2 & suspend_mask) + { + // suspend entry/exit/both + if (cpayload_t2 & TYPE2_PAYLOAD_SUSPEND_OP_MASK) + { + if ((cloop >> 1) % 2) + { + G_sgpe_stop_record.group.ex_r[suspend_index] |= BIT32(qloop); + } + else + { + G_sgpe_stop_record.group.ex_l[suspend_index] |= BIT32(qloop); + } + + if((G_sgpe_stop_record.group.ex_r[suspend_index] & + G_sgpe_stop_record.group.ex_l[suspend_index] & + G_sgpe_stop_record.group.quad[suspend_index]) == + G_sgpe_stop_record.group.quad[suspend_index]) + { + out32(OCB_OCCFLG_CLR, BIT32(SGPE_IGNORE_STOP_CONTROL)); + } + } + // unsuspend entry/exit/both + else + { + if ((cloop >> 1) % 2) + { + G_sgpe_stop_record.group.ex_r[suspend_index] &= ~BIT32(qloop); + } + else + { + G_sgpe_stop_record.group.ex_l[suspend_index] &= ~BIT32(qloop); + } + + if ((G_sgpe_stop_record.group.ex_r[suspend_index] | + G_sgpe_stop_record.group.ex_l[suspend_index]) == 0) + { + G_sgpe_stop_record.group.core[vector_index] |= + G_sgpe_stop_record.group.core[suspend_index]; + G_sgpe_stop_record.group.core[suspend_index] = 0; + G_sgpe_stop_record.group.qswu[vector_index] |= + G_sgpe_stop_record.group.qswu[suspend_index]; + G_sgpe_stop_record.group.qswu[suspend_index] = 0; + out32(OCB_OCCFLG_CLR, BIT32(SGPE_IGNORE_STOP_CONTROL)); + } + } + } + } + + continue; + } + GPE_GETSCOM(GPE_SCOM_ADDR_CORE(CPPM_CPMMR, - ((qloop << 2) + cloop)), scom_data); + ((qloop << 2) + cloop)), scom_data.value); // T2 T3 NS given point to SGPE // exit exit SGPE ---- proceed with exit @@ -270,7 +481,7 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq) // if t2 entry (t3 exit or empty) else if (cpayload_t2 && (!(cpayload_t2 & TYPE2_PAYLOAD_EXIT_EVENT))) { - if (!(scom_data & BIT64(13))) + if (!(scom_data.words.upper & BIT32(13))) { // wakeup=normal + notify=cme -> error if (cpayload_t2 != 0x400) @@ -300,7 +511,7 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq) // if t3 entry (t2 exit or empty) else if (cpayload_t3 && (!(cpayload_t3 & TYPE2_PAYLOAD_EXIT_EVENT))) { - if (!(scom_data & BIT64(13))) + if (!(scom_data.words.upper & BIT32(13))) { PK_TRACE_ERR("ERROR: Received Type3 Entry PIG When Wakeup_notify_select = 0. HALT SGPE!"); PK_PANIC(SGPE_PIG_TYPE3_ENTRY_WNS_CME); @@ -315,7 +526,7 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq) // both exit or one exit + one empty else { - if (!(scom_data & BIT64(13))) + if (!(scom_data.words.upper & BIT32(13))) { if ((cpayload_t2 & TYPE2_PAYLOAD_EXIT_EVENT) && (cpayload_t3 & TYPE2_PAYLOAD_EXIT_EVENT)) @@ -332,25 +543,20 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq) { PK_TRACE_INF("Core Request Exit"); - if (cloop < CORES_PER_EX) + if (G_sgpe_stop_record.group.quad[VECTOR_BLOCKX] & BIT32(qloop)) { - G_sgpe_stop_record.group.ex_l[VECTOR_EXIT] |= - BIT32(qloop); - G_sgpe_stop_record.group.ex_b[VECTOR_EXIT] |= - BIT32((qloop << 1)); + PK_TRACE_DBG("Core is in Block Wakeup Mode, Ignore Now", cloop); + G_sgpe_stop_record.group.core[VECTOR_BLOCKX] |= + BIT32(((qloop << 2) + cloop)); } else { - G_sgpe_stop_record.group.ex_r[VECTOR_EXIT] |= + PK_TRACE_DBG("Core Considered Stopped, Will Wakeup", cloop); + G_sgpe_stop_record.group.quad[VECTOR_EXIT] |= BIT32(qloop); - G_sgpe_stop_record.group.ex_b[VECTOR_EXIT] |= - BIT32(((qloop << 1) + 1)); + G_sgpe_stop_record.group.core[VECTOR_EXIT] |= + BIT32(((qloop << 2) + cloop)); } - - G_sgpe_stop_record.group.quad[VECTOR_EXIT] |= - BIT32(qloop); - G_sgpe_stop_record.group.core[VECTOR_EXIT] |= - BIT32(((qloop << 2) + cloop)); } } } @@ -362,13 +568,6 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq) G_sgpe_stop_record.level[qloop][3]); } - G_sgpe_stop_record.group.ex_b[VECTOR_EXIT] &= - G_sgpe_stop_record.group.ex_b[VECTOR_CONFIG]; - G_sgpe_stop_record.group.ex_l[VECTOR_EXIT] &= - G_sgpe_stop_record.group.ex_l[VECTOR_CONFIG]; - G_sgpe_stop_record.group.ex_r[VECTOR_EXIT] &= - G_sgpe_stop_record.group.ex_r[VECTOR_CONFIG]; - PK_TRACE_DBG("Quad Special Wakeup: Raise[%x], Drop[%x]", G_sgpe_stop_record.group.qswu[VECTOR_EXIT], G_sgpe_stop_record.group.qswu[VECTOR_ENTRY]); @@ -402,5 +601,8 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq) G_sgpe_stop_record.wof.status_stop = STATUS_PROCESSING; pk_semaphore_post(&(G_sgpe_stop_record.sem[0])); } + + PK_TRACE("Disable ipi3_lo interrupt"); + out32(OCB_OIMR1_OR, BIT32(29)); } } |