[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 | 2 +-
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(+), 13 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..c5d1e05 100644
--- a/src/kernel2/src/arch/i386/vm86.c
+++ b/src/kernel2/src/arch/i386/vm86.c
@@ -150,7 +150,7 @@ static int create_vm86_task(int intr, vm86_regs_t* regs, uintptr_t stack)
visf.es = regs->es;
// Und das ganze auf den Stack
- task->kernel_stack = ((uint8_t*) task->kernel_stack)
+ task->user_isf = task->kernel_stack = ((uint8_t*) task->kernel_stack)
+ sizeof(*isf) - sizeof(visf);
memcpy(task->kernel_stack, &visf, sizeof(visf));
diff --git a/src/kernel2/src/interrupts/im.c b/src/kernel2/src/interrupts/im.c
index 1930c0d..0379d30 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 != 0x8) {
+ 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