summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPatrick Williams <iawillia@us.ibm.com>2010-06-22 16:41:25 -0500
committerPatrick Williams <iawillia@us.ibm.com>2010-06-22 16:41:25 -0500
commit261aa2b9b790868a16a6cee0f19c73221ddc81d5 (patch)
tree324a74523aa6596705ae2021c494e6acd2ddbb89 /src
parent02b38895c3af9ce6aae9bc02ef2930fabefff628 (diff)
downloadtalos-hostboot-261aa2b9b790868a16a6cee0f19c73221ddc81d5.tar.gz
talos-hostboot-261aa2b9b790868a16a6cee0f19c73221ddc81d5.zip
Program exception handling and emulated instruction for mfsprg3.
Diffstat (limited to 'src')
-rw-r--r--src/include/kernel/ppcarch.H14
-rw-r--r--src/kernel/exception.C58
-rw-r--r--src/kernel/makefile2
-rw-r--r--src/kernel/start.S2
-rw-r--r--src/lib/syscall_task.C9
5 files changed, 82 insertions, 3 deletions
diff --git a/src/include/kernel/ppcarch.H b/src/include/kernel/ppcarch.H
new file mode 100644
index 000000000..f6b80ea6f
--- /dev/null
+++ b/src/include/kernel/ppcarch.H
@@ -0,0 +1,14 @@
+#ifndef __KERNEL_PPCARCH_H
+#define __KERNEL_PPCARCH_H
+
+#include <kernel/types.h>
+
+__attribute__((always_inline))
+inline uint64_t ppc_getSRR1()
+{
+ register uint64_t srr1 = 0;
+ asm volatile("mfsrr1 %0" : "=r" (srr1));
+ return srr1;
+}
+
+#endif
diff --git a/src/kernel/exception.C b/src/kernel/exception.C
new file mode 100644
index 000000000..98d36c35c
--- /dev/null
+++ b/src/kernel/exception.C
@@ -0,0 +1,58 @@
+#include <kernel/types.h>
+#include <kernel/console.H>
+#include <kernel/task.H>
+#include <kernel/taskmgr.H>
+#include <kernel/ppcarch.H>
+
+namespace Systemcalls { void TaskEnd(task_t*); }
+namespace ExceptionHandles
+{
+ bool HvEmulation(task_t*);
+}
+
+const uint64_t EXCEPTION_SRR1_MASK = 0x00000000783F0000;
+const uint64_t EXCEPTION_SRR1_HVEMUL = 0x0000000000080000;
+
+extern "C"
+void kernel_execute_prog_ex()
+{
+ task_t* t = TaskManager::getCurrentTask();
+ uint64_t exception = ppc_getSRR1() & EXCEPTION_SRR1_MASK;
+
+ bool handled = false;
+ switch(exception)
+ {
+ case EXCEPTION_SRR1_HVEMUL:
+ handled = ExceptionHandles::HvEmulation(t);
+ break;
+ }
+ if (!handled)
+ {
+ printk("Program exception, killing task %d\n", t->tid);
+ Systemcalls::TaskEnd(t);
+ }
+}
+
+namespace ExceptionHandles
+{
+ bool HvEmulation(task_t* t)
+ {
+ /*printk("NIP = %llx : Inst = %lx\n",
+ t->context.nip,
+ (*(uint32_t*)t->context.nip));*/
+
+ uint32_t instruction = *(uint32_t*)t->context.nip;
+
+ // check for mfsprg3
+ if ((instruction & 0xfc1fffff) == 0x7c1342a6)
+ {
+ t->context.gprs[(instruction & 0x03E00000) >> 21] =
+ (uint64_t) t;
+ t->context.nip = (void*) (((uint64_t)t->context.nip)+4);
+ return true;
+ }
+
+ return false;
+ }
+
+}
diff --git a/src/kernel/makefile b/src/kernel/makefile
index 629c39bcb..4bdc0d02d 100644
--- a/src/kernel/makefile
+++ b/src/kernel/makefile
@@ -2,7 +2,7 @@ OBJDIR = ../../obj
include ../../config.mk
OBJS = start.o kernel.o console.o pagemgr.o heapmgr.o taskmgr.o cpumgr.o
-OBJS += syscall.o scheduler.o spinlock.o
+OBJS += syscall.o scheduler.o spinlock.o exception.o
OBJECTS = $(addprefix ${OBJDIR}/, ${OBJS})
all: ${OBJECTS}
diff --git a/src/kernel/start.S b/src/kernel/start.S
index 93cc0156e..774c62f67 100644
--- a/src/kernel/start.S
+++ b/src/kernel/start.S
@@ -103,7 +103,7 @@ UNIMPL_INTERRUPT(inst_storage, 0x400)
UNIMPL_INTERRUPT(inst_segment, 0x480)
UNIMPL_INTERRUPT(external, 0x500)
UNIMPL_INTERRUPT(alignment, 0x600)
-UNIMPL_INTERRUPT(program, 0x700)
+STD_INTERRUPT(prog_ex, 0x700)
UNIMPL_INTERRUPT(fp_unavail, 0x800)
STD_INTERRUPT(decrementer, 0x900)
UNIMPL_INTERRUPT(hype_decrementer, 0x980)
diff --git a/src/lib/syscall_task.C b/src/lib/syscall_task.C
index d07ea3f19..405e4f202 100644
--- a/src/lib/syscall_task.C
+++ b/src/lib/syscall_task.C
@@ -1,6 +1,7 @@
#include <sys/task.h>
#include <sys/syscall.h>
#include <kernel/task.H>
+#include <kernel/taskmgr.H>
using namespace Systemcalls;
@@ -23,5 +24,11 @@ void task_end()
tid_t task_gettid()
{
- return (tid_t)_syscall0(TASK_GETTID);
+ // Even though we have a syscall for GETTID, we can implement this as a
+ // direct access to SPRG3. On processor that do not support unprivilaged
+ // access to this SPR, we implement it as an emulated instruction in the
+ // exception handler.
+
+ return TaskManager::getCurrentTask()->tid;
+ //return (tid_t)_syscall0(TASK_GETTID);
}
OpenPOWER on IntegriCloud