Autor Thema: TSS aus Tutorial Multitasking  (Gelesen 3833 mal)

sebi2020

  • Beiträge: 130
    • Profil anzeigen
    • Infortus OS
Gespeichert
« am: 29. June 2011, 09:14 »
Ich weis, Köpft mich, wenn ich dafür jetzt ein extra Thread aufmache (könnt ihn ja wieder löschen)... aber eine Sache würde mich zum Multitasking Tutorial noch intressieren.

Dort steht irgendwo:
.esp0 = (new_cpu +1)
Der Stack wächst doch nach unten, oder? und ein pop erhöht doch die adresse, oder? Wenn dem so ist, warum dann + 1.  Ich dachte die CPU möchte den Zustand vielleicht auch noch mal vom Stack holen. Aber gerade mit diesem Plus 1 würde das doch verhindert, oder? oO

Oder geht es darum, den Taskzustand auf den Stack zu schieben? bzw ihn in new_cpu abzuspeichern... ?
« Letzte Änderung: 29. June 2011, 09:30 von sebi2020 »
Please press any-key...
Verflucht wo ist any-key? hier? ach Mist, das war Escape...

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 29. June 2011, 09:31 »
Neues Thema, neuer Thread. Passt schon.

Für eine eingeschränkte CPU mit ein paar Registern weniger (damit ich hier in endlicher Zeit ein Beispiel eingetippt bekomme ;)), sieht dein Stack ja vor dem Einsprung irgendwie so aus:

0xffc: eax
0xff8: ebx
0xff4: cs
0xff0: eip
0xfec: ss
0xfe8: esp <-- Stackpointer hier

Nach dem Einsprung in den Task sind diese Werte alle vom Stack gepopt und in Register geladen worden. Der Stackpointer müsste jetzt auf 0x1000 zeigen, geht ja aber beim iret verloren, weil der Userspace-Stackpointer geladen wurde (der an 0xfe8 im Beispiel). Genau diesen Stackpointer auf 0x1000 willst du wiederherstellen, wenn du bei einem Interrupt in den Kernelspace wechselst. Und der Stackpointer nach dem Ringwechsel kommt eben aus dem TSS, also muss man diese 0x1000 vorher dort rein legen. Nach dem Stackwechsel legt der Prozessor wieder die Rücksprunginformation auf den Stack, dein Interrupt-Stub packt die Register dazu und du bist wieder bei dem Bild von oben angelangt, wenn du in den C-Kernelcode einspringst.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

sebi2020

  • Beiträge: 130
    • Profil anzeigen
    • Infortus OS
Gespeichert
« Antwort #2 am: 29. June 2011, 09:58 »
Also, um dir folgen zu können ( ich weis ich stell mich manchmal ziemlich dumm an...) aber versuch ich jetzt noch mal aus meinem Verständnis das ganze zu beschreiben...

Ich hab den normalen Kernel-Stack erstmal. Wenn nun der Interrupt auftritt sicher die CPU ein paar Register (äh EIP, ESP usw. ??) von selbst, dann sicher ich ja im Assemblercode noch die Interrupt Nummer und bei Exceptions die Fehlernummer, die bei einem Timerinterrupt allerdings einfach null ist. So weit so gut. Dann push ich noch den aktuellen esp auf den Stack als Parameter für die Interuptbehandlungsfunktion... Die Sachen die ich jetzt auf dem Stack liegen habe, bilde ich ja mit der cpu struct ab. soweit richtig?!

Dann bin ich nun im Interrupt. Mein Scheduler holt den nächsten Task, der sagen wir jetzt mal ein Ring0 Task ist und der vorher war ein Userspace Task... nun trag ich im TSS bei esp0 den neuen Task ein und gehe ans ende dieser Struktur... so nun geb ich die Adresse des neuen Taskzustandes zurück. Setze den Stack-Pointer auf die neue Taskstruktur nehm noch den Fehlercode und die Interrupt nummer vom Stack, lade die Segmentregister neu und springe nun mit iret aus dem Interrupt. Das müsste doch dann meine Taskstruktur vom Stack nehmen und EIP (wie in deinem Beispiel jetzt auf 0x1000) liegen. Soweit wieder richtig?

