summaryrefslogtreecommitdiffstats
path: root/src/kernel
diff options
context:
space:
mode:
authorBill Hoffa <wghoffa@us.ibm.com>2016-01-13 14:06:31 -0600
committerDaniel M. Crowell <dcrowell@us.ibm.com>2016-05-06 11:03:22 -0400
commitb42194c6063f64d59fe1c360fa4ae4edd85ad2f3 (patch)
treeb055e27081164600409203f31c3eac93f32397cb /src/kernel
parentdaf95f9b2b66313079186c2d8669ffa75155056f (diff)
downloadblackbird-hostboot-b42194c6063f64d59fe1c360fa4ae4edd85ad2f3.tar.gz
blackbird-hostboot-b42194c6063f64d59fe1c360fa4ae4edd85ad2f3.zip
Doorbell Interrupt Base Support for Core/Thread Wakeup
This change includes: - Implementation of a generic KernelWorkItem Class - Kernel functionality for doorbell send to specific PIRs - Kernel changes to send core/thread Wakeup doorbells using doorbell_send() + placing KernelWorkItems on a cpu stack obj to be executed during doorbell wakeup - Kernel Interrupt Message handler changes to send wakeup msgs - Interrupt Resource Provider (INTRRP) Changes to handle wakeup msgs and monitor for timeouts - Changes to the IPL flow to invoke proper Core/Thread Wakeup - A basic outline (commented out) for how IPC messages can be implemented in the future Change-Id: I547fb8719bac657def561565ae11ab18cde72096 CMVC-Prereq: 992722 RTC:137564 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/22815 Tested-by: Jenkins Server Tested-by: FSP CI Jenkins Reviewed-by: Andrew J. Geissler <andrewg@us.ibm.com> Reviewed-by: Prachi Gupta <pragupta@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/cpumgr.C18
-rw-r--r--src/kernel/doorbell.C48
-rw-r--r--src/kernel/intmsghandler.C28
-rw-r--r--src/kernel/ipc.C7
-rw-r--r--src/kernel/makefile1
-rw-r--r--src/kernel/misc.C10
-rw-r--r--src/kernel/syscall.C15
-rw-r--r--src/kernel/workitem.C50
8 files changed, 152 insertions, 25 deletions
diff --git a/src/kernel/cpumgr.C b/src/kernel/cpumgr.C
index 1aef65650..c1733bb7c 100644
--- a/src/kernel/cpumgr.C
+++ b/src/kernel/cpumgr.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2010,2015 */
+/* Contributors Listed Below - COPYRIGHT 2010,2016 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -45,6 +45,7 @@
#include <kernel/hbterminatetypes.H>
#include <kernel/kernel_reasoncodes.H>
#include <kernel/cpuid.H>
+#include <kernel/doorbell.H>
cpu_t** CpuManager::cv_cpus[KERNEL_MAX_SUPPORTED_NODES];
bool CpuManager::cv_shutdown_requested = false;
@@ -193,7 +194,7 @@ void CpuManager::startCPU(ssize_t i)
// Initialize CPU structure.
if (NULL == cv_cpus[nodeId][cpuId])
{
- printk("Starting CPU %ld...", i);
+ printk("Starting CPU with pir %ld...", i);
cpu_t* cpu = cv_cpus[nodeId][cpuId] = new cpu_t();
// Initialize CPU.
@@ -434,8 +435,21 @@ void CpuManager::startCore(uint64_t pir,uint64_t i_threads)
}
__sync_synchronize();
+ //Send a message to userspace that a core with this base pir is being added
+ // userspace will know which threads on the core to expect already
InterruptMsgHdlr::addCpuCore(pir);
+ for(size_t i = 0; i < threads; i++)
+ {
+ // Only wakeup the threads we were told to wakeup
+ if( i_threads & (0x8000000000000000 >> i) )
+ {
+ printk("Dbell wkup pir %ld\n", pir + i);
+ //Initiate the Doorbell for this core/pir
+ send_doorbell_wakeup(pir + i);
+ }
+ }
+
return;
};
diff --git a/src/kernel/doorbell.C b/src/kernel/doorbell.C
index 33b782bf7..4b99e7aee 100644
--- a/src/kernel/doorbell.C
+++ b/src/kernel/doorbell.C
@@ -24,11 +24,16 @@
/* IBM_PROLOG_END_TAG */
#include <stdint.h>
#include <arch/ppc.H>
+#include <kernel/task.H>
+#include <kernel/taskmgr.H>
+#include <kernel/cpu.H>
+#include <kernel/doorbell.H>
+#include <kernel/console.H>
#include <kernel/cpumgr.H>
void doorbell_clear()
{
- register uint64_t msgtype = 0x0000000028000000; /// Comes from the ISA.
+ register uint64_t msgtype = _DOORBELL_MSG_TYPE;
asm volatile("msgclr %0" :: "r" (msgtype));
return;
@@ -36,9 +41,10 @@ void doorbell_clear()
void doorbell_broadcast()
{
+ /*TODO RTC 152189
size_t threadCount = CpuManager::getThreadCount();
- uint64_t msgtype = 0x0000000028000000; /// Comes from the ISA.
+ uint64_t msgtype = _DOORBELL_MSG_TYPE;
uint64_t thread = getPIR() & (threadCount - 1);
for (size_t i = 0; i < threadCount; ++i)
{
@@ -48,4 +54,42 @@ void doorbell_broadcast()
asm volatile("msgsnd %0" :: "r" (msg));
}
}
+ **/
}
+
+void doorbell_send(uint64_t i_pir)
+{
+ uint64_t msgtype = _DOORBELL_MSG_TYPE;
+ register uint64_t msg = msgtype | i_pir;
+ asm volatile("msgsnd %0" :: "r" (msg));
+
+ return;
+}
+
+void send_doorbell_wakeup(uint64_t i_pir)
+{
+ cpu_t *l_cpu = CpuManager::getCpu(i_pir);
+
+ printkd("send_doorbell_wakeup to pir: %lx\n", i_pir);
+ //Create WorkItem and put on the stack to be executed during doorbell
+ // execution
+ KernelWorkItem* l_work = new CpuWakeupDoorbellWorkItem();
+ l_cpu->doorbell_actions.push(l_work);
+ //Send doorbell to wakeup core/thread
+ doorbell_send(i_pir);
+}
+
+/*
+TODO RTC 150861
+void send_doorbell_ipc(uint64_t i_pir)
+{
+ cpu_t *l_cpu = getCpu(i_pir)
+
+ printk("send_doorbell_ipc to pir: %lx\n", i_pir);
+ //Create WorkItem and put on the stack to be executed during doorbell
+ // execution (if needed, otherwise can likely delete and just send doorbell)
+ KernelWorkItem* l_work = new IpcDoorbellWorkItem();
+ l_cpu->doorbell_actions.push(l_work);
+ doorbell_send(i_pir)
+}
+**/
diff --git a/src/kernel/intmsghandler.C b/src/kernel/intmsghandler.C
index 10c1dcfd8..301be0f05 100644
--- a/src/kernel/intmsghandler.C
+++ b/src/kernel/intmsghandler.C
@@ -113,7 +113,7 @@ void InterruptMsgHdlr::handleInterrupt()
}
else
{
- printk("InterrurptMsgHdlr got called before IPC was setup\n");
+ printk("InterruptMsgHdlr got called before IPC was setup\n");
// The INTR mmio base address is not yet available via the attributes.
// If we get here during an MPIPL then the BAR value could be read
// from the ICP BAR SCOM register, however, since this value will
@@ -165,28 +165,30 @@ void InterruptMsgHdlr::addCpuCore(uint64_t i_pir)
{
// To avoid conflict with interrupts on thread i_pir, change the key
// for the message to be an invalid PIR.
- uint64_t pir_key = i_pir | 0x8000000000000000ul;
+ uint64_t pir_key = i_pir | 0x4000000000000000ul;
cv_instance->iv_lock.lock();
cv_instance->sendMessage(MSG_INTR_ADD_CPU,
(void*)pir_key,(void *)i_pir,t);
cv_instance->iv_lock.unlock();
+ printkd("InterruptMsgHdlr::addCpuCore MSG_INTR_ADD_CPU message "
+ "sent for pir: %lx\n", i_pir);
}
}
-void InterruptMsgHdlr::sendIPI(uint64_t i_pir, uint8_t i_favor)
+void InterruptMsgHdlr::sendThreadWakeupMsg(uint64_t i_pir)
{
- uint64_t mfrrAddress = cv_ipc_base_address;
- mfrrAddress += mmio_offset(i_pir);
- mfrrAddress += MFRR_ADDR_OFFSET;
-
- mfrrAddress |= 0x8000000000000000ul;
-
- register uint8_t data = i_favor;
+ if(cv_instance)
+ {
+ // To avoid conflict with interrupts on thread i_pir, change the key
+ // for the message to be an invalid PIR.
+ uint64_t pir_key = i_pir | 0x8000000000000000ul;
- eieio(); sync();
- MAGIC_INSTRUCTION(MAGIC_SIMICS_CORESTATESAVE);
- asm volatile("stbcix %0,0,%1" :: "r" (data) , "r" (mfrrAddress));
+ cv_instance->iv_lock.lock();
+ cv_instance->sendMessage(MSG_INTR_CPU_WAKEUP,
+ (void*)pir_key,(void *)i_pir,NULL);
+ cv_instance->iv_lock.unlock();
+ }
}
MessageHandler::HandleResult InterruptMsgHdlr::handleResponse
diff --git a/src/kernel/ipc.C b/src/kernel/ipc.C
index 9f0eaa908..e7a9ead9a 100644
--- a/src/kernel/ipc.C
+++ b/src/kernel/ipc.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2015 */
+/* Contributors Listed Below - COPYRIGHT 2013,2016 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -87,8 +87,11 @@ int KernelIpc::send(uint64_t i_q, msg_t * i_msg)
printkd("IPC send from PIR %lx to PIR %x\n",getPIR(),p_dest->pir);
+ /* TODO RTC 150861
// send IPI - use this_node + 10 as favor level of interrupt
- InterruptMsgHdlr::sendIPI(p_dest->pir,this_node + 0x10);
+ //P8 Call: InterruptMsgHdlr::sendIPI(p_dest->pir,this_node + 0x10);
+ //P9 Call (likely): send_doorbell_ipc(p_dest->pir);
+ **/
// The message allocation is freed here to make msg_send for IPC
// messages behave the same as non-IPC msg_send; that is, the message
diff --git a/src/kernel/makefile b/src/kernel/makefile
index ea9666b44..cf5a69aa7 100644
--- a/src/kernel/makefile
+++ b/src/kernel/makefile
@@ -65,6 +65,7 @@ OBJS += ipc.o
OBJS += machchk.o
OBJS += doorbell.o
+OBJS += workitem.o
include ${ROOTPATH}/config.mk
diff --git a/src/kernel/misc.C b/src/kernel/misc.C
index 080c0adf3..3b25ae705 100644
--- a/src/kernel/misc.C
+++ b/src/kernel/misc.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2015 */
+/* Contributors Listed Below - COPYRIGHT 2011,2016 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -41,7 +41,7 @@
#include <kernel/ipc.H>
#include <kernel/timemgr.H>
#include <util/singleton.H>
-
+#include <kernel/doorbell.H>
extern "C"
void kernel_shutdown(size_t, uint64_t, uint64_t, uint64_t,
@@ -340,8 +340,10 @@ namespace KernelMisc
//Issue sbe master workaround
InterruptMsgHdlr::issueSbeMboxWA();
+
// NOTE: The cpu_t structures for theads 1:3 were created
// during init (CpuManager::init).
+ //
#ifdef HOSTBOOT_REAL_WINKLE
// @todo- RTC 141924 Start the other threads 1:3 in a new manner
@@ -349,6 +351,7 @@ namespace KernelMisc
// Maybe something like: sendIPI(..) or addCpuCore(..)
// Need interrupt code in place for this.
+
#else
// get other 3 threads going in SIMICs for now
MAGIC_INSTRUCTION(MAGIC_WAKE_OTHER_THREADS);
@@ -371,6 +374,7 @@ namespace KernelMisc
// get new core going in SIMICS
MAGIC_INSTRUCTION(MAGIC_WAKE_FUSED_THREADS);
#endif
+
} // end if fused core mode
}
@@ -440,7 +444,7 @@ namespace KernelMisc
{
if (slave->winkled)
{
- InterruptMsgHdlr::sendIPI(i);
+ InterruptMsgHdlr::sendThreadWakeupMsg(i);
}
}
}
diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C
index d7e729d80..6f087f021 100644
--- a/src/kernel/syscall.C
+++ b/src/kernel/syscall.C
@@ -55,6 +55,17 @@ extern "C"
void kernel_execute_hype_doorbell()
{
task_t* t = TaskManager::getCurrentTask();
+ doorbell_clear();
+
+ //Execute all work items on doorbell_actions stack
+ KernelWorkItem *l_work = t->cpu->doorbell_actions.pop();
+ while(l_work != NULL)
+ {
+ //Execute Work Item and then delete it
+ (*l_work)();
+ delete l_work;
+ l_work = t->cpu->doorbell_actions.pop();
+ }
if (t->cpu->idle_task == t)
{
@@ -63,8 +74,6 @@ void kernel_execute_hype_doorbell()
}
DeferredQueue::execute();
-
- doorbell_clear();
}
extern "C"
@@ -401,7 +410,7 @@ namespace Systemcalls
if (m->type >= MSG_FIRST_SYS_TYPE)
{
- printkd("Invalid message type for msg_sendrecv, type=%d.\n",
+ printk("Invalid message type for msg_sendrecv, type=%d.\n",
m->type);
TASK_SETRTN(t, -EINVAL);
return;
diff --git a/src/kernel/workitem.C b/src/kernel/workitem.C
new file mode 100644
index 000000000..a883cdb8f
--- /dev/null
+++ b/src/kernel/workitem.C
@@ -0,0 +1,50 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/kernel/workitem.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#include <arch/ppc.H>
+#include <kernel/workitem.H>
+#include <kernel/console.H>
+#include <kernel/intmsghandler.H>
+
+//Define the desired behavior for a CPU core/thread
+// wakeup scenario
+void CpuWakeupDoorbellWorkItem::operator() (void)
+{
+ size_t pir = getPIR();
+ printk("Wkup pir %ld done\n", pir);
+ //Send message to the intrrp in userspace indicating this pir has woken up
+ // There is a task associated with the intrrp that monitors that the proper
+ // cores/threads have woken up
+ InterruptMsgHdlr::sendThreadWakeupMsg(pir);
+ return;
+}
+
+/*TODO RTC 150861
+void IpcDoorbellWorkItem::operator() (void)
+{
+ //Decide what needs to be done when the Ipc Doorbell is received
+ // (if anything)
+}
+**/
OpenPOWER on IntegriCloud