Lowlevel

Lowlevel => Lowlevel-Coding => Thema gestartet von: Hauke am 17. March 2009, 14:48

Titel: Ringwechsel und VM86
Beitrag von: Hauke 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? :?
Titel: Re: Ringwechsel und VM86
Beitrag von: bluecode 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 (http://osdev.berlios.de/v86.html).

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:
Titel: Re: Ringwechsel und VM86
Beitrag von: Hauke 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.
Titel: Re: Ringwechsel und VM86
Beitrag von: bluecode 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.
Titel: Re: Ringwechsel und VM86
Beitrag von: Hauke 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.
Titel: Re: Ringwechsel und VM86
Beitrag von: bluecode 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.
Titel: Re: Ringwechsel und VM86
Beitrag von: Hauke 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.
Titel: Re: Ringwechsel und VM86
Beitrag von: kevin 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.
Titel: Re: Ringwechsel und VM86
Beitrag von: bluecode 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.
Titel: Re: Ringwechsel und VM86
Beitrag von: Hauke 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.
Titel: Re: Ringwechsel und VM86
Beitrag von: kevin am 27. March 2009, 17:53
Ein mov nach cs löst einen #UD aus, egal was da hinten dran noch kommt. ;)
Titel: Re: Ringwechsel und VM86
Beitrag von: Hauke 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. :-)
Titel: Re: Ringwechsel und VM86
Beitrag von: Hauke 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.
Titel: Re: Ringwechsel und VM86
Beitrag von: bluecode 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.
Titel: Re: Ringwechsel und VM86
Beitrag von: Hauke am 01. April 2009, 18:45
Das ist der Codeschnipsel aus Ausgabe 3 APM Powerdown.
Titel: Re: Ringwechsel und VM86
Beitrag von: MNemo 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
Titel: Re: Ringwechsel und VM86
Beitrag von: kevin am 01. April 2009, 23:41
Vermutlich benutzt der int 15h die?
Titel: Re: Ringwechsel und VM86
Beitrag von: Hauke 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.
 :-)