]> git.corax.cc Git - corax/commitdiff
Switch to the kernel page directory when entering the kernel (i.e. separate the kerne...
authorMatthias Kruk <m@m10k.eu>
Tue, 1 Oct 2019 06:42:37 +0000 (15:42 +0900)
committerMatthias Kruk <m@m10k.eu>
Tue, 1 Oct 2019 06:42:37 +0000 (15:42 +0900)
kernel/arch/entry.S
kernel/core/process.c

index 77705f1cf18d04f401bae79e80f880069a9ac662..38ee5301a08ce2b1b8afd1b3be884a54fac53c9b 100644 (file)
@@ -16,6 +16,8 @@
  * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#define __ASSEMBLY_SOURCE
+
 #include <config.h>
 #include "defs.h"
 
@@ -78,6 +80,9 @@
 .global _int_entry_common
 .global _int_restore
 
+.extern _cpu
+.extern _kernel_cr3
+
 .extern _exc_handle
 .extern _int_handle
 .extern _sys_handle
@@ -329,6 +334,44 @@ _int_entry_common:
     movw    %ax, %fs
     movw    %ax, %gs
 
+       /* switch to the kernel page directory, if we're not already using it */
+       movl    (_kernel_cr3), %eax
+       movl    %cr3, %ebx
+       cmpl    %eax, %ebx
+       je              _already_in_kernel
+
+       movl    %eax, %cr3
+
+       /*
+        * When the privilege level changes during an interrupt, the kernel
+        * automatically performs a stack switch, however it does not switch page
+        * directories, meaning we have no choice but to map the per-task kernel
+        * stack into the task's page directory and save the context there. We
+        * then manually switch to the kernel page directory. However, the task's
+        * kernel stack is at a different location in the kernel's page directory
+        * (i.e. its linear address), so we have to adjust the stack pointer before
+        * we can use the stack.
+        */
+
+       cpuidx  %ecx
+       movl    $_cpu, %eax
+0:     subl    $1, %ecx
+       js              1f
+       addl    $CPU_SIZE, %eax
+       jmp             0b
+
+       /* reduce esp to the offset into the stack, then add the linear stack base */
+1:     movl    OFFSET_CPU_CTASK(%eax), %eax
+       subl    $CONFIG_KERNEL_STACK_BASE, %esp
+       addl    OFFSET_TASK_KSTACK(%eax), %esp
+
+       /* do the same with ebp */
+       subl    $CONFIG_KERNEL_STACK_BASE, %ebp
+       addl    OFFSET_TASK_KSTACK(%eax), %ebp
+
+       /* we can now use the stack */
+
+_already_in_kernel:
     cmp     $EXC_MAX, 36(%esp)
     jl      0f
 
index 8562f51234d728b197a4e15474a45d5cb2c1b1b1..387907c36ae648124bbd4841fb89c657edbbb537 100644 (file)
@@ -53,6 +53,7 @@ int process_create(process_t **dst, u32_t ppl, void *entry)
                proc->p_tasks->t_sp = (u32_t)(CONFIG_KERNEL_STACK_BASE +
                                                                          ((u32_t)proc->p_tasks->t_sp - (u32_t)kstack));
 
+               proc->p_tasks->t_kstack = kstack;
                proc->p_tasks->t_tslice = 50;
                proc->p_tasks->t_rslice = 50;