feat: wrapper pour interruptions et pour l'IRQ0 (Scheduler+Timer) et début d'implémentation du scheduling

This commit is contained in:
Nicolas Hordé 2018-12-19 16:13:47 +01:00
parent dd3e40d53e
commit 11428c2415
13 changed files with 299 additions and 191 deletions

View File

@ -63,7 +63,7 @@ Compilation:
Nom | Paquet | Version
--- | --- | ---
gcc | gcc | 5.4.0 20160609
gcc | gcc | *>7.0*
GNU Make | make | 4.1
Outils divers | binutils | 2.26-8
@ -222,16 +222,16 @@ Pour l'instant quelques commandes seulement sont disponibles:
* affichage de chaîne de caractères (prinfs,sprintf,vsprintf) avec type (bin,hexa,octal,float,double,string,char),
* mode protégé limité à 4Go de mémoire vive (32 bits),
* gestion avancée de la mémoire (vmalloc).
* chargeur ELF32,
* espace utilisateur et appels systèmes,
* liste d'API automatiquement mise à jour,
#### En cours
* espace utilisateur et appels systèmes,
* ordonnanceur de tâche (par TSS),
* liste d'API automatiquement mise à jour,
#### A faire
* chargeur ELF32,
* pilote IDE/ATA (PIO mode),
* fonctions affichage image PNG,
* double buffering,

View File

@ -185,7 +185,6 @@ typedef struct process
pid_t getcurrentpid(void);
pid_t getparentpid(void);
pid_t getfreepid(void);
void usepid(pid_t pid);
tid_t getcurrenttid(void);
tid_t maketid(pid_t pid, u32 number);

View File

@ -1,4 +1,7 @@
/*******************************************************************************/
/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */
/* */
void timer(void);
#include "interrupts.h"
__attribute__ ((noreturn)) void timer_handler(regs *dump);

View File

@ -30,7 +30,7 @@ void initgdt(u32 offset)
tss0.trapflag = 0x00;
tss0.iomap = 0x00;
tss0.esp0 = 0x00;
tss0.esp0 = 0x6000;
tss0.ss0 = SEL_TSS;
makegdtdes(&tss0, 0x67, SEG_PRESENT | SEG_CODE | SEG_RING3 | SEG_ACCESSED, 0x00, &gdt[7]); /* descripteur de tss */

View File

@ -14,9 +14,65 @@
/******************************************************************************/
/* Déclenché lors de l'appel d'une interruption */
__attribute__((interrupt)) void interruption(exception_stack_noerror *caller)
__attribute__ ((noreturn)) void interruption_handler(regs *dump)
{
print("Appel d'une interruption\r\n");
u32 interruption=dump->eip;
exception_stack_noerror *caller = (exception_stack_noerror*) ((u32*)dump->esp+1);
bool noerror,user;
if (caller->cs==SEL_KERNEL_CODE || caller->cs==SEL_USER_CODE)
{
noerror=true;
dump->eip = caller->eip;
dump->cs = caller->cs;
dump->eflags = caller->eflags;
if (dump->cs==SEL_KERNEL_CODE)
{
dump->esp = (u32) caller + sizeof(exception_stack_noerror);
user=false;
}
else
{
dump->esp = (u32) ((exception_stack_noerror_user*) caller)->esp;
dump->ss = (u32) ((exception_stack_noerror_user*) caller)->ss;
user=true;
}
}
else
{
noerror=false;
dump->eip = ((exception_stack*)caller)->eip;
dump->cs = ((exception_stack*)caller)->cs;
if (dump->cs==SEL_KERNEL_CODE)
{
dump->esp = (u32) caller + sizeof(exception_stack);
user=false;
}
else
{
dump->esp = (u32) ((exception_stack_user*) caller)->esp;
dump->ss = (u32) ((exception_stack_user*) caller)->ss;
user=true;
}
}
switch (interruption)
{
case 20:
show_lightcpu(dump);
break;
default:
print("Appel d'une interruption\r\n");
}
if (dump->cs==SEL_KERNEL_CODE)
{
setESP(dump);
restcpu_kernel();
}
else
{
setESP(dump);
restcpu_user();
iret();
}
}
/******************************************************************************/
@ -178,7 +234,8 @@ __attribute__ ((noreturn)) void exception_handler(regs *dump)
/* Les IRQ par défaut */
__attribute__((interrupt)) void irq0(exception_stack_noerror *caller)
{ print("irq 0");
{
print("irq 0");
irqendmaster();
}
@ -267,8 +324,6 @@ __attribute__((interrupt)) void irq13(exception_stack_noerror *caller)
print("irq 13");
irqendslave();
irqendmaster();
popad();
popf();
}
__attribute__((interrupt)) void irq14(exception_stack_noerror *caller)

