Autor Thema: Userspace  (Gelesen 5382 mal)

sebi2020

  • Beiträge: 130
    • Profil anzeigen
    • Infortus OS
Gespeichert
« am: 04. January 2010, 21:35 »
Ich habe mal eine frage, was die Privilegien von Progarmmen/Threads angeht. Ich bin gerade bei dem OS-dev für einsteiger beim multitasking->userspace.
Und ich wollte fragen, wie dass mit Privilegien in interrupts aussieht. In welchem Ring läuft so ein Interrupt ab?
Mich intressiert dass, weil so wie das im Tutorial aussieht reicht ein
mov ax,0x10
mov ds,ax
mov ...
jmp 0x8:continue
continue:
aus um im Ring 0 zu laufen und danach wird in Ring drei gewechselt.
Nur würde ich ja dann beim nächsten aufrufen des Interrupts doch von Ring 3 nach Ring 0 wechseln... und dass wundert mich, weil wenn ein Interrupt dann im Ring 3 läuft könnte ich doch in programmen auch einfach nen:
mov ax,0x10
mov ds, ax
mov ...
jmp 0x8:continue
continue:
machen und schon hätte das Programm Kernel-Privilegien. Oder wie ist dass? Ich bin da noch nicht so ganz schlau :)

mfg sebi
« Letzte Änderung: 04. January 2010, 21:51 von sebi2020 »
Please press any-key...
Verflucht wo ist any-key? hier? ach Mist, das war Escape...

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #1 am: 04. January 2010, 21:56 »
Ein jmp/call mit einem Selektor, der auf einen normalen Ring0 Codesegmentdeskriptor verweist, darf nur aus Ring0 heraus verwendet werden. Falls das ein Ring3-Code macht bekommst du einen General Protection Fault. Man kann einen Ringwechsel von 3 auf 0, aber (wenn man es unbedingt mit jmp/call will) über ein Callgate in der GDT machen. Es hat sich aber wahrscheinlich als performanter herausgestellt das über einen Interrupt zu machen, also ein Interrupt/Trap-Gate in der IDT.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

sebi2020

  • Beiträge: 130
    • Profil anzeigen
    • Infortus OS
Gespeichert
« Antwort #2 am: 04. January 2010, 22:08 »
Ein jmp/call mit einem Selektor, der auf einen normalen Ring0 Codesegmentdeskriptor verweist, darf nur aus Ring0 heraus verwendet werden. Falls das ein Ring3-Code macht bekommst du einen General Protection Fault. Man kann einen Ringwechsel von 3 auf 0, aber (wenn man es unbedingt mit jmp/call will) über ein Callgate in der GDT machen. Es hat sich aber wahrscheinlich als performanter herausgestellt das über einen Interrupt zu machen, also ein Interrupt/Trap-Gate in der IDT.
naja, also dass heißt von ring 3 auf 0 wechseln funktionert nur in einem Interrupt-Gate bzw. trap -gate, oder mit nem call-gate Also ich frag mich grad wie man dass sonst anstellen will... und naja "wenn man es unbedingt mit einem jmö/call will). Also ich habe dass jetzt mit nem far-jump gemacht weil mir keine andere möglichkeit eingefallen ist auf anderem weg das code-segment zu wechseln. mov ax,0x8 ... mov cs,ax funktioniert definitiv nicht, zuimindest bei mir nicht :D
« Letzte Änderung: 04. January 2010, 22:10 von sebi2020 »
Please press any-key...
Verflucht wo ist any-key? hier? ach Mist, das war Escape...

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #3 am: 04. January 2010, 22:27 »
Zitat von: sebi2020
Also ich frag mich grad wie man dass sonst anstellen will...
Strenggenommen ginge es auch noch per Taskgate und mittels solcher speziellen Funktionen wie "sysenter" oder "sysret" (und bestimmt auch noch mehr), aber das nur so nebenbei :wink:

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 04. January 2010, 22:50 »
Wenn ich mich grad nicht sehr täusche, kannst du mit einem Far-Jump den Ring nicht wechseln (es gibt Ausnahmen, die hier aber nicht relevant sind). In der Praxis machst du den Ringwechsel von 0 nach 3 über iret und den von 3 nach 0 über int (bzw. automatisch per Hardwareinterrupt oder Exception).

