[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[tyndur-devel] [PATCH] kernel2: Kernel-Interrupts moeglich machen



* kernel2: Anpassungen damit kernel-Interrupts nicht mehr den Stack
           durcheinander bringen.
* kernel2: Neues Feld user_isf eingefuehrt, damit im Kernel jederzeit
           auf den ISF des Userspace-Interrupts zugegriffen werden
           kann, auch nach einem Kernel-Interrupt.
! kernel2: Keine RPCs zu Tasks die in Kernel-Interrupts sind

Signed-off-by: Antoine Kaufmann <toni@xxxxxxxxxx>
---
 src/kernel2/include/tasks.h      |    3 +++
 src/kernel2/src/arch/i386/vm86.c |    1 +
 src/kernel2/src/interrupts/im.c  |   24 ++++++++++++++----------
 src/kernel2/src/syscalls/rpc.c   |   12 ++++++++++--
 src/kernel2/src/tasks/thread.c   |    1 +
 5 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/src/kernel2/include/tasks.h b/src/kernel2/include/tasks.h
index dfd0ea5..d1b031c 100644
--- a/src/kernel2/include/tasks.h
+++ b/src/kernel2/include/tasks.h
@@ -106,6 +106,9 @@ typedef struct {
     /// Groesse des Kernelstacks
     size_t kernel_stack_size;
 
+    /// Aktueller Stackframe des Userspace-Interrupts
+    vaddr_t user_isf;
+
     /// Anfang des Usermode-Stacks
     vaddr_t user_stack_bottom;
 
diff --git a/src/kernel2/src/arch/i386/vm86.c b/src/kernel2/src/arch/i386/vm86.c
index cdee6f1..2aa7a25 100644
--- a/src/kernel2/src/arch/i386/vm86.c
+++ b/src/kernel2/src/arch/i386/vm86.c
@@ -152,6 +152,7 @@ static int create_vm86_task(int intr, vm86_regs_t* regs, uintptr_t stack)
     // Und das ganze auf den Stack
     task->kernel_stack = ((uint8_t*) task->kernel_stack)
         + sizeof(*isf) - sizeof(visf);
+    task->user_isf = task->kernel_stack;
     memcpy(task->kernel_stack, &visf, sizeof(visf));
 
     // Sofort in den VM86-Task wechseln. Der aufrufende Thread wird
diff --git a/src/kernel2/src/interrupts/im.c b/src/kernel2/src/interrupts/im.c
index 1930c0d..b9b1e01 100644
--- a/src/kernel2/src/interrupts/im.c
+++ b/src/kernel2/src/interrupts/im.c
@@ -133,9 +133,14 @@ interrupt_stack_frame_t* im_handler(interrupt_stack_frame_t* isf)
     // Pointer auf den aktuellen Thread holen    
     pm_thread_t* thread = current_thread;
     pm_thread_t* old_thread = thread;
-    thread->kernel_stack = (vaddr_t) isf;
     uint8_t int_num = isf->interrupt_number;
-    
+    interrupt_stack_frame_t* new_isf = isf;
+
+    // Wenn der Int aus dem Userspace kommt, legen wir den zugehoerigen ISF ab
+    if ((isf->cs & 0x3) || (isf->eflags & 0x20000)) {
+        thread->user_isf = isf;
+    }
+
     if (int_num < 20) {
         handle_exception(isf, int_num);
     } else if ((int_num >= 20) && (int_num < 32)){
@@ -179,25 +184,24 @@ interrupt_stack_frame_t* im_handler(interrupt_stack_frame_t* isf)
 
     thread = current_thread;
     if (thread != old_thread) {
-        interrupt_stack_frame_t* new_isf =
-            (interrupt_stack_frame_t*) thread->kernel_stack;
+        interrupt_stack_frame_t* user_isf = thread->user_isf;
+        old_thread->kernel_stack = isf;
+        new_isf = thread->kernel_stack;
 
         cpu_get_current()->tss.ss0 = 2 << 3;
-        if (new_isf->eflags & 0x20000) {
+        if (user_isf->eflags & 0x20000) {
             cpu_get_current()->tss.esp0 =
-                (uintptr_t) thread->kernel_stack
-                + sizeof(struct vm86_isf);
+                (uintptr_t) user_isf + sizeof(struct vm86_isf);
         } else {
             cpu_get_current()->tss.esp0 =
-                (uintptr_t) thread->kernel_stack
-                + sizeof(interrupt_stack_frame_t);
+                (uintptr_t) user_isf + sizeof(interrupt_stack_frame_t);
         }
 
         mmc_activate(&thread->process->context);
     }
 
     im_end_of_interrupt(int_num);
-    return (interrupt_stack_frame_t*) thread->kernel_stack;
+    return new_isf;
 }
 
 /**
diff --git a/src/kernel2/src/syscalls/rpc.c b/src/kernel2/src/syscalls/rpc.c
index 0f542d9..f412389 100644
--- a/src/kernel2/src/syscalls/rpc.c
+++ b/src/kernel2/src/syscalls/rpc.c
@@ -198,11 +198,19 @@ int do_fastrpc(pid_t callee_pid, size_t metadata_size, void* metadata,
 
     // Interrupt Stack Frame des aufgerufenen Tasks mappen
     paddr_t callee_isf_phys =
-        mmc_resolve(&callee->process->context, callee->kernel_stack);
+        mmc_resolve(&callee->process->context, callee->user_isf);
 
     interrupt_stack_frame_t* callee_isf = (interrupt_stack_frame_t*)
         vmm_kernel_automap(callee_isf_phys, sizeof(*callee_isf));
 
+    // Wenn sich der Task gerade in einem Kernel-Int befindet, lassen wir ihn
+    // besser in Ruhe und probieren spaeter nochmal.
+    if ((current_thread != callee) &&
+        (callee->kernel_stack != callee->user_isf))
+    {
+        vmm_kernel_unmap(callee_isf, sizeof(*callee_isf));
+        return -EAGAIN;
+    }
 
     // RPC-Backlinkinformation anlegen
     rpc_t* rpc = malloc(sizeof(rpc_t));
@@ -351,7 +359,7 @@ bool fastrpc_irq(pm_process_t* callee, size_t metadata_size, void* metadata,
 void syscall_fastrpc_ret(void)
 {
     rpc_t* rpc = list_pop(current_process->rpcs);
-    interrupt_stack_frame_t* callee_isf = current_thread->kernel_stack;
+    interrupt_stack_frame_t* callee_isf = current_thread->user_isf;
 
     // Wenn der Task vom RPC-Handler zurückkehrt, obwohl der Handler
     // gar nicht aufgerufen wurde, läuft was schief
diff --git a/src/kernel2/src/tasks/thread.c b/src/kernel2/src/tasks/thread.c
index b94cc3b..ba6e569 100644
--- a/src/kernel2/src/tasks/thread.c
+++ b/src/kernel2/src/tasks/thread.c
@@ -79,6 +79,7 @@ pm_thread_t* pm_thread_create(pm_process_t* process, vaddr_t entry)
         thread->kernel_stack_size - sizeof(interrupt_stack_frame_t));
     interrupt_stack_frame_t* isf = (interrupt_stack_frame_t*) thread->
         kernel_stack;
+    thread->user_isf = thread->kernel_stack;
 
     //  Wir wollen alle Register schoen mit 0 initialisiert haben
     memset(isf, 0, sizeof(interrupt_stack_frame_t));
-- 
1.6.4.4