Nun müsste doch der ESP = dem ESP im TSS sein... aber ab wann spielt den dann jetzt der ESP - Pointer im TSS eine Rolle. Ich hab grad einen Ringwechsel gemacht, aber was tut jetzt hier der ESP aus dem TSS, das hab ich irgendwie noch nicht ganz verstanden. Oder ich hab hier nur kompletten blödsinn geschrieben :)
Please press any-key...
Verflucht wo ist any-key? hier? ach Mist, das war Escape...

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 29. June 2011, 10:17 »
Doch, das passt alles soweit.

Das TSS kommt dann zum Zug, wenn du in Ring 3 einen Interrupt bekommst und damit in Ring 0 zurückwechselst. Woanders kriegt der Prozessor ja das ss/esp für Ring 0 nicht her.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

sebi2020

  • Beiträge: 130
    • Profil anzeigen
    • Infortus OS
Gespeichert
« Antwort #4 am: 29. June 2011, 10:33 »
Wenn jetzt in Ring 3 ein Interrupt ausgelöst wird. Auf welchem Stack liegt den dann das ganze? Auf dem Userstack?
Also ich bin verwirrt, weil ich lade den ESP doch selber ... : mov esp, eax
Also ich glaub ich habs verstanden. Moment.
Wenn ich jetzt in nen Ring 3 Task bin, hab ich den Userstack-Pointer geladen, und weil er bei einem wechsel von ring 3 nach ring 0 sich den esp nicht vom stack holt, muss ich ihn in esp0 sichern, so wie er vorher war, der kernel stack. So?
« Letzte Änderung: 29. June 2011, 10:42 von sebi2020 »
Please press any-key...
Verflucht wo ist any-key? hier? ach Mist, das war Escape...

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 29. June 2011, 10:44 »
Auf dem Kernelstack natürlich. Wäre irgendwie doof, wenn der Userspace (zum Beispiel aus einem anderen Thread) darauf Einfluss nehmen könnte. Also doof im Sinn von Sicherheitsproblem, weil der Userspace damit Ring-0-Rechte kriegen könnte, wenn er die Rücksprungadresse modifiziert.

Mit dem mov wechselst du nur vom Kernelstack des einen Tasks zum Kernelstack des anderen Tasks. Auf diesem Kernelstack liegt jeweils nochmal der Userspace-Stackpointer (das gehört zu den Daten, die ein Interrupt automatisch pusht und die beim iret wiederhergestellt werden).
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

sebi2020

  • Beiträge: 130
    • Profil anzeigen
    • Infortus OS
Gespeichert
« Antwort #6 am: 29. June 2011, 10:49 »
Hm, aber das heißt der Kernelstack für jeden Prozess ist nur für die CPU strukturen und Interrupts zuständig, oder? Also bei den Userspace Tasks mein ich.
Please press any-key...
Verflucht wo ist any-key? hier? ach Mist, das war Escape...

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 29. June 2011, 10:59 »
Und als ganz normaler Stack für den ganzen Code, der im Kernel läuft. Syscalls und so weiter.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

sebi2020

  • Beiträge: 130
    • Profil anzeigen
    • Infortus OS
Gespeichert
« Antwort #8 am: 29. June 2011, 11:12 »
Aber ich allozier doch für jeden Task ein extra Stack... oO
Bei Ring 0 Tasks nur ein Kernelstack, bei Usermode Tasks ein Kernelstack und einen Userstack... Oder meinst du mit Ring0 Code, der im Kernel läuft? Weil ich hab ja eine Init funktion. Da ist der esp noch auf 0x200000 gesetzt. Aber sobald ich in die Multitasking Funktion springe, hab ich ja einen neuen Stack.
« Letzte Änderung: 29. June 2011, 11:22 von sebi2020 »
Please press any-key...
Verflucht wo ist any-key? hier? ach Mist, das war Escape...

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 29. June 2011, 12:08 »
Sobald du mal angefangen hast, Multitasking zu machen, wird dein alter Stack an 0x200000 nie wieder benutzt. Es sei denn, du recyclest ihn für den Idle-Task oder sowas. Kernelcode wird ja sobald alles initialisiert ist, nur noch von Interrupthandlern aus ausgeführt. Das heißt, dass du immer auf dem Kernelstack bist, der zum aktiven Prozess gehört.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

 

Einloggen