In welchem Ring du nach einem Interrupt bist, hängt von dem cs-Selektor ab, den du für den jeweiligen Interrupt in der IDT eingetragen hast.
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 #5 am: 05. January 2010, 00:43 »
achso, naja, das war jetzt auch nur ne vermutung, weil ich so zumindest das code-segment bei ring 0 damit geladen habe, ganz am anfang.
irgendwie konnt ich jetzt noch nich ganz finden, wo das codesegment, mit nem ring 3 codeselektor geladen wird. also nen iret und so is ja alles im interrupt-handler drin, aber irgendwoher muss er doch den selektor für cs haben.
[EDIT] also ich rede hiervon: http://lowlevel.brainsware.org/wiki/index.php/Teil_6_-_Multitasking#Userspace
« Letzte Änderung: 05. January 2010, 00:45 von sebi2020 »
Please press any-key...
Verflucht wo ist any-key? hier? ach Mist, das war Escape...

SHyx0rmZ

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 05. January 2010, 11:58 »
Im Interrupt Deskriptor steht drin, in welchem Code Segment der Interrupt ausgeführt wird. Beim Aufrufen der Interrupt Routine werden CS und EIP (und noch ein paar andere Register, ist aber im PM anders als im LM) gespeichert und beim iret wieder geladen, so, dass dann in das gleiche Code Segment zurückgesprungen wird, das vor dem Interrupt aktiv war.

PS: mox cs, ax ist eine verbotene Operation ;-)
@X="krJhbuaesrytre c a cnR.ohut";while@X[/(..)(.)/];@X=@X[3..-1]+$1;print$2;end
"Scheiß auf Perl, wir haben Kekse" - Emperor Ruby

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 05. January 2010, 12:41 »
Hast du denn verstanden, wie das Multitasking an sich funktioniert, oder genauer gesagt das Starten der Tasks? In init_task setzt du einen Stack mit dem Prozessorzustand auf, der dann im Interrupthandler eingelesen wird. Die letzten paar Felder davon werden vom iret benutzt, um den Sprung in den Task zu machen. Die eigentlich entscheidende Zeile, damit du in Ring 3 kommst, ist die hier:
.cs  = 0x18 | 0x03,Der Rest am zusätzlichen Code für Multitasking mit Userspace ist nur dafür da, dass das nicht gleich einen Absturz provoziert. ;)
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: 05. January 2010, 15:25 »
Hast du denn verstanden, wie das Multitasking an sich funktioniert, oder genauer gesagt das Starten der Tasks? In init_task setzt du einen Stack mit dem Prozessorzustand auf, der dann im Interrupthandler eingelesen wird. Die letzten paar Felder davon werden vom iret benutzt, um den Sprung in den Task zu machen. Die eigentlich entscheidende Zeile, damit du in Ring 3 kommst, ist die hier:
.cs  = 0x18 | 0x03,Der Rest am zusätzlichen Code für Multitasking mit Userspace ist nur dafür da, dass das nicht gleich einen Absturz provoziert. ;)
oh doch verstehe, ich hab das wohl überlesen ;-). aber ich überleg noch die init_task funktion so umzuschreiben das ich ring 0 tasks erstellen kann oder ring 3 tasks, da es praktisch wäre nicht nur ring 3 tasks zu haben :).

mfg Sebi
Please press any-key...
Verflucht wo ist any-key? hier? ach Mist, das war Escape...

sebi2020

  • Beiträge: 130
    • Profil anzeigen
    • Infortus OS
Gespeichert
« Antwort #9 am: 06. January 2010, 20:37 »
Versteh ich dass den richtig, wenn es heißt das man nur esp0 und ss0 aus dem tss braucht, dass ich dann diese mit werten belege und den rest einfach auf 0 lasse?
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 #10 am: 06. January 2010, 20:47 »
Ja, kannst du machen. Du kannst aber auch 42 oder 1337 reinschreiben, wenn dir das mehr Spaß macht. Mit Softwaremultitasking werden die restlichen Felder einfach nicht benutzt (außer die IO-Bitmap, aber die brauchst du jetzt wohl erstmal noch nicht).
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 #11 am: 06. January 2010, 20:51 »
ah okay, und  eine frage hätteich da noch, ich versteh diese anweisung nicht:
asm volatile("ltr %%ax" : : "a" (5 << 3));soll das ein selektor für den deskriptor in der gdt sein? und wenn ja wofür steht die 5 und wofür die 3; warum schreibt man nicht gleich 40 rein?

