aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/idt.c2
-rw-r--r--src/core/scheduler.c35
-rw-r--r--src/core/scheduler.h1
-rw-r--r--src/core/scheduler_asm.S28
4 files changed, 49 insertions, 17 deletions
diff --git a/src/core/idt.c b/src/core/idt.c
index 861927a..30bb113 100644
--- a/src/core/idt.c
+++ b/src/core/idt.c
@@ -26,7 +26,7 @@ void idt_init(){
if(i==33)
idt_write_entry((IDT_ENTRY){0x08,(u32)&INT_KEYPRESS,IDT_INT_GATE|IDT_P},i);
if(i==48)
- idt_write_entry((IDT_ENTRY){0x08,(u32)&INT_SYSCALL,IDT_INT_GATE|IDT_P|IDT_PRVL_3},i);
+ idt_write_entry((IDT_ENTRY){0x08,(u32)&INT_SYSCALL,IDT_TRAP_GATE|IDT_P|IDT_PRVL_3},i);
}
// Load IDT
asm("lidtl (IDTR)");
diff --git a/src/core/scheduler.c b/src/core/scheduler.c
index 59f3b9d..0c1d255 100644
--- a/src/core/scheduler.c
+++ b/src/core/scheduler.c
@@ -37,8 +37,19 @@ void schedule(u32 *stack){
p->regs.eip=stack[12];
p->regs.cs=stack[13];
p->regs.eflags=stack[14];
- p->regs.esp=stack[15];
- p->regs.ss=stack[16];
+
+ // If clock occurs during a syscall (another interrupt)
+ if(p->regs.cs==0x08){
+ // Since we where already in kernel mode
+ // the CPU did not push ss and esp
+ // thus esp point to
+ p->regs.esp=&stack[15]; // Since we came from another interrupt this value will be restore by the last interrupt
+ p->regs.ss=TSS.ss0;
+ }
+ else {
+ p->regs.esp=stack[15];
+ p->regs.ss=stack[16];
+ }
// Get the next task to run
current_id++;
@@ -46,9 +57,9 @@ void schedule(u32 *stack){
current_id=0;
p=&procs[current_id];
- // Have a clean stack on next interrupt
- TSS.esp0=(u32)stack+17;
- asm("mov %%ss, %0": "=m" (TSS.ss0));
+ // Use kernel stack of the next task
+ TSS.ss0=p->regs.ss0;
+ TSS.esp0=p->regs.esp0;
// Ensure interrupts are activated and NT flag is clear
p->regs.eflags|=0x200;
@@ -90,6 +101,8 @@ void task_create(void *task, int task_size){
void *entry_point=PAGING_ENTRY_POINT_VIRT;
// User stack start at the end of last allocated page (since addresses are going down)
void *ustack=(void*)(PAGING_ENTRY_POINT_VIRT+allocated*4096);
+ // Kernel stack start at the end of last allocated page +1 (see paging_allocate() implementation)
+ void *kstack=(void*)(PAGING_ENTRY_POINT_VIRT+(allocated+1)*4096);
// Load the task into memory
memcpy(task,PAGING_ENTRY_POINT_PHY(page_dir), task_size);
@@ -105,6 +118,8 @@ void task_create(void *task, int task_size){
p->regs.ebx=0;
p->regs.ecx=0;
p->regs.edx=0;
+ p->regs.ss0=0x18;
+ p->regs.esp0=kstack;
// Manage eflags
u32 eflags;
@@ -135,19 +150,15 @@ void scheduler_start(){
// Enable scheduling
scheduler_on=1;
- // Save kernel stack state
- u32 *stack;
- asm("mov %%ebp, %0":"=r" (stack));
- // Remove ebp from the (c call convention) and return address (call)
- TSS.esp0=(u32)stack+2;
- asm("mov %%ss, %0": "=m" (TSS.ss0));
-
// Get first stack
current_id=0;
PROC *p=&procs[current_id];
// Ensure interrupts are activated and NT flag is clear
p->regs.eflags|=0x200;
p->regs.eflags&=0xffffbfff;
+ // Use task kernel stack
+ TSS.ss0=p->regs.ss0;
+ TSS.esp0=p->regs.esp0;
// Switch to user task
asm(
"push %0 \n\t"
diff --git a/src/core/scheduler.h b/src/core/scheduler.h
index 3410ba1..9678470 100644
--- a/src/core/scheduler.h
+++ b/src/core/scheduler.h
@@ -14,6 +14,7 @@ typedef struct REGISTERS {
u32 esi, edi;
u32 ds, es, fs, gs;
u32 eflags;
+ u32 ss0, esp0;
} __attribute__((packed)) REGISTERS;
// If you change the following struct
diff --git a/src/core/scheduler_asm.S b/src/core/scheduler_asm.S
index 1f916ec..2fdf3e5 100644
--- a/src/core/scheduler_asm.S
+++ b/src/core/scheduler_asm.S
@@ -5,6 +5,24 @@
// to this process
task_switch:
pop %esi
+
+ // Switch to the new task kernel stack
+ mov 72(%esi), %ss
+ mov 76(%esi), %esp
+
+ // If we where in kernel mode we should keep using the same
+ // stack which is stored in regs.ss and regs.esp by schedule
+ mov 24(%esi), %eax
+ cmp $0x08, %eax # Check if we were in kernel mode
+ jne skip_kernel_stack
+ mov 32(%esi), %ss
+ mov 36(%esi), %esp
+ skip_kernel_stack:
+
+ // Setup process page directory to be able to use task stack
+ mov 4(%esi), %eax
+ mov %eax, %cr3
+
push 8(%esi) # eax (cf PROC struct)
push 12(%esi) # ebx
push 16(%esi) # ecx
@@ -20,10 +38,6 @@ task_switch:
movb $0x20, %al
outb %al, $0x20
- // Setup process page directory
- mov 4(%esi), %eax
- mov %eax, %cr3
-
// Setup registers
pop %gs
pop %fs
@@ -37,8 +51,14 @@ task_switch:
pop %eax
// Perform the task switch
+ push %eax
+ mov 24(%esi), %eax
+ cmp $0x08, %eax # Check if we were in kernel mode
+ pop %eax
+ je skip_stack
push 32(%esi) # ss
push 36(%esi) # esp
+ skip_stack:
push 68(%esi) # eflags
push 24(%esi) # cs
push 28(%esi) # eip