Autor Thema: Ringwechsel und VM86  (Gelesen 6373 mal)

Hauke

  • Beiträge: 113
    • Profil anzeigen
Gespeichert
« am: 17. March 2009, 14:48 »
Ich wollte den VM86 einbauen welcher ja  von einem Task (Prozess) mit der Privilegstufe 3 bewirkt werden muss, der dann VM86 startet (iret), denn der erste Versuch mit VM86 denn ich mittels Software Interrupt ausgelöst habe hat beim Befehl int 10h (im VM86) einen Absturz verursacht.  Meine Add Funktion für Tasks hab ich so abgeändert, dass nun auch die Privilegstufe mit einbezogen werden.  Doch jetzt wird ein Exceptions 13 ausgelöst.  Wenn ich jedoch Privilegstufe auf 0 setze geht alles
void f3(){while(1);}
Tasks.add(0x0 ,0xffffffff,(unsigned int) &t_f1,0,(unsigned int) f1,0, true);
Tasks.add(0x0 ,0xffffffff,(unsigned int) &t_f3,0,(unsigned int) f3,3, true);

unsigned short CTask::add(unsigned int base, unsigned int size, unsigned int tss_base ,                   unsigned int page_base, unsigned int start,unsigned char privileg , bool update)  //paging noch nicht enthalten
/// Code Segement
i = GDT->add(base,size,0x9A | ((privileg & 3) << 5),G); //G==3
p_tss->CS = (i << 3) | (privileg & 3);
/// Data Segement
i = GDT->add(base,size,0x92 | ((privileg & 3) << 5),G);
i = (i << 3) | (privileg & 3);
p_tss->DS = i;
p_tss->ES = i;
p_tss->FS = (privileg & 3);
p_tss->GS = (privileg & 3);
p_tss->EIP = start;
p_tss->EFLAGS = 0x90200;
p_tss->CR3 = page_base;
//noch schlecht
p_tss->ESP = 0x300000 + task_Eintraege * 0x10000;
p_tss->SS = i;//0x10;

Ist beim Rinwechsel noch etwas wichtiges zu beachten? :?

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #1 am: 17. March 2009, 19:23 »
Wie kriegst du eine Virtual-8086-Mode-Task mit Privilegstufe 0 hin bzw. was meinst du damit? Das geht nämlich nicht, da die Segmentregister keine Selektoren (und damit auch kein RPL bzw. in der Folge auch kein CPL) mehr enthalten sondern eine RealMode-Segmentadresse. Deshalb ist ein V86-Task nach Definition CPL3.
Das setzen der Segmentregister in deinem Code ist insofern kompletter Mist :wink:

Zitat
Doch jetzt wird ein Exceptions 13 ausgelöst.
Exakt das sollte auch passieren. Ein Virtual-8086-Task darf nicht einfach ein INT (und andere, siehe Tutorial unten) ausführen, deswegen wirft die CPU erstmal eine Exception und du musst diese Instruktion von Hand emulieren, dass nennt man dann einen Virtual-8086-Monitor (welchen du schreiben musst).

Ein gutes Tutorial gibts hier.

edit: Ich sollte/wollte noch hinzufügen, dass man das auch ohne Virtual-8086-Monitor machen kann, aber das geht dann nicht mehr ab dem 386, sondern erst mit den Virtual-8086-Mode-Extension (VME) des Pentiums (iirc). Das ist zum einen Mal noch ne Ecke anders, zum anderen solltest du vorher erstmal normalen Virtual-8086-Mode verstanden haben. :wink:
« Letzte Änderung: 17. March 2009, 19:25 von bluecode »
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

Hauke

  • Beiträge: 113
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 18. March 2009, 11:53 »
Ich hab mich wohl falsch ausgedrückt. Der C++ ausschnitt hat nichts direkt mit dem VM86 zu tun. Mein Hauptproblem ist nämlich erst einmal ein Task auszuführen, der im Ring 3 läuft, ich hab einfach die Segmente (GDT Einträge) mit einer niedrigeren Privilegstufe erstellt wie auch die Selektoren und dann diesen Task genauso wie die anderen behandelt (gewechselt) mit Softwaremultitasking. Und das verursacht den Exceptions 13 noch einmal die Frage:
Zitat
Ist beim Rinwechsel noch etwas wichtiges zu beachten?

Ich hab diesen Software Interrupt, in der Mainfunktion des Kernels,  aufgerufen aufgrund der Beschreibung hiervon http://lowlevel.brainsware.org/wiki/index.php/Virtual_8086_Mode
_int53:
pop eax  ;eip
pop eax  ;cs
pop ebx  ;eflags
or ebx, 0x20000

push 0
push 0
push 0
push 0
push 0x9000  ;ss
push 0
push ebx
push 0x8000  ;cs
push 0  ;ip
iret
Zitat
Das geht nämlich nicht
   Ich wollte das nur noch erwähnen wo das nicht geht. Xor ax,ax geht, aber int 10h halt nicht, was zum Absturz führt.