View File

@ -12,7 +12,46 @@ pushl %esp
pushf
pushl %cs
pushl $\num
jmp dumpcpu
jmp exception_suite
.endm
.macro semidumpcpu
pushl %ds
pushl %es
pushl %fs
pushl %gs
pushl %eax
pushl %ebx
pushl %ecx
pushl %edx
pushl %esi
pushl %edi
pushl %ebp
mov %cr0, %eax
pushl %eax
mov %cr2, %eax
pushl %eax
mov %cr3, %eax
pushl %eax
mov %cr4, %eax
pushl %eax
mov %dr0, %eax
pushl %eax
mov %dr1, %eax
pushl %eax
mov %dr2, %eax
pushl %eax
mov %dr3, %eax
pushl %eax
mov %dr6, %eax
pushl %eax
mov %dr7, %eax
pushl %eax
mov $0xC0000080, %ecx
rdmsr
pushl %edx
pushl %eax
pushl %esp
.endm
exception 0
@ -35,6 +74,10 @@ exception 16
exception 17
exception 18
exception_suite:
semidumpcpu
call exception_handler
.global wrapper_sysenter
wrapper_sysenter:
pushl %ss
@ -42,79 +85,25 @@ pushl %esp
pushf
pushl %cs
pushl $0x00
pushl %ds
pushl %es
pushl %fs
pushl %gs
pushl %eax
pushl %ebx
pushl %ecx
pushl %edx
pushl %esi
pushl %edi
pushl %ebp
mov %cr0, %eax
pushl %eax
mov %cr2, %eax
pushl %eax
mov %cr3, %eax
pushl %eax
mov %cr4, %eax
pushl %eax
mov %dr0, %eax
pushl %eax
mov %dr1, %eax
pushl %eax
mov %dr2, %eax
pushl %eax
mov %dr3, %eax
pushl %eax
mov %dr6, %eax
pushl %eax
mov %dr7, %eax
pushl %eax
mov $0xC0000080, %ecx
rdmsr
pushl %edx
pushl %eax
pushl %esp
semidumpcpu
call sysenter_handler
dumpcpu:
pushl %ds
pushl %es
pushl %fs
pushl %gs
pushl %eax
pushl %ebx
pushl %ecx
pushl %edx
pushl %esi
pushl %edi
pushl %ebp
mov %cr0, %eax
pushl %eax
mov %cr2, %eax
pushl %eax
mov %cr3, %eax
pushl %eax
mov %cr4, %eax
pushl %eax
mov %dr0, %eax
pushl %eax
mov %dr1, %eax
pushl %eax
mov %dr2, %eax
pushl %eax
mov %dr3, %eax
pushl %eax
mov %dr6, %eax
pushl %eax
mov %dr7, %eax
pushl %eax
mov $0xC0000080, %ecx
rdmsr
pushl %edx
pushl %eax
.global wrapper_interruption
wrapper_interruption:
pushl %ss
pushl %esp
call exception_handler
pushf
pushl %cs
pushl $0x00
semidumpcpu
call interruption_handler
.global wrapper_timer
wrapper_timer:
pushl %ss
pushl %esp
pushf
pushl %cs
pushl $0x00
semidumpcpu
call timer_handler

