Autor Thema: Ring-Wechsel und Multitasking!  (Gelesen 9750 mal)

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« am: 23. November 2005, 18:38 »
Hallo,

also ich habe jetzt Code der die GDT, IDT, IRQ's, INT's, A20 setztz und in den PM schaltet. Das funktioniert auch alles wunderbar. Ich habe auch alles bis dahin verstanden (dank den Tutorials hier und meinen Büchern). Ich befinde mich jetzt im Ring0. Codesegment und Datensegment sind gleich. Aber wie wechsele ich z.B. nach Ring3? Und mit Multitasking komme ich noch gar nicht klar. Ich habe das aus meinem Buch und dem Tutorial hier nicht verstanden. Die Deskriptore für die TSS Segmente können in der IDT oder GDT stehen nicht wahr? Aber wofür ist das TR Register? Und wenn ich zum TSS-Segment springe muss ich dann in dem Codesegmentregister die Nummer der z.B. GDT eintragen die dann auf den TSS-Deskriptor zeigt? Ich verstehe das nicht so richtig. Wie wechsle ich einen Task? Ich bin Neuling in sachen PM also habt bitte Verständnis.

Danke!!!
In the Future everyone will need OS-64!!!

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 23. November 2005, 20:19 »
Hallo

Ich bin grad auch beim Multitasking. Ich mach das so. Mein Timer-Interrupt ruft abwechslungsweise zwei TS-Deskriptoren (TaskSegment auch TSS genannt) auf. Jeder dieser TS-Deskriptoren zeigt auf zwei verschiedene TS (TaskSegmente). Im TaskSegment hab ich einfach als CS den jetztigen Code-Deskriptor (ich hab für alles den selben)eingetragen und als IP ein Label in meinem Code. Sobald nun mein Timer-Interrupt den TS-Deskriptor (durch "jmp TS-DESKRIPTOR") aufruft und damit verbunden das TaskSegment lädt, beginnt der Prozessor den Code bei dem angegebenen Label zu verarbeiten. Nach einer Zeit unterbricht der Timer-Interrupt das ganze wieder und lädt den anderen Task....

Das TR Register musst du nur ein einziges Mal laden (weil das TR-Register nachher automatisch bei "jmp TS-DESKRIPTOR" geladen wird), und zwar am Anfang, damit der Prozesser weiss, welcher Task jetzt gerade geladen ist. Ich mach das so:
jmp Task3           ;jump in den Task, welcher in das TR geladen wir
Task3:                ;Label
ltr ax                  ;Das aktuelle TaskSegment laden
sti                      ;jetzt kann der Timer-Interrupt loslegen mit Multitasking


Dafür habe ich in ax den Deskriptor, der auf das Task Segment zeigt, welches als Offset-Adresse "Task3" gespeichert hat.

Ich hoffe ich konnte dir helfen
Nooooooooooos

zacK

  • Beiträge: 216
    • Profil anzeigen
    • http://www.domae.ch
Gespeichert
« Antwort #2 am: 24. November 2005, 08:05 »
tach,

an dieser Stelle möchte ich gerne wissen welche Art von Multitasking ihr gewählt habt. Hardware- oder Software-Multitasking? Oder ein Gemisch? Und die Gründe.

Bis jetzt weiss ich noch nicht so richtig was ich nehmen soll. Bin aber jetztig eher auf der Software Lösung... was meint ihr?

Gruss

Legend

  • Beiträge: 635
    • Profil anzeigen
    • http://os.joachimnock.de
Gespeichert
« Antwort #3 am: 24. November 2005, 10:47 »
Software. Das Prinzip war sehr einfach und schnell umgesetzt.
Bei der Hardware Variante (die ich vorher studieren wollte) hab ich mir nach den Intel Docs nur noch gedacht "Weiche!"!
*post*

zacK

  • Beiträge: 216
    • Profil anzeigen
    • http://www.domae.ch
Gespeichert
« Antwort #4 am: 24. November 2005, 11:24 »
was mich einzig und alein vom puren software multitasking abhaltet ist, das du keine möglichkeit hast befehle wie in, out, hlt, cli zu sperren... oder vertraut ihr euren programmen ;) *riskant*

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 24. November 2005, 12:27 »
Ich hab auch Hardware gewählt, wegen der Sicherheit. Und ich finde die Hardware-Variante auch gut wegen der Einfachheit. Denn eigentlich muss man nur einen Jump auf ein TSS machen und das ist der ganze Zauber.

Gruss
Nooooooooos

zacK

  • Beiträge: 216
    • Profil anzeigen
    • http://www.domae.ch
Gespeichert
« Antwort #6 am: 24. November 2005, 12:56 »
machst du dann ein reines Hardware Task Switching? oder speicherst du irgendow noch name, parent thread, id, priority, state,.....

