summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/kernel/doorbell.H41
-rw-r--r--src/kernel/deferred.C4
-rw-r--r--src/kernel/doorbell.C51
-rw-r--r--src/kernel/futexmgr.C10
-rw-r--r--src/kernel/makefile6
-rw-r--r--src/kernel/msghandler.C3
-rw-r--r--src/kernel/start.S26
-rw-r--r--src/kernel/syscall.C25
-rw-r--r--src/kernel/timemgr.C6
-rw-r--r--src/makefile1
10 files changed, 168 insertions, 5 deletions
diff --git a/src/include/kernel/doorbell.H b/src/include/kernel/doorbell.H
new file mode 100644
index 000000000..d0c65be2c
--- /dev/null
+++ b/src/include/kernel/doorbell.H
@@ -0,0 +1,41 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/include/kernel/doorbell.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,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 */
+#ifndef __KERNEL_DOORBELL_H
+#define __KERNEL_DOORBELL_H
+
+/** doorbell_broadcast
+ *
+ * Broadcast a doorbell exception to all threads on the same core.
+ */
+void doorbell_broadcast();
+
+/** doorbell_clear
+ *
+ * Clears a pending doorbell from the executing thread, so that the
+ * exception is no longer asserted.
+ */
+void doorbell_clear();
+
+#endif
diff --git a/src/kernel/deferred.C b/src/kernel/deferred.C
index af8a10189..6888fd646 100644
--- a/src/kernel/deferred.C
+++ b/src/kernel/deferred.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2012,2014 */
+/* Contributors Listed Below - COPYRIGHT 2012,2016 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -24,6 +24,7 @@
/* IBM_PROLOG_END_TAG */
#include <kernel/deferred.H>
#include <kernel/cpumgr.H>
+#include <kernel/doorbell.H>
#include <util/singleton.H>
#include <assert.h>
#include <arch/ppc.H>
@@ -228,6 +229,7 @@ void DeferredWork::start()
void DeferredWork::_waitForCpus()
{
+ doorbell_broadcast();
iv_barrier.wait();
}
diff --git a/src/kernel/doorbell.C b/src/kernel/doorbell.C
new file mode 100644
index 000000000..33b782bf7
--- /dev/null
+++ b/src/kernel/doorbell.C
@@ -0,0 +1,51 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/kernel/doorbell.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,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 <stdint.h>
+#include <arch/ppc.H>
+#include <kernel/cpumgr.H>
+
+void doorbell_clear()
+{
+ register uint64_t msgtype = 0x0000000028000000; /// Comes from the ISA.
+ asm volatile("msgclr %0" :: "r" (msgtype));
+
+ return;
+}
+
+void doorbell_broadcast()
+{
+ size_t threadCount = CpuManager::getThreadCount();
+
+ uint64_t msgtype = 0x0000000028000000; /// Comes from the ISA.
+ uint64_t thread = getPIR() & (threadCount - 1);
+ for (size_t i = 0; i < threadCount; ++i)
+ {
+ if (i != thread)
+ {
+ register uint64_t msg = msgtype | i;
+ asm volatile("msgsnd %0" :: "r" (msg));
+ }
+ }
+}
diff --git a/src/kernel/futexmgr.C b/src/kernel/futexmgr.C
index f9146a414..0c378ea24 100644
--- a/src/kernel/futexmgr.C
+++ b/src/kernel/futexmgr.C
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2011,2014 */
+/* Contributors Listed Below - COPYRIGHT 2011,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. */
@@ -31,7 +33,7 @@
#include <kernel/scheduler.H>
#include <kernel/futexmgr.H>
#include <util/singleton.H>
-
+#include <kernel/doorbell.H>
//-----------------------------------------------------------------------------
@@ -145,6 +147,10 @@ uint64_t FutexManager::_wake(uint64_t * i_futex1, uint64_t i_count1,
}
}
+ if(started)
+ {
+ doorbell_broadcast();
+ }
iv_lock.unlock();
diff --git a/src/kernel/makefile b/src/kernel/makefile
index 39e3f11dd..ea9666b44 100644
--- a/src/kernel/makefile
+++ b/src/kernel/makefile
@@ -5,7 +5,9 @@
#
# OpenPOWER HostBoot Project
#
-# COPYRIGHT International Business Machines Corp. 2010,2014
+# Contributors Listed Below - COPYRIGHT 2010,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.
@@ -62,5 +64,7 @@ OBJS += terminate.o
OBJS += ipc.o
OBJS += machchk.o
+OBJS += doorbell.o
+
include ${ROOTPATH}/config.mk
diff --git a/src/kernel/msghandler.C b/src/kernel/msghandler.C
index cb051eb88..46bad32fb 100644
--- a/src/kernel/msghandler.C
+++ b/src/kernel/msghandler.C
@@ -31,6 +31,7 @@
#include <kernel/scheduler.H>
#include <kernel/taskmgr.H>
#include <kernel/console.H>
+#include <kernel/doorbell.H>
void MessageHandler::sendMessage(msg_sys_types_t i_type, void* i_key,
void* i_data, task_t* i_task)
@@ -108,6 +109,7 @@ void MessageHandler::sendMessage(msg_sys_types_t i_type, void* i_key,
current->cpu->scheduler->addTask(current);
TaskManager::setCurrentTask(ready_task);
ready_task = NULL;
+ doorbell_broadcast();
}
// Insert pending info into our queue until response is recv'd.
@@ -169,6 +171,7 @@ int MessageHandler::recvMessage(msg_t* i_msg)
else // Add other deferred tasks to scheduler ready queue.
{
deferred_task->cpu->scheduler->addTask(deferred_task);
+ doorbell_broadcast();
}
}
else if (UNHANDLED_RC == rc)
diff --git a/src/kernel/start.S b/src/kernel/start.S
index 5d30ed15d..f9b5a95ce 100644
--- a/src/kernel/start.S
+++ b/src/kernel/start.S
@@ -208,7 +208,17 @@ UNIMPL_INTERRUPT_STUB(hype_data_storage, 0xE00)
UNIMPL_INTERRUPT_STUB(hype_inst_storage, 0xE20)
STD_INTERRUPT_STUB(hype_emu_assist, 0xE40)
UNIMPL_INTERRUPT_STUB(hype_maint, 0xE60)
+
+;// Hypervisor Doorbell Exception Vector
+;//
+;// There isn't enough room here for a "normal" stub, so jump out to 'stub2'
+;// where there is some space.
+.org _start + 0xE80
+intvect_syscall_hype_doorbell_stub:
+ b intvect_syscall_hype_doorbell_stub2
+
STD_INTERRUPT_STUB(hypervisor_external, 0xEA0)
+
UNIMPL_INTERRUPT_STUB(perf_monitor, 0xF00)
UNIMPL_INTERRUPT_STUB(vector_unavail, 0xF20)
UNIMPL_INTERRUPT_STUB(vsx_unavail, 0xF40)
@@ -877,6 +887,22 @@ UNIMPL_INTERRUPT_NOADDR(trace, 0xD00)
UNIMPL_INTERRUPT_NOADDR(hype_data_storage, 0xE00)
UNIMPL_INTERRUPT_NOADDR(hype_inst_storage, 0xE20)
UNIMPL_INTERRUPT_NOADDR(hype_maint, 0xE60)
+
+;// Hypervisor Doorbell Exception (part 2).
+;//
+;// Doorbells come in with the HSSR[01] registers, since they are Hypervisor
+;// exceptions, instead of the SRR[01] registers that the normal exception
+;// code deals with. Copy the contents of HSSR[01] -> SRR[01] first.
+;//
+intvect_syscall_hype_doorbell_stub2:
+ mtsprg0 r1
+ mfspr r1,HSRR0
+ mtsrr0 r1
+ mfspr r1,HSRR1
+ mtsrr1 r1
+ mfsprg0 r1
+STD_INTERRUPT_NOADDR(hype_doorbell)
+
UNIMPL_INTERRUPT_NOADDR(perf_monitor, 0xF00)
UNIMPL_INTERRUPT_NOADDR(vector_unavail, 0xF20)
UNIMPL_INTERRUPT_NOADDR(vsx_unavail, 0xF40)
diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C
index fe59ea0c3..d7e729d80 100644
--- a/src/kernel/syscall.C
+++ b/src/kernel/syscall.C
@@ -42,6 +42,7 @@
#include <kernel/stacksegment.H>
#include <kernel/heapmgr.H>
#include <kernel/intmsghandler.H>
+#include <kernel/doorbell.H>
#include <sys/sync.h>
#include <errno.h>
@@ -51,6 +52,22 @@ namespace KernelIpc
};
extern "C"
+void kernel_execute_hype_doorbell()
+{
+ task_t* t = TaskManager::getCurrentTask();
+
+ if (t->cpu->idle_task == t)
+ {
+ t->cpu->scheduler->returnRunnable();
+ t->cpu->scheduler->setNextRunnable();
+ }
+
+ DeferredQueue::execute();
+
+ doorbell_clear();
+}
+
+extern "C"
void kernel_execute_decrementer()
{
cpu_t* c = CpuManager::getCurrentCPU();
@@ -188,6 +205,8 @@ namespace Systemcalls
t->cpu->scheduler->addTask(newTask);
TASK_SETRTN(t, newTask->tid);
+
+ doorbell_broadcast();
}
void TaskEnd(task_t* t)
@@ -210,6 +229,7 @@ namespace Systemcalls
// Move task to master CPU and pick a new task.
t->cpu->scheduler->addTaskMasterCPU(t);
t->cpu->scheduler->setNextRunnable();
+ doorbell_broadcast();
}
void TaskWait(task_t* t)
@@ -359,6 +379,7 @@ namespace Systemcalls
{
TASK_SETRTN(waiter, (uint64_t) m);
waiter->cpu->scheduler->addTask(waiter);
+ doorbell_broadcast();
}
mq->lock.unlock();
@@ -424,6 +445,7 @@ namespace Systemcalls
// back to scheduler.
{
t->cpu->scheduler->addTask(t);
+ doorbell_broadcast();
}
TaskManager::setCurrentTask(waiter);
}
@@ -455,6 +477,7 @@ namespace Systemcalls
if (TaskManager::getCurrentTask() != t)
{
t->cpu->scheduler->addTask(t);
+ doorbell_broadcast();
}
}
// Pseudo-sync messages are handled by pushing the response onto
@@ -477,6 +500,7 @@ namespace Systemcalls
{
TASK_SETRTN(client, (uint64_t) m);
client->cpu->scheduler->addTask(client);
+ doorbell_broadcast();
}
mq2->lock.unlock();
@@ -492,6 +516,7 @@ namespace Systemcalls
TASK_SETRTN(t,0);
t->cpu->scheduler->addTask(t);
+ doorbell_broadcast();
}
}
else
diff --git a/src/kernel/timemgr.C b/src/kernel/timemgr.C
index a1984e661..e5759a61b 100644
--- a/src/kernel/timemgr.C
+++ b/src/kernel/timemgr.C
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2010,2014 */
+/* Contributors Listed Below - COPYRIGHT 2010,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. */
@@ -28,6 +30,7 @@
#include <util/misc.H>
#include <kernel/misc.H>
#include <sys/task.h>
+#include <kernel/doorbell.H>
uint64_t TimeManager::iv_timebaseFreq = 0xFFFFFFFF;
@@ -107,6 +110,7 @@ void TimeManager::_checkReleaseTasks(Scheduler* s)
{
s->addTask(node->task);
delete node;
+ doorbell_broadcast();
}
}
diff --git a/src/makefile b/src/makefile
index cf362a85b..143231e53 100644
--- a/src/makefile
+++ b/src/makefile
@@ -73,6 +73,7 @@ DIRECT_BOOT_OBJECTS += kernel.o
DIRECT_BOOT_OBJECTS += taskmgr.o
DIRECT_BOOT_OBJECTS += cpumgr.o
DIRECT_BOOT_OBJECTS += syscall.o
+DIRECT_BOOT_OBJECTS += doorbell.o
DIRECT_BOOT_OBJECTS += scheduler.o
DIRECT_BOOT_OBJECTS += exception.o
DIRECT_BOOT_OBJECTS += vmmmgr.o
OpenPOWER on IntegriCloud