summaryrefslogtreecommitdiffstats
path: root/src/kernel
diff options
context:
space:
mode:
authorDoug Gilbert <dgilbert@us.ibm.com>2011-11-04 12:12:01 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-01-05 11:06:04 -0600
commit7de0708eac63bb81786c2a5e794c5d6fbef069c4 (patch)
treeb47aeb4c9827851d61b44d5cb922704f73257693 /src/kernel
parent048789fdce6b406de3b7149f8171afd63eea1829 (diff)
downloadtalos-hostboot-7de0708eac63bb81786c2a5e794c5d6fbef069c4.tar.gz
talos-hostboot-7de0708eac63bb81786c2a5e794c5d6fbef069c4.zip
Interrupt presenter implementation
Change-Id: If6b499d819b71298b8a64e096e1eb83c639ad645 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/517 Tested-by: Jenkins Server Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/exception.C13
-rw-r--r--src/kernel/intmsghandler.C125
-rw-r--r--src/kernel/makefile2
-rw-r--r--src/kernel/start.S2
-rw-r--r--src/kernel/syscall.C43
5 files changed, 177 insertions, 8 deletions
diff --git a/src/kernel/exception.C b/src/kernel/exception.C
index 863743f06..6ce01bc96 100644
--- a/src/kernel/exception.C
+++ b/src/kernel/exception.C
@@ -28,6 +28,7 @@
#include <arch/ppc.H>
#include <kernel/vmmmgr.H>
#include <kernel/cpuid.H>
+#include <kernel/intmsghandler.H>
namespace ExceptionHandles
{
@@ -221,6 +222,16 @@ void kernel_execute_machine_check()
"\tSRR0 = %lx, SRR1 = %lx\n"
"\tDSISR = %lx, DAR = %lx\n",
t->tid, getPIR(),
- getSRR0(), getSRR0(), getDSISR(), getDAR());
+ getSRR0(), getSRR1(), getDSISR(), getDAR());
kassert(false);
}
+
+extern "C"
+void kernel_execute_external()
+{
+ // SRR0 set to the effective addr the thread
+ // would have attempted to execute next
+ // SRR1 [33:36,42:47] set to zero
+ // all others copied from MSR
+ InterruptMsgHdlr::handleInterrupt();
+}
diff --git a/src/kernel/intmsghandler.C b/src/kernel/intmsghandler.C
new file mode 100644
index 000000000..b7b86c2f5
--- /dev/null
+++ b/src/kernel/intmsghandler.C
@@ -0,0 +1,125 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/kernel/intmsghandler.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2011
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#include <kernel/intmsghandler.H>
+#include <sys/msg.h>
+#include <util/singleton.H>
+#include <kernel/console.H>
+#include <sys/interrupt.h>
+#include <util/lockfree/atomic_construct.H>
+
+const char* INTR_MSGQ = "/msg/interrupt";
+
+InterruptMsgHdlr * InterruptMsgHdlr::cv_instance = NULL;
+
+
+void InterruptMsgHdlr::create(MessageQueue * i_msgQ)
+{
+ if(cv_instance)
+ {
+ // TODO should this be considered an unrecoverable error?
+ // i_msgQ has already been changed by the syscall, so we either have to
+ // make a new InterrupMsgHdlr object to match the new queue or we halt
+ // the system.
+ printk("WARNING replacing existing Interrupt handler!\n");
+
+ InterruptMsgHdlr* instance = cv_instance;
+ while(instance != NULL)
+ {
+ if(__sync_bool_compare_and_swap(&cv_instance, instance, NULL))
+ {
+ delete instance;
+ }
+ instance = cv_instance;
+ }
+ }
+
+ // Atomically construct.
+ if (__sync_bool_compare_and_swap(&cv_instance, NULL, NULL))
+ {
+ InterruptMsgHdlr* instance = new InterruptMsgHdlr(i_msgQ);
+ if (!__sync_bool_compare_and_swap(&cv_instance, NULL, instance))
+ {
+ delete instance;
+ }
+ }
+}
+
+
+void InterruptMsgHdlr::handleInterrupt()
+{
+
+ // TODO will this always be processor 0 core 0 thread 0?
+ // Need a way to pass this addr down from user code?
+ uint64_t xirrAddress = (static_cast<uint64_t>(ICPBAR_VAL) << 20) + 4;
+
+ // Ignore HRMOR setting
+ xirrAddress |= 0x8000000000000000ul;
+
+ uint32_t xirr = 0;
+ printkd ("XirrAddr %lx\n",xirrAddress);
+
+ // Reading this register acknowledges the interrupt and deactivates the
+ // external interrupt signal to the processor. The XIRR is now locked
+ // and can't be pre-empted by a "more favored" interrupt.
+ // This is a cache-inhibited load from hypervisor state.
+ // lwzcix BOP1,Ref_G0,BOP2
+ asm volatile("lwzcix %0, 0, %1"
+ : "=r" (xirr) // output, %0
+ : "r" (xirrAddress) // input, %1
+ : ); // no impacts
+
+ if(cv_instance)
+ {
+ cv_instance->sendMessage(MSG_INTR_EXTERN,
+ (void *)xirr,
+ NULL,
+ NULL);
+ }
+
+ // else we got an external interrupt before we got things set up.
+ // TODO Is there anything that can be done other than
+ // leave the interrupt presenter locked.
+ // Does the code that sets up the IP registers need to check to see if
+ // there is an interrupt sitting there and send an EOI?
+}
+
+
+void InterruptMsgHdlr::addCpuCore(uint64_t i_pir)
+{
+ if(cv_instance)
+ {
+ cv_instance->sendMessage(MSG_INTR_ADD_CPU,(void *)i_pir,NULL,NULL);
+ }
+}
+
+MessageHandler::HandleResult InterruptMsgHdlr::handleResponse
+(
+ msg_sys_types_t i_type,
+ void* i_key,
+ task_t* i_task,
+ int i_rc
+ )
+{
+ return UNHANDLED_RC;
+}
+
diff --git a/src/kernel/makefile b/src/kernel/makefile
index 05c15115a..06c7536be 100644
--- a/src/kernel/makefile
+++ b/src/kernel/makefile
@@ -26,7 +26,7 @@ OBJS = start.o kernel.o console.o pagemgr.o heapmgr.o taskmgr.o cpumgr.o
OBJS += syscall.o scheduler.o spinlock.o exception.o vmmmgr.o timemgr.o
OBJS += futexmgr.o ptmgr.o segmentmgr.o devicesegment.o basesegment.o
OBJS += block.o cpuid.o misc.o msghandler.o blockmsghdlr.o stacksegment.o
-OBJS += softpatch_p7.o barrier.o idebug.o
+OBJS += softpatch_p7.o barrier.o idebug.o intmsghandler.o
include ${ROOTPATH}/config.mk
diff --git a/src/kernel/start.S b/src/kernel/start.S
index 71f3b6db9..bcb770a58 100644
--- a/src/kernel/start.S
+++ b/src/kernel/start.S
@@ -151,7 +151,7 @@ STD_INTERRUPT(data_storage, 0x300)
STD_INTERRUPT(data_segment, 0x380)
STD_INTERRUPT(inst_storage, 0x400)
STD_INTERRUPT(inst_segment, 0x480)
-UNIMPL_INTERRUPT(external, 0x500)
+STD_INTERRUPT(external, 0x500)
STD_INTERRUPT(alignment, 0x600)
STD_INTERRUPT(prog_ex, 0x700)
STD_INTERRUPT(fp_unavail, 0x800)
diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C
index 013ffc78c..561218b00 100644
--- a/src/kernel/syscall.C
+++ b/src/kernel/syscall.C
@@ -39,6 +39,7 @@
#include <kernel/vmmmgr.H>
#include <kernel/stacksegment.H>
#include <kernel/heapmgr.H>
+#include <kernel/intmsghandler.H>
extern "C"
void kernel_execute_decrementer()
@@ -121,8 +122,8 @@ namespace Systemcalls
&FutexWait, // FUTEX_WAIT
&FutexWake, // FUTEX_WAKE
- &Shutdown, // MISC_SHUTDOWN
- &CpuCoreType, // MISC_CPUCORETYPE
+ &Shutdown, // MISC_SHUTDOWN
+ &CpuCoreType, // MISC_CPUCORETYPE
&CpuDDLevel, // MISC_CPUDDLEVEL
&MmAllocBlock, // MM_ALLOC_BLOCK
@@ -246,16 +247,47 @@ namespace Systemcalls
}
static MessageQueue* msgQRoot = NULL;
+ static MessageQueue* msgQIntr = NULL;
void MsgQRegisterRoot(task_t* t)
{
- msgQRoot = (MessageQueue*) TASK_GETARG0(t);
- TASK_SETRTN(t, 0);
+ switch(TASK_GETARG0(t))
+ {
+ case MSGQ_ROOT_VFS:
+ msgQRoot = (MessageQueue*) TASK_GETARG1(t);
+ TASK_SETRTN(t,0);
+ break;
+
+ case MSGQ_ROOT_INTR:
+ msgQIntr = (MessageQueue*) TASK_GETARG1(t);
+ InterruptMsgHdlr::create(msgQIntr);
+ TASK_SETRTN(t,0);
+ break;
+
+ default:
+ printk("ERROR MsgRegisterRoot invalid type %ld\n",
+ TASK_GETARG0(t));
+ TASK_SETRTN(t,-EINVAL);
+ }
}
void MsgQResolveRoot(task_t* t)
{
- TASK_SETRTN(t, (uint64_t) msgQRoot);
+ switch(TASK_GETARG0(t))
+ {
+ case MSGQ_ROOT_VFS:
+ TASK_SETRTN(t, (uint64_t) msgQRoot);
+ break;
+
+ case MSGQ_ROOT_INTR:
+ TASK_SETRTN(t, (uint64_t) msgQIntr);
+ break;
+
+ default:
+ printk("ERROR MsgQResolveRoot invalid type %ld\n",
+ TASK_GETARG0(t));
+ TASK_SETRTN(t,0);
+ }
}
void MsgSend(task_t* t)
@@ -563,3 +595,4 @@ namespace Systemcalls
}
};
+
OpenPOWER on IntegriCloud