aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoic Guegan <manzerbredes@mailbox.org>2021-04-16 14:39:24 +0200
committerLoic Guegan <manzerbredes@mailbox.org>2021-04-16 14:39:24 +0200
commit98d524bc8acb7b19afb693afea3ac77629d6f4bf (patch)
tree86a883c01bbf521ef40e914d16939b44c08e7f01
parent58b706d40f8ad0d71b667ca81d91b96ca537cb8e (diff)
Multitasking works!
-rw-r--r--src/bringelle.c37
-rw-r--r--src/core/idt.c2
-rw-r--r--src/core/paging.c2
-rw-r--r--src/core/paging.h8
-rw-r--r--src/core/scheduler.c99
-rw-r--r--src/core/scheduler.h4
-rw-r--r--src/core/scheduler_asm.S39
7 files changed, 120 insertions, 71 deletions
diff --git a/src/bringelle.c b/src/bringelle.c
index cb8c5e4..38c066e 100644
--- a/src/bringelle.c
+++ b/src/bringelle.c
@@ -9,14 +9,26 @@ extern void interrupt_enable();
void utask(){
char *msg=(char*)4206592+10;
- msg[0]='T';
- msg[1]='a';
- msg[2]='s';
- msg[3]='k';
- msg[4]='1';
- msg[5]='\0';
- asm("mov $0x1, %%eax;int $0x30"::"b"(msg));
- while(1);
+ msg[0]='A';
+ msg[1]='\0';
+ while(1){
+ asm("mov $0x1, %%eax;int $0x30"::"b"(msg));
+ for(int i=0;i<10000;i++){
+
+ }
+ }
+}
+
+void utask2(){
+ char *msg=(char*)4206592+10;
+ msg[0]='B';
+ msg[1]='\0';
+ while(1){
+ asm("mov $0x1, %%eax;int $0x30"::"b"(msg));
+ for(int i=0;i<10000;i++){
+
+ }
+ }
}
void bringelle(){
@@ -34,10 +46,15 @@ void bringelle(){
show_tics=1;
// Utask
- print("Launch user task \n");
+ print("Launch user tasks \n");
+
int* page_dir=paging_allocate(2);
- run_task(page_dir, utask,100);
+ task_create(page_dir, utask,100);
+
+ int* page_dir2=paging_allocate(2);
+ task_create(page_dir2, utask2,100);
+ scheduler_start();
while(1);
}
diff --git a/src/core/idt.c b/src/core/idt.c
index 4e08d62..5acdf8b 100644
--- a/src/core/idt.c
+++ b/src/core/idt.c
@@ -25,7 +25,7 @@ void idt_init(){
if(i==33)
idt_write_entry((IDT_ENTRY){0x08,(u32)&INT_KEYPRESS,IDT_INT_GATE},i);
if(i==48)
- idt_write_entry((IDT_ENTRY){0x08,(u32)&INT_SYSCALL,IDT_TRAP_GATE},i);
+ idt_write_entry((IDT_ENTRY){0x08,(u32)&INT_SYSCALL,IDT_INT_GATE|0x6000},i);
}
// Load IDT
asm("lidtl (IDTR)");
diff --git a/src/core/paging.c b/src/core/paging.c
index 0fab46a..ab853bb 100644
--- a/src/core/paging.c
+++ b/src/core/paging.c
@@ -110,7 +110,7 @@ int *paging_allocate(int p){
u_page_table[1]=(int)k_page_table|7;
u_page_table[2]=(int)u_page_table|7;
u_page_table[3]=(int)paging_allocate_next_page()|7;
-
+
return page_dir;
}
diff --git a/src/core/paging.h b/src/core/paging.h
index 5329384..34eddff 100644
--- a/src/core/paging.h
+++ b/src/core/paging.h
@@ -9,7 +9,13 @@
#else
#define PAGING_MAX_DIR_ENTRY PAGING_MAX_PAGES/1024
#endif
-#define PADDR(entry) (((u32)entry)&0xFFFFF000)
+#define PAGING_PADDR(entry) ((int*)(((u32)entry)&0xFFFFF000))
+#define PAGING_ENTRY_POINT_VIRT (1024*PAGING_PAGE_SIZE+3*PAGING_PAGE_SIZE)
+#define PAGING_ENTRY_POINT_PHY(page_dir) ((int*)(((int*)((((int*)page_dir)[1])&0xFFFFF000))[3]&0xFFFFF000))
+
+
+
+
/**
* Configure and enable paging
diff --git a/src/core/scheduler.c b/src/core/scheduler.c
index 0a8c5c7..fffeaf2 100644
--- a/src/core/scheduler.c
+++ b/src/core/scheduler.c
@@ -9,16 +9,14 @@ PROC procs[MAX_PROC];
u16 current_id;
u16 nproc;
-void schedule(){
+void schedule(u32 *stack){
// Note that this function is called by clock
// clock is called by INT_CLOCK (core/int.S)
// which store all the process information on
// the stack. Thus, knowing the C calling conventions
// and that schedule() is call by two functions with no parameters,
// the first process register can be accessed by ebp+2
- u32 *stack;
- asm("mov %%ebp, %0":"=r" (stack));
-
+
// No proc to schedule
if(nproc<2)
return;
@@ -47,7 +45,8 @@ void schedule(){
current_id++;
if(current_id>=nproc)
current_id=0;
-
+ p=&procs[current_id];
+
// Have a clean stack on next interrupt
TSS.esp0=(u32)stack+19;
asm("mov %%ss, %0": "=m" (TSS.ss0));
@@ -58,13 +57,16 @@ void schedule(){
// Perform task switch
asm(
- "mov %0, %%esi \n\t"
+ "push %0 \n\t"
"jmp task_switch \n\t"
:: "a" (p)
);
}
void clock(){
+ u32* stack;
+ asm("mov %%ebp, %0":"=r" (stack));
+
static int tic=0;
static int sec=0;
tic++;
@@ -75,46 +77,69 @@ void clock(){
putchar('.');
}
if(scheduler_on==1)
- schedule();
+ schedule(stack);
}
-void run_task(int *page_dir, void *task, int task_size){
+void task_create(int *page_dir, void *task, int task_size){
+ if(nproc<=MAX_PROC){
// Compute various addresses
- int*pt_addr=(int*)PADDR(page_dir[1]);
- void *entry_point=(void*)(PADDR(pt_addr[3]));
- void *ustack=(void*)((int)entry_point+0xFF);
+ void *entry_point=PAGING_ENTRY_POINT_VIRT;
+ void *ustack=(void*)(PAGING_ENTRY_POINT_VIRT+0xFF);
// Load the task into memory
- memcpy(task,entry_point, task_size);
-
- // Load page directory
- asm(
- "mov %0, %%eax \n\t"
- "mov %%eax,%%cr3 \n\t"
- :: "b"(page_dir)
- );
+ memcpy(task,PAGING_ENTRY_POINT_PHY(page_dir), task_size);
- // Setup users adresses
-
- // Switch to user task
+ // Setup process registers
+ PROC *p=&procs[nproc];
+ p->regs.cs=0x23; // Task cs which is 0x30 along with prlv which is 0x3
+ p->regs.eip=entry_point;
+ p->regs.ss=0x33; // Task ss which is 0x20 along with prlv which is 0x3
+ p->regs.esp=ustack; // Stack is here for now...
+ p->regs.ds=0x2B; // GDT entry 0x28 along with prlv which is 0x3
+ p->regs.eax=0;
+ p->regs.ebx=0;
+ p->regs.ecx=0;
+ p->regs.edx=0;
+
+ // Manage eflags
+ u32 eflags;
asm (
- "cli \n\t" // Ensure we do not get interrupted
- "movl %%ss, %%eax \n\t"
- "movl %%eax, %0 \n\t" // Save kernel ss segment into the TSS
- "movl %%esp, %1 \n\t" // Save kernel esp into the TSS BEFORE setting up the stack
- "pushl $0x33 \n\t" // Push task ss which is 0x30 along with prlv which is 0x3
- "pushl %2 \n\t" // Push task esp
"pushfl \n\t" // Retrieve flags
"popl %%eax \n\t"
"orl $0x200, %%eax \n\t" // Enable interrupt for the user task
"and $0xffffbfff, %%eax \n\t" // Clear the NT flags
- "push %%eax \n\t" // Push task flags
- "push $0x23 \n\t" // Push task cs which is 0x20 along with prlv which is 0x3
- "push %3 \n\t" // Push task entry point
- "mov $0x2B, %%eax \n\t" // GDT entry 0x28 along with prlv which is 0x3
- "mov %%eax, %%ds \n\t" // Setting up user data segment
- "iret \n\t" // Launch user task
- : "=m" (TSS.ss0), "=m" (TSS.esp0)
- : "b" (ustack), "c" (entry_point)
- );
+ "mov %%eax, %0 \n\t" // Get flags into eflag
+ : "=m" (eflags)
+ );
+ p->regs.eflags=eflags;
+
+ // Setup other attributes
+ p->id=nproc;
+ p->pid=nproc;
+ p->page_dir=page_dir;
+ nproc++;
+ }
+}
+
+void scheduler_start(){
+ if(nproc>0){
+ asm("cli");
+ scheduler_on=1; // Enable scheduling
+ u32 *stack;
+ asm("mov %%ebp, %0":"=r" (stack));
+ TSS.esp0=(u32)stack+1; // Remove ebp (c call convention)
+ asm("mov %%ss, %0": "=m" (TSS.ss0));
+
+ current_id=1;
+ PROC *p=&procs[current_id];
+
+ // Ensure interrupts are activated and NT flag is clear
+ p->regs.eflags|=0x200;
+ p->regs.eflags&=0xffffbfff;
+ asm(
+ "push %0 \n\t"
+ "jmp task_switch"
+ :: "a" (p)
+ );
+ }
} \ No newline at end of file
diff --git a/src/core/scheduler.h b/src/core/scheduler.h
index 9055fda..fbcf6bd 100644
--- a/src/core/scheduler.h
+++ b/src/core/scheduler.h
@@ -34,6 +34,6 @@ extern u16 nproc;
void clock();
void schedule();
-void run_task(int *page_dir, void *task, int task_size);
-
+void task_create(int *page_dir, void *task, int task_size);
+void scheduler_start();
#endif \ No newline at end of file
diff --git a/src/core/scheduler_asm.S b/src/core/scheduler_asm.S
index 92e3f2e..1f916ec 100644
--- a/src/core/scheduler_asm.S
+++ b/src/core/scheduler_asm.S
@@ -4,24 +4,24 @@
// to a PROC structure and jump
// to this process
task_switch:
- push 12(%esi) # eax (cf PROC struct)
- push 16(%esi) # ebx
- push 20(%esi) # ecx
- push 24(%esi) # edx
- push 44(%esi) # ebp
- push 48(%esi) # esi
- push 52(%esi) # edi
- push 56(%esi) # ds
- push 60(%esi) # es
- push 64(%esi) # fs
- push 68(%esi) # gs
+ pop %esi
+ push 8(%esi) # eax (cf PROC struct)
+ push 12(%esi) # ebx
+ push 16(%esi) # ecx
+ push 20(%esi) # edx
+ push 40(%esi) # ebp
+ push 48(%esi) # edi
+ push 52(%esi) # ds
+ push 56(%esi) # es
+ push 60(%esi) # fs
+ push 64(%esi) # gs
// Don't forget to clear the interrupt
movb $0x20, %al
outb %al, $0x20
// Setup process page directory
- mov 8(%esi), %eax
+ mov 4(%esi), %eax
mov %eax, %cr3
// Setup registers
@@ -30,7 +30,6 @@ task_switch:
pop %es
pop %ds
pop %edi
- pop %esi
pop %ebp
pop %edx
pop %ecx
@@ -38,9 +37,11 @@ task_switch:
pop %eax
// Perform the task switch
- push 36(%esi) # ss
- push 40(%esi) # esp
- push 72(%esi) # eflags
- push 28(%esi) # cs
- push 32(%esi) # eip
- iret
+ push 32(%esi) # ss
+ push 36(%esi) # esp
+ push 68(%esi) # eflags
+ push 24(%esi) # cs
+ push 28(%esi) # eip
+ mov 52(%esi), %ds # Choose the right data segment
+ mov 44(%esi), %esi # Now restore task esi
+ iret # Launch task