mfg Sebi
« Letzte Änderung: 06. January 2010, 20:52 von sebi2020 »
Please press any-key...
Verflucht wo ist any-key? hier? ach Mist, das war Escape...

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #12 am: 06. January 2010, 21:09 »
Jo, das ist ein Selektor. Siehe dazu den entsprechenden Wikieintrag:
Zitat von: „Task State Segment“
Um ein TSS für den Ringwechsel benutzen zu können, muss es vorher mit ltr <Selektor> geladen werden.

Und zur Frage, wozu das so geschrieben wurde: Siehe Wiki zum Thema Selektoren.

Wie du siehst, steht der Index des Eintrags drei Bits nach links geshiftet im Selektor. Und das drückt die Zeile aus: Der Index ist 5, das ganze wird um drei Bits nach links geshiftet (in der GDT, deshalb ist Bit 2 nicht gesetzt und außerdem ohne RPL (bzw. mit RPL=0), deshalb sind auch Bits 0 und 1 nicht gesetzt). Man könnte auch 40 schreiben, ja. Aber dann würde das eben nicht so deutlich.

sebi2020

  • Beiträge: 130
    • Profil anzeigen
    • Infortus OS
Gespeichert
« Antwort #13 am: 06. January 2010, 22:10 »
Zitat
und außerdem ohne RPL (bzw. mit RPL=0), deshalb sind auch Bits 0 und 1 nicht gesetzt)
aber wieso ohne RPL, dass versteh ich nicht. Es geht doch im Ring 3, wieso dann RPL 0?
Please press any-key...
Verflucht wo ist any-key? hier? ach Mist, das war Escape...

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #14 am: 07. January 2010, 06:16 »
Ich glaub dafür muss man das ganze andersrum aufziehen: Das DPL des Task-State-Segments sollte 0 sein, sonst kann ein Userspaceprogramm mit call/jmp den Task wechseln (siehe auch fh-zwickau unter Task-Wechsel). Wenn das DPL 0 ist kann aber das RPL im Selektor nicht einfach kleiner sein, sondern muss auch 0 sein. Die andere Seite der Medaille ist, dass das RPL des TSS-Selektors nichts darüber aussagt in welchem Ring der Task, der von diesem Segment beschrieben wird läuft (das wird über das RPL des darin enthaltenen CS-Selektors geregelt), sondern eben nur darüber wer auf dieses TSS zugreifen darf.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

sebi2020

  • Beiträge: 130
    • Profil anzeigen
    • Infortus OS
Gespeichert
« Antwort #15 am: 09. January 2010, 13:55 »
achso okay, verstehe.
ich hab nur ne frage, warum wird die tss - esp0 mit new_cpu +1 belegt. Weil wenn ich jetzt mal auf die struktur schaue würde ich esp0 somit mit ebx belegen aber nicht mit esp. ich mein die umgekehrte reinfolge gilt vielleicht beim stack, das ich das umgekehrt auf den stack leg, aber dohc nicht beim zugriff auf die struktur  :?

mfg Sebi
Please press any-key...
Verflucht wo ist any-key? hier? ach Mist, das war Escape...

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #16 am: 09. January 2010, 14:34 »
schedule gibt die Struktur zurück in der beim Interrupt der Taskstatus gespeichert werden soll (bzw. später daraus wiederhergestellt werden soll), da der Stack aber von oben nach unten wächst, möchte man an das Ende dieser Struktur (und kann dann über ein push direkt in die Struktur speichern) und exakt das erreicht man über new_cpu + 1.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

sebi2020

  • Beiträge: 130
    • Profil anzeigen
    • Infortus OS
Gespeichert
« Antwort #17 am: 09. January 2010, 14:46 »
also ich verstehs immer noch nicht ganz die struktur sind ungefähr so aus:
struct cpu_state
{
   uint32_t eax;
  ....
// von cpu gesichert
  uint32_t eip;
  ...
}
Heißt an der niedrigeren adresse liegt eax,ebx usw, an den  hohen eip usw..

Im Stack wird aber als erstes element ss gespeichert. Heißt eip, esp , ss usw. sind an der höheren adresse gepsichert.
Wenn ich jetzt die Adresse von new_cpu + 1 übergebe, müsste man aber zu eax + 1 byte kommen,  und nciht zu esp. Also ich verstehs nicht, die Adresse von cpu_state liegt doch am ende des stacks, und nicht  am anfang  :?
Please press any-key...
Verflucht wo ist any-key? hier? ach Mist, das war Escape...

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #18 am: 09. January 2010, 14:49 »
new_cpu + 1 springt sizeof(cpu_state) Bytes weiter (Pointerarithmetik!), also ans Ende der Struktur.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

 

Einloggen