wie hast du das gestaltet?

Osbios

  • Beiträge: 247
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 24. November 2005, 13:35 »
Zitat von: Legend
Software. Das Prinzip war sehr einfach und schnell umgesetzt.
Bei der Hardware Variante (die ich vorher studieren wollte) hab ich mir nach den Intel Docs nur noch gedacht "Weiche!"!

Die Docs von AMD sollen besser zu lesen sein.

Zitat von: zacK
was mich einzig und alein vom puren software multitasking abhaltet ist, das du keine möglichkeit hast befehle wie in, out, hlt, cli zu sperren... oder vertraut ihr euren programmen *riskant*

ARGH, verdammt, darüber habe ich noch gar nicht nachgedacht.  :?
db 0x55AA

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 24. November 2005, 16:38 »
Klar hat man die Möglichkeit IO-Ports und Ring0 Instructions zu sperren.
Die IO-Bitmap des TSS funktioniert auch mit Software Multitasking, und die normalen Programme laufen auch in Ring3.

Man braucht für das Softwaretasking immer noch ein TSS. In dieses TSS wird der Ring0-SS und der Ring0-ESP eingetragen. Jedes Programm kriegt einen eigenen Ring0-Stack. Das TSS läd man dann mit LTR Wenn jetzt der Timer Interrupt aufgerufen wird, ruft man den Scheduler auf, um einen Thread zu finden, den man aufruft. Man pushed die Register auf den Kernel-Stack und speichert den aktuellen ESP in der aktuellen Thread-Struct oder was auch immer. Man wechselt  eventuell die Pagedirectories, trägt dann in der TSS den Kernel-Stack ein, und setzt ESP auf den Kernel-Stack des neuen Threads. Dann popt man alle Parameter und führt IRET aus, um in die Anwendung zu springen.

zacK

  • Beiträge: 216
    • Profil anzeigen
    • http://www.domae.ch
Gespeichert
« Antwort #9 am: 24. November 2005, 17:02 »
was braucht man mindestens für ein software task switching mit io-bitmap und ring0 <- kernel und ring3 progi?

tss, struct für jeden task....?!
hat da jemand ein gute tutorial?

thx

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 24. November 2005, 17:35 »
Starten des Multitaskings
Du erstellst wie unten beschrieben einen neuen Prozess für den Kernel. Dann brauchst du eine TSS. Da trägst du dann Ring0 SS und Ring0 ESP des Kernelstack vom Prozess, der grad läuft ein. Beachte, das in das TSS nicht der ESP eingetragen wird, sondern der Pointer auf das unterste Stackelement. In der GDT brauchst du einen TSS-Descriptor, der auf diese TSS zeigt. Du lädst nun mit LTR das TSS.

Einen neuen Prozess erstellen
Als erstes erstellst du einen neuen Kernelstack für den Prozess, und pushest auf ihn die Werte der Register, die der Prozess haben soll, wenn er gestartet wird. Beim Kernelprozess ist das nicht notwendig, da er ja grade läuft.
Jetzt erstellst du für jeden Prozess eine struct, in der du Informationen zum Prozess speicherst. Dort trägst du das Pagedirectory des Prozesses ein, sowie   den Stack den du eben erstellt hat.

Tasks per Interupt wechseln
Du trägst in der IDT einen Handler für den Interupt ein, den du benutzen willst. (z.B. Timer Interrupt (IRQ 0)) Der Handler pusht nun alle Register, ruft den scheduler auf, wechselt die Stacks und popt die Register wieder.

C Beispielcode zum Stackerstellen:
unsigned long *stackbase = malloc (STACK_SIZE);
unsigned long *stackptr = stackbase;
// die werde die vom interrupt gate gepushed werden, werden später mit iret gepopt.
*stackptr = ss; // automatisch vom interrupt gate gepushed
stackptr--;
*stackptr = esp; // automatisch vom interrupt gate gepushed
stackptr--;
*stackptr = eflags; // automatisch vom interrupt gate gepushed
stackptr--;
*stackptr = cs; // automatisch vom interrupt gate gepushed
stackptr--;
*stackptr = eip; // startaddresse der anwendung, wird automatisch vom interrupt gate gepushed
stackptr--;
*stackptr = eax;
stackptr--;
*stackptr = ebx;
stackptr--;
*stackptr = ecx;
stackptr--;
*stackptr = edx;
stackptr--;
*stackptr = esi;
stackptr--;
*stackptr = edi;
stackptr--;
*stackptr = ds;
stackptr--;
*stackptr = es;
stackptr--;
*stackptr = fs;
stackptr--;
*stackptr = gs;
stackptr--;