View File

@ -41,6 +41,7 @@ extern wrapper_exception15;
extern wrapper_exception16;
extern wrapper_exception17;
extern wrapper_exception18;
extern wrapper_interruption;
/******************************************************************************/
/* Initialise la reprise après erreur */
@ -208,7 +209,7 @@ void initidt(void)
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 18);
for (i = 19; i < 32; i++)
{
putidt((u32) interruption, SEL_KERNEL_CODE,
putidt((u32) &wrapper_interruption, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING3 | TRAPGATE, i);
}
putidt((u32) irq0, SEL_KERNEL_CODE,
@ -229,7 +230,7 @@ void initidt(void)
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 39);
for (i = 40; i < 96; i++)
{
putidt((u32) interruption, SEL_KERNEL_CODE,
putidt((u32) &wrapper_interruption, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING3 | TRAPGATE, i);
}
putidt((u32) irq8, SEL_KERNEL_CODE,
@ -250,7 +251,7 @@ void initidt(void)
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 103);
for (i = 104; i < IDT_SIZE; i++)
{
putidt((u32) interruption, SEL_KERNEL_CODE,
putidt((u32) &wrapper_interruption, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | TRAPGATE, i);
}
/* initialise le registre idt */

View File

@ -364,7 +364,6 @@ unsigned convert(u32 keypressed)
__attribute__((interrupt)) void keyboard_handler(exception_stack_noerror *caller)
{
u8 scancode, ascii;
cli();
while ((inb(0x64) & 1) == 0);
scancode = inb(0x60);
ascii = convert(scancode);

View File

@ -22,13 +22,13 @@ libs.o:$(OBJS) $(OBJASM)
$(ASM) $^
handlers.o:handlers.c
$(CC) -mno-sse $^
$(CC) -mgeneral-regs-only $^
keyboard.o:keyboard.c
$(CC) -mno-sse $^
$(CC) -mgeneral-regs-only $^
mouse.o:mouse.c
$(CC) -mno-sse $^
$(CC) -mgeneral-regs-only $^
syscall.o:syscall.c
$(CC) -fomit-frame-pointer $^

View File

@ -95,6 +95,8 @@ u32 loadelf(u8 * src, pid_t pid)
header = (elf32 *) src;
program = (elf32p *) (src + header->e_phoff);
code = iself(src);
process *aprocess=findprocess(pid);
if (aprocess==NULL) return NULL;
if (code != 0)
{
printf("Erreur de chargement ELF, %s !\r\n",
@ -119,13 +121,13 @@ u32 loadelf(u8 * src, pid_t pid)
}
if (program->p_flags == PF_X + PF_R)
{
processes[(u32)pid].exec_low = (u8 *) v_begin;
processes[(u32)pid].exec_high = (u8 *) v_end;
aprocess->exec_low = (u8 *) v_begin;
aprocess->exec_high = (u8 *) v_end;
}
if (program->p_flags == PF_W + PF_R)
{
processes[(u32)pid].bss_low = (u8 *) v_begin;
processes[(u32)pid].bss_high = (u8 *) v_end;
aprocess->bss_low = (u8 *) v_begin;
aprocess->bss_high = (u8 *) v_end;
}
memcpy((u8 *) (src + program->p_offset),
(u8 *) v_begin, program->p_filesz, 0);
@ -144,19 +146,21 @@ u32 loadelf(u8 * src, pid_t pid)
void initprocesses(void)
{
u32 i = 1;
u32 i = 0;
processes = (process *) vmalloc(sizeof(process) * MAXNUMPROCESS);
while (i < MAXNUMPROCESS)
{
processes[i].pid = NULL;
processes[i++].status = PROCESS_STATUS_FREE;
}
createtask(0,getinitretry(),true);
processes[0].result = 0;
processes[0].status = PROCESS_STATUS_READY;
processes[0].iskernel = true;
current = maketid(0,0);
lastpid = NULL;
pid_t pid=getfreepid();
process *aprocess=findprocess(pid);
if (aprocess==NULL) return NULL;
aprocess->pid = pid;
aprocess->result = 0;
aprocess->status = PROCESS_STATUS_READY;
aprocess->iskernel = true;
current=createtask(pid,getinitretry(),true);
}
/*******************************************************************************/
@ -166,8 +170,8 @@ pid_t getfreepid(void)
{
u32 i = lastpid;
u32 parsed = 0;
while (processes[++i].status != PROCESS_STATUS_FREE
&& ++parsed < MAXNUMPROCESS)
while (processes[i++].status != PROCESS_STATUS_FREE
&& parsed++ < MAXNUMPROCESS)
{
if (i >= MAXNUMPROCESS)
i = 0;
@ -177,6 +181,7 @@ pid_t getfreepid(void)
printf("PANIC: plus d'emplacement disponible pour un novueau processus\n");
return NULL;
}
lastpid=i;
return (pid_t)i;
}
@ -185,15 +190,15 @@ pid_t getfreepid(void)
tid_t getfreeptid(pid_t pid)
{
tid_t new;
new.pid=pid;
task_t *task_head= &processes[(u32)pid].task_head;
process *aprocess=findprocess(pid);
if (aprocess==NULL) return maketid(0,0);
u32 number=0;
task *next;
TAILQ_FOREACH(next, task_head, tailq)
if (next->tid.number>new.number)
new.number=next->tid.number;
next->tid.number++;
return new;
TAILQ_FOREACH(next, &aprocess->task_head, tailq)
if (next->tid.number>number)
number=next->tid.number;
number++;
return maketid(pid,number);
}
/*******************************************************************************/
@ -228,7 +233,10 @@ tid_t maketid(pid_t pid, u32 number)
process* findprocess(pid_t pid)
{
return &processes[(u32)pid];
if ((u32)pid>0)
return &processes[(u32)pid-1];
else
return NULL;
}
/*******************************************************************************/
@ -236,15 +244,7 @@ process* findprocess(pid_t pid)
process* findcurrentprocess(void)
{
return &processes[(u32)getcurrentpid()];
}
/*******************************************************************************/
/* Determine le dernier PID occupé */
void usepid(pid_t pid)
{
lastpid = pid;
return &processes[(u32)getcurrentpid()-1];
}
/*******************************************************************************/
@ -254,7 +254,9 @@ void switchtask(tid_t tid)
{
tid_t previous = current;
task *atask = findtask(tid);
if (atask==NULL) return;
process *aprocess=findprocess(tid.pid);
if (aprocess==NULL) return;
if (!aprocess->iskernel)
setTSS(atask->kernel_stack.ss0, atask->kernel_stack.esp0);
else
@ -273,9 +275,10 @@ void switchtask(tid_t tid)
task* findtask(tid_t tid)
{
task_t *task_head= &processes[(u32)tid.pid].task_head;
process *aprocess=findprocess(tid.pid);
if (aprocess==NULL) return NULL;
task *next;
TAILQ_FOREACH(next, task_head, tailq)
TAILQ_FOREACH(next, &aprocess->task_head, tailq)
if (next->tid.number==tid.number)
return next;
}
@ -296,7 +299,9 @@ void deletetask(tid_t tid)
{
stoptask(tid);
process* aprocess=findprocess(tid.pid);
if (aprocess==NULL) return;
task *atask=findtask(tid);
if (atask==NULL) return;
TAILQ_REMOVE(&aprocess->task_head, atask, tailq);
vfree(atask);
}
@ -307,6 +312,7 @@ void deletetask(tid_t tid)
void runtask(tid_t tid)
{
task *atask=findtask(tid);
if (atask==NULL) return;
if (atask->status == TASK_STATUS_READY)
{
atask->status = TASK_STATUS_RUN;
@ -322,6 +328,7 @@ tid_t createtask(pid_t pid,u8 *entry, bool kerneltask)
tid_t tid;
tid.pid=pid;
process* aprocess=findprocess(pid);
if (aprocess==NULL) return maketid(0,0);
task *new = (task *) vmalloc(sizeof(task));
TAILQ_INSERT_TAIL(&aprocess->task_head, new, tailq);
page *astack = virtual_page_getfree();
@ -355,7 +362,6 @@ tid_t createtask(pid_t pid,u8 *entry, bool kerneltask)
}
new->tid=getfreeptid(pid);
new->dump.eip = aprocess->entry;
new->status=TASK_STATUS_READY;
new->dump.eax = 0;
new->dump.ecx = 0;
new->dump.edx = 0;
@ -372,8 +378,9 @@ tid_t createtask(pid_t pid,u8 *entry, bool kerneltask)
void stoptask(tid_t tid)
{
task *current=findtask(tid);
current->status=TASK_STATUS_STOP;
task *atask=findtask(tid);
if (atask==NULL) return;
atask->status=TASK_STATUS_STOP;
}
/*******************************************************************************/
@ -384,18 +391,24 @@ pid_t createprocess(u8 *src, bool kerneltask)
tid_t previous = current;
current.pid = getfreepid();
current.number = 0;
usepid(current.pid);
process* new=findcurrentprocess();
if (new==NULL) return NULL;
new->pid = current.pid;
new->pdd = virtual_pd_create();
TAILQ_INIT(&new->page_head);
TAILQ_INIT(&new->task_head);
new->iskernel=kerneltask;
setCR3(new->pdd->addr->paddr);
new->entry = loadelf(src, new->pid);
createtask(new->pid,new->entry, new->iskernel);
current = previous;
process* old=findcurrentprocess();
setCR3(old->pdd->addr->paddr);
if (old==NULL) return NULL;
u32 cr3=KERNEL_PD_ADDR;
if (old->pdd!=NULL)
cr3=old->pdd->addr->paddr;
setCR3(cr3);
new->status=PROCESS_STATUS_READY;
return new->pid;
}
@ -406,6 +419,7 @@ void deleteprocess(pid_t pid)
{
stopprocess(pid);
process* aprocess=findprocess(pid);
if (aprocess==NULL) return;
task *next;
TAILQ_FOREACH(next, &aprocess->task_head, tailq)
deletetask(next->tid);
@ -419,11 +433,13 @@ void deleteprocess(pid_t pid)
void runprocess(pid_t pid)
{
process* aprocess=findprocess(pid);
if (aprocess==NULL) return;
if (aprocess->status == PROCESS_STATUS_READY)
{
aprocess->status = PROCESS_STATUS_RUN;
tid_t tid=maketid(pid,0);
tid_t tid=maketid(pid,1);
task *atask=findtask(tid);
if (atask==NULL) return;
atask->status=TASK_STATUS_RUN;
switchtask(tid);
}
@ -435,6 +451,7 @@ void runprocess(pid_t pid)
void stopprocess(pid_t pid)
{
process* aprocess=findprocess(pid);
if (aprocess==NULL) return;
if (aprocess->status == PROCESS_STATUS_RUN)
{
aprocess->status = PROCESS_STATUS_READY;

98
lib/scheduler.c Normal file
View File

@ -0,0 +1,98 @@
/*******************************************************************************/
/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */
/* */
#include "interrupts.h"
#include "types.h"
#include "asm.h"
#include "memory.h"
#include "timer.h"
#include "vga.h"
#include "gdt.h"
static u8 curs[4] = { "-\\|/" };
static u8 curspos = 0;
static u32 time = 0;
/******************************************************************************/
/* Récupère la valeur du timer */
/* SYSCALL
{
"ID":4,
"NAME":"getticks",
"LIBRARY":"libsys",
"INTERNALNAME":"gettimer",
"DESCRIPTION":"Return the internal value of the timer",
"ARGS": [],
"RETURN":"u32"
}
END */
u32 gettimer(void)
{
return time;
}
/******************************************************************************/
/* Handler d'interruption du timer IRQ 0 */
__attribute__ ((noreturn)) void timer_handler(regs *dump)
{
u32 interruption=dump->eip;
exception_stack_noerror *caller = (exception_stack_noerror*) ((u32*)dump->esp+1);
bool noerror,user;
if (caller->cs==SEL_KERNEL_CODE || caller->cs==SEL_USER_CODE)
{
noerror=true;
dump->eip = caller->eip;
dump->cs = caller->cs;
dump->eflags = caller->eflags;
if (dump->cs==SEL_KERNEL_CODE)
{
dump->esp = (u32) caller + sizeof(exception_stack_noerror);
user=false;
}
else
{
dump->esp = (u32) ((exception_stack_noerror_user*) caller)->esp;
dump->ss = (u32) ((exception_stack_noerror_user*) caller)->ss;
user=true;
}
}
else
{
noerror=false;
dump->eip = ((exception_stack*)caller)->eip;
dump->cs = ((exception_stack*)caller)->cs;
if (dump->cs==SEL_KERNEL_CODE)
{
dump->esp = (u32) caller + sizeof(exception_stack);
user=false;
}
else
{
dump->esp = (u32) ((exception_stack_user*) caller)->esp;
dump->ss = (u32) ((exception_stack_user*) caller)->ss;
user=true;
}
}
showchar(0, 0, curs[curspos], 7);
curspos = (curspos + 1) & 0x3;
time++;
irqendmaster();
if (dump->cs==SEL_KERNEL_CODE)
{
setESP(dump);
restcpu_kernel();
}
else
{
setESP(dump);
restcpu_user();
iret();
}
}
/*******************************************************************************/

View File

@ -1,55 +0,0 @@
/*******************************************************************************/
/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */
/* */
#include "interrupts.h"
#include "types.h"
#include "asm.h"
#include "memory.h"
#include "timer.h"
#include "vga.h"
static u8 curs[4] = { "-\\|/" };
static u8 curspos = 0;
static u32 time = 0;
/******************************************************************************/
/* Récupère la valeur du timer */
/* SYSCALL
{
"ID":4,
"NAME":"getticks",
"LIBRARY":"libsys",
"INTERNALNAME":"gettimer",
"DESCRIPTION":"Return the internal value of the timer",
"ARGS": [],
"RETURN":"u32"
}
END */
u32 gettimer(void)
{
return time;
}
/******************************************************************************/
/* Handler d'interruption de la souris IRQ 0 */
void timer(void)
{
cli();
pushf();
pushad();
showchar(0, 0, curs[curspos], 7);
curspos = (curspos + 1) & 0x3;
time++;
irqendmaster();
popad();
popf();
sti();
leave();
iret();
}
/*******************************************************************************/

View File

@ -25,6 +25,8 @@ static u8 errormsg[] =
"\033[150C\033[8D\033[37m\033[1m[\033[31mERREUR\033[37m]\033[0m";
static u8 key = 0;
extern wrapper_timer;
void ok()
{
print(okmsg);
@ -78,20 +80,20 @@ int main(u32 magic, u32 addr)
sti();
ok();
print(" -Installation de l'horloge systeme (IRQ 0)");
setidt((u32) timer, SEL_KERNEL_CODE,
print(" -Installation de l'ordonnanceur et horloge systeme (IRQ 0)");
setidt((u32) &wrapper_timer, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 32);
enableirq(0);
ok();
print(" -Installation du pilote clavier (IRQ 1)");
setidt((u32) keyboard_handler, SEL_KERNEL_CODE,
setidt((u32) &keyboard_handler, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 33);
enableirq(1);
ok();
print(" -Installation du pilote souris (IRQ12+IRQ2)");
setidt((u32) mouse_handler, SEL_KERNEL_CODE,
setidt((u32) &mouse_handler, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 100);
enableirq(2);
enableirq(12);