Gleich beim iret hätte ich vermutet.

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #3 am: 18. March 2009, 19:52 »
Der C++ ausschnitt hat nichts direkt mit dem VM86 zu tun.
Er soll nicht das erstellen was du für einen V86-Task hälst? Warum postest du den Code dann?

Zitat
Mein Hauptproblem ist nämlich erst einmal ein Task auszuführen, der im Ring 3 läuft, ich hab einfach die Segmente (GDT Einträge) mit einer niedrigeren Privilegstufe erstellt wie auch die Selektoren und dann diesen Task genauso wie die anderen behandelt (gewechselt) mit Softwaremultitasking.
Kapier ich nicht, du willst doch Virtual-8086-Mode Tasks und keine Protected-Mode Ring 3 Tasks, oder sollen wir dir erstmal bei letzterem helfen? Wie dir eventuell noch nicht aufgefallen ist, ist ein Virtual-8086-Tasks was fundamental anderes wie ein Protected-Mode Ring 3 Tasks. Wenn du letzteres noch nicht geschafft hast, dann mach das definitiv zuerst.
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

Hauke

  • Beiträge: 113
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 20. March 2009, 15:44 »
OK ich hab jetzt den Ringwechsel hinbekommen (in beide Richtungen).
Ich wusste nicht, dass beim Ringwechsel  ESP und SS auf den Stack müssen und dass in das TaskRegister ein 'gültiger' TSS Descriptor gehört der zum Rückwechsel (Ring 0) da ist. (SS und ESP)

Zum VM86 hab ich noch eine Frage genauer gesagt zum Tutorial  im Codeslisting #4
ctx->cs = ivt[ip[1] * 2 + 1];
ctx->eip = ivt[ip[1] * 2];
Auf was zeigt dieser Zeiger. Die Adresse aus der ivt muss doch auch auf den User-Stack, damit das ausgeführt werden kann.

Und mit dem Interrupt-Flag verstehe ich nicht richtig wozu wird das gebraucht?
   if (current->v86_if)
        stack[2] |= EFLAG_IF;
    else
        stack[2] &= ~EFLAG_IF;

Noch einmal um das zu Rekapitulieren. (ob ich das richtig verstanden habe) 
In einem Ring3 Task wird VM86 gestartet.
Dann entsteht wahrscheinlich  ein Execption 13, da bestimmte Befehle halt nicht erlaubt sind.
Jetzt ist zu Prüfen, ob das VM-Flag gesetzt ist. Wenn er gesetzt ist muss der gewollte Befehl ‚Simuliert‘ werden.
« Letzte Änderung: 20. March 2009, 16:56 von Hauke »

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #5 am: 20. March 2009, 21:20 »
Zum VM86 hab ich noch eine Frage genauer gesagt zum Tutorial  im Codeslisting #4
ctx->cs = ivt[ip[1] * 2 + 1];
ctx->eip = ivt[ip[1] * 2];
Auf was zeigt dieser Zeiger. Die Adresse aus der ivt muss doch auch auf den User-Stack, damit das ausgeführt werden kann.

was auch gemacht wird:
    stack[0] = (uint16_t) (ctx->eip + 2);
    stack[1] = ctx->cs;
    stack[2] = (uint16_t) ctx->eflags;
[quote][/quote]
Wobei nicht die Adresse aus der IVT, sondern die "alte" CS:IP Adresse auf den Stack muss, beim iret braucht man schließlich diese und nicht die "Neue".

[quote]Und mit dem Interrupt-Flag verstehe ich nicht richtig wozu wird das gebraucht?
   if (current->v86_if)
        stack[2] |= EFLAG_IF;
    else
        stack[2] &= ~EFLAG_IF;[/quote]
Es werden dort auf dem Stack die "richtigen" EFlags "simuliert". Das richtige IF im momentanen EFLAGS Register der CPU ist immer gesetzt, damit die Interrupts im PMode-Kernel ankommen. Aber da der V86-Task natürlich auch cli/sti ausführen könnte/möchte muss man zumindest bei den Operationen wo er explizit an die EFlags rankommt (zB auf dem Stack nach einem "INT") den vom V86-Task durch cli/sti induzierten IF Status (= current->v86_if) hernehmen. Sonst macht der V86-Task ein CLI, danach ein INT und es landet ein gesetztes IF auf dem Stack, was natürlich den Task "verwirren" könnte.

[quote]Noch einmal um das zu Rekapitulieren. (ob ich das richtig verstanden habe) 
In einem Ring3 Task wird VM86 gestartet.
Dann entsteht wahrscheinlich  ein Execption 13, da bestimmte Befehle halt nicht erlaubt sind.
Jetzt ist zu Prüfen, ob das VM-Flag gesetzt ist. Wenn er gesetzt ist muss der gewollte Befehl ‚Simuliert‘ werden.[/quote]
Jop, exakt.
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

