Autor Thema: Software Multitasking  (Gelesen 13731 mal)

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« am: 13. May 2005, 14:55 »
Hi, ich habe hier ein paar Fragen über Software Multitasking:

Wenn ich das richtig verstanden habe sollte das tasking so funktionieren:
-> der scheduler wird von irq 0 aufgerufen
-> alle register werden auf den stack gepusht
-> die stackpointer werden auf den stack des tasks geändert
-> alle register werden gepopt
-> der task wird per iret aufgerufen ( ? )

Woher weiß der Prozessor nun, welches privileg-level der task hat? Hängt das vom Codesegment ab, das der task verwendet, oder wie wird das gehandhabt?

Wenn ich jetzt in einem level 3 task einen interrupt aufrufe, brauche ich ja, soweit ich weiß, ein TSS. Wo wird dieses TSS jetzt in der GDT abegelegt?

Ich habe weder ein Tutorial oder mit der Suchfunktion etwas gefunden, was ich gebrauchen könnte. :(

Legend

  • Beiträge: 635
    • Profil anzeigen
    • http://os.joachimnock.de
Gespeichert
*post*

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 15. May 2005, 15:13 »
Danke für den Link, das Tutorial hat mir sehr geholfen^^.

Ich habe es jetzt geschaft das Multitasking einzubauen, jedoch funktioniert irgentwie der Ring 0 -> Ring 3 Change nicht, oder umgekehrt. Wenn ich Prozesse im Ring 0 laufen laufen lasse funktioniert aber alles.

Bochs liefert mir den Fehlercode:
fetch_raw_descriptor: LDTR.valid=0

Der Fehler wird offensichtlich beim 1. Taskswitch ausgelöst, beim Switch vom Idle zum "test" Prozess

Hier ist mein Code:

Diese Prozeduren handlen die Prozesse und wählen den nächsten Task aus:

#include "memory.h"
#include "process.h"

extern void updateGDT();

tTSS kernelTSS;
tProcess *parentProcess;

tProcess *currentProcess;
unsigned long currentStack;

unsigned char enableSchedule;

tProcess *createProcess( unsigned char *id, void *entry ) {
tProcess *process = allocateSystemMemory( sizeof( tProcess ) );
memset( process, 0, sizeof( tProcess ) );

strcpy( process->processID, id );

memset( process->processKernelStack, 0, 256 );
memset( process->processUserStack, 0, 256 );

unsigned long *stack = process->processKernelStack + 256;
*(--stack) = 0x20; // User stack selector
*(--stack) = 0;(unsigned long)process->processUserStack + 256; // User ESP
*(--stack) = 0x200; // EFLAGS
*(--stack) = 0x18; // User code selector
*(--stack) = (unsigned long)entry; // EIP
*(--stack) = 0; // EDX
*(--stack) = 0; // ECX
*(--stack) = 0; // EBX
*(--stack) = 0; // EAX
*(--stack) = 0; // (User) ESP - get's discarded while popping
*(--stack) = 0; // EBP
*(--stack) = 0; // EDI
*(--stack) = 0; // ESI
*(--stack) = 0x20; // DS
*(--stack) = 0x20; // ES
*(--stack) = 0x20; // FS
*(--stack) = 0x20; // GS

process->processStack = stack;
process->next = 0;

return process;
}

void testProcess() {
while( 1 );
}

void initScheduler() {
// create idle process
parentProcess = allocateSystemMemory( sizeof( tProcess ) );
memset( parentProcess, 0, sizeof( tProcess ) );
strcpy( parentProcess->processID, "system/idle" );
parentProcess->processStack = parentProcess->processKernelStack + 256; //stack;

// create test process
tProcess *proc = createProcess( "application/test", testProcess );
parentProcess->next = proc;

// setup tss for ring change
memset( &kernelTSS, 0, sizeof( tTSS ) );

kernelTSS.esp_ring0 = (unsigned long)parentProcess->processKernelStack + 256;
kernelTSS.cs = 0x18;
kernelTSS.ds = 0x20;
kernelTSS.es = 0x20;
kernelTSS.fs = 0x20;
kernelTSS.gs = 0x20;
kernelTSS.ss_ring0 = 0x10;

updateGDT();

currentProcess = parentProcess;
enableSchedule = 1;
}

void schedule() {
if( enableSchedule == 1 ) {
//if( currentProcess == 0 ){
// currentProcess = parentProcess;
//}else{
currentProcess->processStack = (unsigned long*)currentStack;
//}

if( currentProcess->next == 0 ) {
currentProcess = parentProcess;
}else{
currentProcess = currentProcess->next;
}

printk( "Task %s\n", currentProcess->processID );

currentStack = (unsigned long)currentProcess->processStack;
kernelTSS.esp_ring0 = (unsigned int)currentProcess->processKernelStack + 256;
}
}


Die Prozess Struktur sieht so aus:
256 Einträge pro Stack ist zwar schon etwas wenig, sollte aber für Testzwecke reichen^^
struct tProcess {
unsigned char processID[32];

unsigned long *processDirectory;

tMemory processMemory;

unsigned long processKernelStack[256];
unsigned long processUserStack[256];
unsigned long *processStack;

struct tProcess *next;
};


Das hier ist mein Scheduler:
[global _isr_32]
[extern _schedule]
[extern _currentStack]
_isr_32:

cld

pushad
push ds
push es
push fs
push gs

;change the task
;save old esp
mov [_currentStack], esp
call _schedule
mov esp, [_currentStack]

mov al, 0x20
out 0x20, al

pop gs
pop fs
pop es
pop ds
popad

iret


Meine GDT baue ich so auf:
[bits 32]
[section .text]

[global _updateGDT]
[extern _kernelTSS]

DESC_4K_GRAN EQU   128
DESC_BIG EQU    64

DESC_32BIT EQU    8
DESC_TSS EQU     1

DESC_PRESENT EQU   128
DESC_DPL3 EQU 64+32
DESC_DPL0 EQU     0
DESC_SEGMENT EQU    16
DESC_CODE EQU     8
DESC_DATA EQU     0
DESC_DATA_EXPAND_DOWN EQU     4
DESC_CODE_READ_EXEC EQU     2
DESC_DATA_READ_WRITE EQU     2
DESC_ACCESSED EQU     1

_updateGDT:
; fill in tss value
push eax

lgdt [GDT_DESC]

mov eax, _kernelTSS
mov [DESC_KERNEL_TSS+2], al
mov [DESC_KERNEL_TSS+3], ah
shr eax, 16
mov [DESC_KERNEL_TSS+4], al
mov eax, _kernelTSS
shr eax, 24
mov [DESC_KERNEL_TSS+7], al

mov ax, 0x28
ltr ax

pop eax

retn

GDT_START:
DESC_NULL: ;0x0
dd 0
dd 0

DESC_KERNEL_CODE: ;0x8
db 255
db 255
db 0
db 0
db 0
db DESC_PRESENT + DESC_DPL0 + DESC_SEGMENT + DESC_CODE + DESC_CODE_READ_EXEC
db DESC_4K_GRAN + DESC_BIG + 0xF
    db 0
   
    DESC_KERNEL_DATA: ;0x10
db 255
db 255
db 0
db 0
db 0
db DESC_PRESENT + DESC_DPL0 + DESC_SEGMENT + DESC_DATA + DESC_DATA_READ_WRITE
db DESC_4K_GRAN + DESC_BIG + 0xF
    db 0
   
DESC_USER_CODE: ;0x18
db 255
db 255
db 0
db 0
db 0
db DESC_PRESENT + DESC_DPL3 + DESC_SEGMENT + DESC_CODE + DESC_CODE_READ_EXEC
db DESC_4K_GRAN + DESC_BIG + 0xF
    db 0
   
    DESC_USER_DATA: ;0x20
db 255
db 255
db 0
db 0
db 0
db DESC_PRESENT + DESC_DPL3 + DESC_SEGMENT + DESC_DATA + DESC_DATA_READ_WRITE
db DESC_4K_GRAN + DESC_BIG + 0xF
    db 0
   
    DESC_KERNEL_TSS: ;0x28
db 104
db 0
db 0
db 0
db 0
db DESC_PRESENT + DESC_DPL0 + DESC_32BIT + DESC_TSS
db DESC_BIG
db 0

GDT_END:

GDT_DESC:
dw GDT_END - GDT_START
dd GDT_START
[/code]

 

Einloggen