diff options
Diffstat (limited to 'src/usr/intr/intrrp.C')
-rw-r--r-- | src/usr/intr/intrrp.C | 200 |
1 files changed, 96 insertions, 104 deletions
diff --git a/src/usr/intr/intrrp.C b/src/usr/intr/intrrp.C index e4abde595..91bca3c11 100644 --- a/src/usr/intr/intrrp.C +++ b/src/usr/intr/intrrp.C @@ -180,7 +180,10 @@ errlHndl_t IntrRp::_init() // so unmask those interrupts l_err = unmaskInterruptSource(LSI_PSU); - + //Set value for enabled threads + uint64_t l_en_threads = get_enabled_threads(); + TRACDCOMP(g_trac_intr, "IntrRp::_init() Threads enabled:" + " %lx", l_en_threads); } while(0); return l_err; @@ -421,11 +424,7 @@ void IntrRp::msgHandler() uint64_t l_data0 = (l_xirr_pir & 0xFFFFFFFF); PIR_t pir = static_cast<PIR_t>(l_data0); - uint64_t baseAddr = iv_baseAddr + cpuOffsetAddr(pir); - uint32_t * xirrAddress = - reinterpret_cast<uint32_t*>(baseAddr + XIRR_OFFSET); - - TRACFCOMP(g_trac_intr, + TRACDCOMP(g_trac_intr, "External Interrupt received. XIRR=%x, PIR=%x", xirr,pir.word); //An external interrupt comes from two paths @@ -467,15 +466,6 @@ void IntrRp::msgHandler() (uint32_t) type, rc); } } - else if (type == INTERPROC_XISR) - { - // Ignore "spurious" IPIs (handled below). - - // Note that we could get an INTERPROC interrupt - // and handle it through the above registration list - // as well. This is to catch the case where no one - // has registered for an IPI. - } else if (type == LSI_PSU) { TRACDCOMP(g_trac_intr, "PSU Interrupt Detected"); @@ -490,89 +480,78 @@ void IntrRp::msgHandler() "Ignoring it.", (uint32_t)type); } + } + break; - // Handle IPIs special since they're used for waking up - // cores and have special clearing requirements. - if (type == INTERPROC_XISR) - { - // Clear IPI request. - volatile uint8_t * mfrr = - reinterpret_cast<uint8_t*>(baseAddr + MFRR_OFFSET); + case MSG_INTR_CPU_WAKEUP: + { + uint64_t l_xirr_pir = msg->data[0]; + uint64_t l_data0 = (l_xirr_pir & 0xFFFFFFFF); + PIR_t l_pir = static_cast<PIR_t>(l_data0); + PIR_t l_core_pir = l_pir; + l_core_pir.threadId = 0; - TRACFCOMP( g_trac_intr,"mfrr = %x",*mfrr); + if (iv_ipisPending.count(l_core_pir)) + { + TRACFCOMP(g_trac_intr,INFO_MRK + "IntrRp::msgHandler Doorbell wakeup received" + " for %d", l_pir.word); - (*mfrr) = 0xff; - eieio(); // Force mfrr clear before xirr EIO. + IPI_Info_t& ipiInfo = iv_ipisPending[l_core_pir]; + ipiInfo.first &= + ~(0x8000000000000000 >> l_pir.threadId); - // Deal with pending IPIs. - PIR_t core_pir = pir; core_pir.threadId = 0; - if (iv_ipisPending.count(core_pir)) + if (0 == ipiInfo.first) { - TRACFCOMP(g_trac_intr,INFO_MRK - "IPI wakeup received for %d", pir.word); - - IPI_Info_t& ipiInfo = iv_ipisPending[core_pir]; - - ipiInfo.first &= - ~(0x8000000000000000 >> pir.threadId); - - if (0 == ipiInfo.first) - { - msg_t* ipiMsg = ipiInfo.second; - iv_ipisPending.erase(core_pir); - - ipiMsg->data[1] = 0; - msg_respond(iv_msgQ, ipiMsg); - } - else - { - TRACDCOMP(g_trac_intr,INFO_MRK - "IPI still pending for %x", - ipiInfo.first); - } + msg_t* ipiMsg = ipiInfo.second; + iv_ipisPending.erase(l_core_pir); + ipiMsg->data[1] = 0; + msg_respond(iv_msgQ, ipiMsg); } - - // Writing the XIRR with the same value read earlier - // to signal an EOI. - xirr |= CPPR_MASK; //set all CPPR bits - allow any INTR - *xirrAddress = xirr; - - TRACDCOMP(g_trac_intr, - "EOI issued. XIRR=%x, PIR=%x", - xirr,pir); - - // Now handle any IPC messages - // If something is registered for IPIs - // and msg is ready, then handle - if(r != iv_registry.end() && - (KernelIpc::ipc_data_area.msg_queue_id != - IPC_DATA_AREA_CLEAR) && - (KernelIpc::ipc_data_area.msg_queue_id != - IPC_DATA_AREA_LOCKED)) + else { - msg_q_t msgQ = r->second.msgQ; - - msg_t * rmsg = msg_allocate(); - rmsg->type = r->second.msgType; - rmsg->data[0] = type; // interrupt type - rmsg->data[1] = l_xirr_pir; - rmsg->extra_data = NULL; - - int rc = msg_sendrecv_noblk(msgQ, rmsg, iv_msgQ); - if(rc) - { - TRACFCOMP(g_trac_intr,ERR_MRK - "IPI Interrupt received, but could " - "not send message to the registered " - "handler. Ignoring it. rc = %d", - rc); - } + TRACFCOMP(g_trac_intr,INFO_MRK + "IPI still pending for %x", + ipiInfo.first); } + } } break; +/*TODO RTC 150861 -- I think a new IPC message type needs to be defined. + * And the code below should be executed when this new message + * type is received. The Kernel will send this message to + * here (this intrrp code) during doorbell wakeup. + + // Now handle any IPC messages + // If something is registered for IPIs + // and msg is ready, then handle + if(r != iv_registry.end() && + (KernelIpc::ipc_data_area.msg_queue_id != + IPC_DATA_AREA_CLEAR) && + (KernelIpc::ipc_data_area.msg_queue_id != + IPC_DATA_AREA_LOCKED)) + { + msg_q_t msgQ = r->second.msgQ; + msg_t * rmsg = msg_allocate(); + rmsg->type = r->second.msgType; + rmsg->data[0] = type; // interrupt type + rmsg->data[1] = l_xirr_pir; + rmsg->extra_data = NULL; + + int rc = msg_sendrecv_noblk(msgQ, rmsg, iv_msgQ); + if(rc) + { + TRACFCOMP(g_trac_intr,ERR_MRK + "IPI Interrupt received, but could " + "not send message to the registered " + "handler. Ignoring it. rc = %d", + rc); + } + } +**/ case MSG_INTR_EOI: { // Use standrard EOI (End of Interrupt) sequence @@ -662,13 +641,16 @@ void IntrRp::msgHandler() } break; -#ifdef CONFIG_ENABLE_P9_IPI // Called when a new cpu becomes active other than the master // Expect a call for each new core case MSG_INTR_ADD_CPU: { + //Get the base PIR sent from the kernel PIR_t pir = msg->data[1]; + //No need to care about thread ID as that will be gathered + // below pir.threadId = 0; + //Push back base core PIR for later use iv_cpuList.push_back(pir); TRACFCOMP(g_trac_intr,"Add CPU group[%d], chip[%d]," @@ -676,40 +658,31 @@ void IntrRp::msgHandler() pir.groupId, pir.chipId, pir.coreId, pir.threadId); - size_t threads = cpu_thread_count(); + //Get threads to be enabled so they will be monitored uint64_t en_threads = get_enabled_threads(); - iv_ipisPending[pir] = IPI_Info_t(en_threads, msg); - for(size_t thread = 0; thread < threads; ++thread) - { - // Skip threads that we shouldn't be starting - if( !(en_threads & (0x8000000000000000>>thread)) ) - { - TRACDCOMP(g_trac_intr,"MSG_INTR_ADD_CPU: Skipping thread %d",thread); - continue; - } - pir.threadId = thread; - //wh_p9 initInterruptPresenter(pir); - sendIPI(pir); - } - - pir.threadId = 0; + //Create handleCpuTimeout task - this task will monitor + // for wakeup messages from each individual expected + // thread to be sent. task_create(handleCpuTimeout, reinterpret_cast<void*>(pir.word)); + TRACFCOMP(g_trac_intr, "handleCpuTimeout task started" + " responding to kernel message"); } break; -#endif case MSG_INTR_ADD_CPU_TIMEOUT: { PIR_t pir = msg->data[0]; + TRACDCOMP("IntrRp::msgHandler() CPU Timeout Message " + "received for: %x", pir.word); size_t count = msg->data[1]; if(iv_ipisPending.count(pir)) { if (count < CPU_WAKEUP_INTERVAL_COUNT) { - TRACDCOMP(g_trac_intr, + TRACFCOMP(g_trac_intr, INFO_MRK "Cpu wakeup pending on %x", pir.word); @@ -2768,6 +2741,8 @@ void* INTR::IntrRp::handleCpuTimeout(void* _pir) msg->data[0] = pir; msg_q_t intr_msgQ = msg_q_resolve(VFS_ROOT_MSG_INTR); + TRACFCOMP( g_trac_intr,"handleCpuTimeout for pir: %lx", pir); + do { // Sleep for the right amount. @@ -2838,3 +2813,20 @@ void INTR::drainQueue() } //else no queue, no need to do anything } + +uint64_t INTR::get_enabled_threads( void ) +{ + TARGETING::Target* sys = NULL; + TARGETING::targetService().getTopLevelTarget(sys); + assert( sys != NULL ); + uint64_t en_threads = sys->getAttr<TARGETING::ATTR_ENABLED_THREADS>(); + if( en_threads == 0 ) + { + //TODO RTC 151022 + //Read <SBE memory area> for enabled threads value + // and set attribute appropriately + en_threads = 0xF000000000000000; //Enable all the threads + sys->setAttr<TARGETING::ATTR_ENABLED_THREADS>(en_threads); + } + return en_threads; +} |