diff options
-rw-r--r-- | src/include/kernel/doorbell.H | 41 | ||||
-rw-r--r-- | src/kernel/deferred.C | 4 | ||||
-rw-r--r-- | src/kernel/doorbell.C | 51 | ||||
-rw-r--r-- | src/kernel/futexmgr.C | 10 | ||||
-rw-r--r-- | src/kernel/makefile | 6 | ||||
-rw-r--r-- | src/kernel/msghandler.C | 3 | ||||
-rw-r--r-- | src/kernel/start.S | 26 | ||||
-rw-r--r-- | src/kernel/syscall.C | 25 | ||||
-rw-r--r-- | src/kernel/timemgr.C | 6 | ||||
-rw-r--r-- | src/makefile | 1 |
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 |