Assembler-Beispielcode
taskswitch_interupt:
push eax
push ebx
push ecx
push edx
push esi
push edi
push ds
push es
push fs
push gs
mov [_thread_stack], esp
; die funktion _schedule hat folgende aufgaben:
; sie speichert die globale variable _thread_stack in die prozess-struct
; dann wählt sie den neuen prozess aus,
; wechselt das pagedirectory,
; speichert seinen esp in _thread_stack
; und speichert die basis des stacks in das tss
call _schedule

; eoi senden
; muss vor dem popen von eax gemacht werden
mov al, 0x20
out 0x20, al

mov esp, [_thread_stack]
pop gs
pop fs
pop es
pop ds
pop edi
pop esi
pop edx
pop ebx
pop eax
iret

zacK

  • Beiträge: 216
    • Profil anzeigen
    • http://www.domae.ch
Gespeichert
« Antwort #11 am: 24. November 2005, 19:42 »
vielen dank Super Saiyajin 7 Gohan... :D

was ist muss ich dann machen wenn ich ein interrupt ausführen will wenn ein prozess aktiviert ist?

und wann muss ich mit ltr den tss laden? dass ist mir noch voll unklar...

vielen dank nochmal!
gruss

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 24. November 2005, 20:01 »
Garnichts, die Interupthandler funktionieren so wie ohne Multitasking. Du solltest nur in den Interupthandlern darauf achten, das du alle Register, die du benutzt auch sicherst und wiederherstellst, damit der Prozess vom Handler nichts mitbekommt, aber das musst du ja auch machen, wärend nur der Kernel aktiv ist.

Du musst das TSS nur einmal laden, bevor du das Multitasking benutzt, danach musst du nur den Ring0-ESP im TSS updaten, das TSS jedoch nicht neuladen.

zacK

  • Beiträge: 216
    • Profil anzeigen
    • http://www.domae.ch
Gespeichert
« Antwort #13 am: 24. November 2005, 22:01 »
nein, ich meine mein kernel samt irq int ist auf ring0. nun rüft ein task ein int auf. dann muss ich ja ein ring3-ring0 sprung machen mittels TasGate oder k.A was...

thx

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #14 am: 25. November 2005, 00:13 »
Zitat von: zacK
nein, ich meine mein kernel samt irq int ist auf ring0. nun rüft ein task ein int auf. dann muss ich ja ein ring3-ring0 sprung machen mittels TasGate oder k.A was...

thx
Nein, im Interrupt Deskriptor gibst du doch schon den Level an den man benötigt um auf den Interrupthandler zugreifen zu können. Dann trägst du dort halt 3 ein (2, 1 und 0 funktionieren dann auch). Also müsste doch so sein oder? Wenn das nicht so ist dann verbessert mich bitte.
In the Future everyone will need OS-64!!!

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 25. November 2005, 07:06 »
Ja, du musst nur das Privileglevel im Interrupthandler ändern.

zacK

  • Beiträge: 216
    • Profil anzeigen
    • http://www.domae.ch
Gespeichert
« Antwort #16 am: 25. November 2005, 08:25 »
aber ich möchte meinen programmen mit einem IO_Bitmap spezielle sachen verbieten... z.B in und out. Dann macht der User etwas mit der Maus -> IRQ12 und wenn ich das EOI senden will ist fertig mit Ring3...
oder was genau kann man überhaupt mit dem Bitmap setzten?

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 25. November 2005, 10:12 »
Eben, du kannst deinen Programmen per IO_Bitmap (bei Software Multitasking im TSS) verschiedene Ports verbieten oder erlauben.

Und wenn ein Interrupt (IRQ) aufgerufen wird, dann wird das entsprechende Gate in der IDT (am Anfang definiert) aufgerufen, und da ist es scheiss egal in welchem Ring du dich befindest, solange du im Gate-Deskriptor eingetragen hast, dass der Interrupt vom Ring 3 aufgerufen werden kann.

Das Gate in der IDT springt nachher zu deinem Handler, der ja im Kernel ist (oder etwa nicht) und der ja im Ring 0 läuft, somit kannst du das EOI ohne Bedenken senden.

Gruss
Noooooooooos

zacK

  • Beiträge: 216
    • Profil anzeigen
    • http://www.domae.ch
Gespeichert
« Antwort #18 am: 29. November 2005, 12:54 »
ich habe immer noch verständigungsprobleme mit dem softwaremultitasking mit tss. ohne habe ich es schon geschaft.

was brauch ich nun damit ich tss und ring3 programme laufen kann?

TaskGate?
TSS?

vielen dank!

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #19 am: 29. November 2005, 14:38 »
Zitat
softwaremultitasking mit tss
Nennt sich dies nicht Hardwaremultitasking?
In the Future everyone will need OS-64!!!

 

Einloggen