Hauke

  • Beiträge: 113
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 27. March 2009, 13:53 »
OK ich hab jetzt die ersten Befehle simulieren können und das Gerüst dazu implementiert.
Jetzt ist Exeption 6 (ungültiger Befehl) aufgetreten mit dem Befehl mov cs, [ds + 0x1f14] diesen Befehl gibt es wohl nur im RealMode. (er wird disassembelt, deswegen gibt es ihn wohl doch irgendwie)
Jetzt such ich eine Tabelle, in der Befehle mit ihren Bytesignaturen aufgelistet sind, einziges was ich gefunden habe sind die einzelnen Befehltypen aber nicht die Bytesignaturen.
Ein direkter link währe sehr gut.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 27. March 2009, 14:10 »
Im Intel-Manual (oder natürlich auch AMD) sind die Opcodes aufgelistet und die Codierung der Operanden wird am Anfang desselben Buchs beschrieben.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #8 am: 27. March 2009, 17:24 »
Jetzt ist Exeption 6 (ungültiger Befehl) aufgetreten mit dem Befehl mov cs, [ds + 0x1f14] diesen Befehl gibt es wohl nur im RealMode. (er wird disassembelt, deswegen gibt es ihn wohl doch irgendwie)
Der ist aber sehr kaputt, du bist wahrscheinlich irgendwo gelandet, wo kein Code im eigentlichen Sinne steht, sondern halt was anderes. Der Befehl triggert mit recht eine Exception 6.
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

Hauke

  • Beiträge: 113
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 27. March 2009, 17:42 »
Nein halt ich hab mich geirrt der Befehl ist mov cs, wort ptr ds:[bx+0x1f14]BIOS Befehl c086:0005 müsste beim Starten überall gleich sein.
« Letzte Änderung: 27. March 2009, 17:44 von Hauke »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 27. March 2009, 17:53 »
Ein mov nach cs löst einen #UD aus, egal was da hinten dran noch kommt. ;)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Hauke

  • Beiträge: 113
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 01. April 2009, 14:33 »
So ich hab den Fehler gefunden ich hab die Adressen  immer umgebaut
wie z. B. 0xc000:0x012c  zu  0xc012:0x000c und bei einigen Befehlen spring er deswegen an einer falschen Stelle hin. Danke für die Hilfe. :-)

Hauke

  • Beiträge: 113
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 01. April 2009, 17:10 »
Ich hab doch noch ein Problem:
Ich wollte den Herunterfahren Schnipsel  ausprobieren, aber da Passiert nichts.
Das einzige, was mir als Fehler einfällt, sind meine out und in Funktionen, ob diese richtig funktionieren.  (ich weis nicht, wie out und in unter C offiziell heisst)void out(unsigned short _port, unsigned char _data)
{
__asm__ ("out %%al, %%dx" : : "a" (_data), "d" (_port));
}

unsigned char in(unsigned short _port)
{
unsigned char result;
__asm__ ("in %%dx, %%al" : "=a" (result) : "d" (_port));
return result;
}


void outw(unsigned short _port, unsigned short _data)
{
__asm__ ("out %%ax, %%dx" : : "a" (_data), "d" (_port));
}

unsigned short inw(unsigned short _port)
{
unsigned short result;
__asm__ ("in %%dx, %%ax" : "=a" (result) : "d" (_port));
return result;
}
Oder es liegt an etwas anderen.
« Letzte Änderung: 01. April 2009, 17:15 von Hauke »

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #13 am: 01. April 2009, 18:14 »
Ich wollte den Herunterfahren Schnipsel  ausprobieren, aber da Passiert nichts.
Welchen?

Zitat
ch weis nicht, wie out und in unter C offiziell heisst.
Die Funktionen gibt es offiziell nicht.

Zitat
Oder es liegt an etwas anderen.
Wahrscheinlich, die Funktionen sehen jedenfalls gut aus.
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

Hauke

  • Beiträge: 113
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 01. April 2009, 18:45 »
Das ist der Codeschnipsel aus Ausgabe 3 APM Powerdown.

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 01. April 2009, 23:18 »
Und wo für brauchst du da die in/out funktionen?

    ; SYSTEM POWERDOWN
    ; WARNING - DO NOT RUN UNDER WIN! (IT WORKS!)
    ; (C) 1999 BY VINNY 
 
    MOV AX,0x5300
    XOR BX,BX
    INT 0x15 ; APM install check
    MOV AX,0x5304
    XOR BX, BX
    INT 0x15 ; disconnect interface
    MOV AX,0x5301
    XOR BX, BX
    INT 0x15 ; connect real-mode interface
    MOV AX,0x5307
    MOV BX,1
    MOV CX,3
    INT 0x15 ; powerdown system
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 01. April 2009, 23:41 »
Vermutlich benutzt der int 15h die?
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Hauke

  • Beiträge: 113
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 07. April 2009, 12:37 »
Ja der Int15h benutzt out.
Ich musste mein Multitasking für Taktwechsel und VM wechsel richtig einrichten. (hat leider etwas zu lange gedauert), jedenfalls geht was Herunterfahren nicht es wird nur ein Software Reset gemacht.  (sagt mir Bochs), aber der Rest funktioniert.

Deshalb nochmals vielen Dank.
 :-)

 

Einloggen