]> git.corax.cc Git - corax/commitdiff
Move definition of struct task from arch/task.h to include/arch.h; add proper impleme...
authorMatthias Kruk <m@m10k.eu>
Fri, 6 Sep 2019 17:52:58 +0000 (02:52 +0900)
committerMatthias Kruk <m@m10k.eu>
Fri, 6 Sep 2019 17:53:35 +0000 (02:53 +0900)
kernel/arch/task.S
kernel/arch/task.h [deleted file]
kernel/include/arch.h

index 6a0360e19fa2e66330d0a7f769d081ded37b66b7..31d2f62486bd0bcdeeea8d8c5a748dcef5207aef 100644 (file)
 
 #define CPU_SIZE (TSS_OFFSET + TSS_SIZE + 4)
 #define CUR_TASK (TSS_OFFSET + TSS_SIZE)
+
+#define OFFSET_ESP0   0
+#define OFFSET_CR3    4
+#define OFFSET_KSTACK 8
+
 .extern _cpu
 
-.global _task_prepare
-_task_prepare:
-    pushl   %ebx
-    /* eax = task, ecx = eip, ebx = esp */
-    movl    8(%esp), %eax
-    movl    12(%esp), %ecx
-    movl    16(%esp), %ebx
-
-    addl    $(STACK_OFFSET + STACK_SIZE - STACK_INIT_SIZE), %eax
-    movl    $USER_DATA, (%eax)
-#if CONFIG_INITIALIZE_USER_REGS == 1
-    movl    $32, %esi
-    xorl    %edx, %edx
-
-0:     test    %esi, %esi
-    jz      1f
-    movl    %edx, (%eax, %esi)
-    subl    $4, %esi
-    jmp     0b
-
-#endif /* CONFIG_INITIALIZE_USER_REGS */
-    /* 4(%eax) - 32(%eax) is the location of the general purpose registers */
-1:     movl    %ecx, 36(%eax)
-    movl    $USER_CODE, 40(%eax)
-    movl    $USER_EFLAGS, 44(%eax)
-    movl    %ebx, 48(%eax)
-    movl    $USER_DATA, 52(%eax)
-
-    popl    %ebx
-    ret
-
-.global _task_switch
-_task_switch:
-    movl    4(%esp), %eax
-    movl    4(%eax), %ebx
-    movl    %cr3, %edx
-    cmpl    %edx, %ebx
-    jz      0f
-    movl    %ebx, %cr3
-
-0:     cpuidx  %ecx
-    movl    $CPU_SIZE, %esi
-    shll    %cl, %esi
-    movl    _cpu(%esi), %ebx
-    movl    CUR_TASK(%ebx), %edi
-    cmpl    %edi, %eax
-
-    jz      0b
-    movl    %esp, (%edi)
-    movl    %eax, CUR_TASK(%ebx)
-    movl    (%eax), %esp
-    iret
+.global task_prepare
+.global task_switch
+
+task_prepare:
+       /*
+        * int task_prepare(struct task*, u32_t cr3, u32_t eip,
+        *                  u32_t esp, u32_t priv)
+        *
+        *  priv  = 20(%esp)
+        *  esp   = 16(%esp)
+        *  eip   = 12(%esp)
+        *  cr3   =  8(%esp)
+        *  task  =  4(%esp)
+        */
+
+       movl    4(%esp), %edi
+
+       /* store cr3 in task structure */
+       movl    8(%esp), %eax
+       movl    %eax, 4(%edi)
+
+       /* calculate stack start (since it grows down) */
+       movl    $CONFIG_KERNEL_STACK_SIZE, %ecx
+       movl    (%esp), %eax
+       leal    OFFSET_KSTACK(%eax, %ecx, 1), %eax
+
+       /*
+        * We will use _int_restore (the lower half of the interrupt handler)
+        * to start execution of tasks. In order to do that, we need to set up
+        * the stack properly. The _int_restore assembly function will restore
+        * the data segments and general purpose registers before executing the
+        * iret instruction. This is why we need the following stack layout.
+        *
+        *  +--------+
+        *  | SS     | 60(%eax) \
+        *  | ESP    | 56(%eax) |
+        *  | EFLAGS | 52(%eax) > for iret
+        *  | CS     | 48(%eax) |
+        *  | EIP    | 44(%eax) /
+        *  +--------+
+        *  | error  | 40(%eax) \ error pushed by _int_entryNN
+        *  | intr   | 36(%eax) / int number pushed by _int_entryNN
+        *  +--------+
+        *  | EDI    | 32(%eax) \
+        *  | ESI    | 28(%eax) |
+        *  | EBP    | 24(%eax) |
+        *  | unused | 20(%eax) |
+        *  | EBX    | 16(%eax)  > for popa
+        *  | EDX    | 12(%eax) |
+        *  | ECX    |  8(%eax) |
+        *  | EAX    |  4(%eax) /
+        *  +--------+
+        *  | DS     |   (%eax) > data segment registers
+        *  +--------+
+        *
+        * In total, there are 16 dwords to be put on the stack, so we will
+        * start by adding 64 to %eax and then use the addresses above.
+        */
+
+       subl    $64, %eax
+
+       /* calculate DS from priv and put it on the new stack */
+       movl    20(%esp), %ecx
+       shll    $4, %ecx
+       addl    $16, %ecx
+       orl             20(%esp), %ecx
+       movl    %ecx, (%eax)
+
+       /* Clear general purpose registers (and error/intr) */
+       movl    $0, 4(%eax)
+       movl    $0, 8(%eax)
+       movl    $0, 12(%eax)
+       movl    $0, 16(%eax)
+       movl    $0, 20(%eax)
+       movl    $0, 24(%eax)
+       movl    $0, 28(%eax)
+       movl    $0, 32(%eax)
+       movl    $0, 36(%eax)
+       movl    $0, 40(%eax)
+
+       /* put EIP on the new stack */
+       movl    12(%esp), %ecx
+       movl    %ecx, 44(%eax)
+
+       /* calculate CS from priv and put it on the new stack */
+       movl    20(%esp), %ecx
+       shll    $4, %ecx
+       addl    $8, %ecx
+       orl     20(%esp), %ecx
+       movl    %ecx, 48(%eax)
+
+       /* put EFLAGS on the new stack */
+       movl    $USER_EFLAGS, 52(%eax)
+
+       /* put the stack pointer on the stack */
+
+       /* put the stack segment on the new stack - use the value from DS */
+       movl    (%eax), %ecx
+       movl    %ecx, 60(%eax)
+
+       /* put EAX into the task structure */
+       movl    4(%esp), %ecx
+       movl    %eax, OFFSET_ESP0(%ecx)
+
+       /* that should be it */
+       ret
+
+task_switch:
+       /*
+        * void task_switch(struct task*)
+        *
+        *  task = 4(%esp)
+        */
+
+       /* get a pointer to the cpu structure of the current cpu */
+       cpuidx  %ecx
+       movl    $_cpu, %eax
+       /* while(--ecx > 0) { eax += CPU_SIZE; } */
+0:     subl    $1, %ecx
+       js              1f
+       addl    $CPU_SIZE, %eax
+       jmp             0b
+
+       movl    CUR_TASK(%eax), %esi
+       movl    4(%esp), %edi
+
+       cmpl    %esi, %edi
+       jnz             1f
+       /* FIXME: Return -EALREADY instead */
+       movl    $-1, %eax
+       ret
+
+1:     movl    OFFSET_CR3(%edi), %ecx
+
+       /* check if we can avoid writing to cr3, which would clear the TLB */
+       movl    %cr3, %edx
+       cmpl    %ecx, %edx
+       jz              2f
+
+       /* switch page directory */
+       movl    %ecx, %cr3
+
+2:     movl    %edi, CUR_TASK(%eax)
+
+       /* write ESP to the previous TCB, if any */
+       test    %esi, %esi
+       jz              3f
+       movl    %esp, OFFSET_ESP0(%esi)
+
+       /* load new ESP */
+3:     movl    OFFSET_ESP0(%edi), %esp
+
+       /* pretend that we're returning from an interrupt */
+       jmp             _int_restore
diff --git a/kernel/arch/task.h b/kernel/arch/task.h
deleted file mode 100644 (file)
index 0cd1fd2..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * This file is part of the Corax operating system.
- * Copyright (C) 2016 Matthias Kruk
- *
- * Corax is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Corax is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __TASK_H
-#define __TASK_H
-
-#include <config.h>
-
-/* Definition of an architectural task - think of it
- * as a TCB. It is not a operating system process or
- * thread, but merely the information needed by the
- * CPU to perform context switches, etc.
- *
- * Specifically, we need to remember the task's page
- * directory and the stack pointer. The task's context
- * is on top of its stack, i.e. all we have to do is
- * load the task's stack pointer and execute an iret */
-
-struct task {
-    u32_t   t_esp;
-    u32_t   t_cr3;
-
-    u8_t    t_kstack[CONFIG_USER_STACK_SIZE];
-} __attribute__((packed));
-
-struct task* _task_prepare(struct task *t, u32_t eip, u32_t esp);
-void _task_switch(struct task*);
-
-#endif /* __TASK_H */
index 6b6c65ffe95b3ed306d985bf7e162bc816aaff10..06f1932f9f93ccba61bae1eb6922c40b3f29a9d0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of the Corax operating system.
- * Copyright (C) 2016 Matthias Kruk
+ * Copyright (C) 2016-2019 Matthias Kruk
  *
  * Corax is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 #include <corax/types.h>
 
+struct task {
+       u32_t t_sp;
+       u32_t t_pgdir;
+
+       u8_t  t_kstack[CONFIG_KERNEL_STACK_SIZE];
+} __attribute__((packed));
+
 int     cpu_get_id(void);
 u64_t   cpu_get_capabilities(void);
 u64_t   cpu_timestamp(void);
 
 u32_t   cpu_set_pstate(int pstate);
 
+int     task_prepare(struct task*, u32_t cr3, u32_t eip, u32_t esp, u32_t priv);
+int     task_switch(struct task*);
+
 #endif /* __ARCH_H */