Autor Thema: Interrupts - PageFault  (Gelesen 22875 mal)

Adi

  • Beiträge: 20
    • Profil anzeigen
Gespeichert
« am: 26. March 2007, 13:47 »
Hallo,

das ist mein erster Beitrag und muss sagen ich bin echt begeistert ein so tolles  deutschsprachiges Forum bezüglich OS-Entwicklung gefunden zu haben! ;-)

Schreibe gerade selbst ein kleines Betriebssystem in c++... allerdings habe ich ein Problem welches ich bisher nicht lösen konnte! wäre froh wenn von euch jemand eine Lösung hat :-)

Also es geht um folgenden Beispiel-Kernel:
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=6718&lngWId=3

dessen Code teilweise auch bei mir Verwendung findet...

Nun nach genauerem betrachten wird klar dass man eine neue ISR mit folgendem Code aktiviert:
(keyboard.cpp)
enable_irq(1, keyboard_int, INT_GATE|BITS_32|PRESENT|RING_2);

Dies funktioniert auch alles soweit! Wenn ich allerdings Interrupt0 nutzen möchte (z.b. für Taskswitching) bekomme ich merkwürdige Bildschirmausgaben oder auch gleich einen Page-Fault!

Hier meine Ergänzungen:
enable_irq(0, int_test, INT_GATE|BITS_32|PRESENT|RING_2);

void int_test(){

//Don't let interrupts bother us while handling one.
        interrupt_disable();

kernel->video->put('x');
 kernel->video->refresh();

//tell pic we have acknowledged the interrupt
        outportb(0x20, 0x20);

interrupt_enable();

asm("mov %ebp,%esp");
asm("pop %ebp");
asm("iret"); //return to executing code
}


Wie im obigen Code gewünscht werden die X'e ausgegeben un erst nach ein paar Zeilen tritt ein Page-fault auf!
« Letzte Änderung: 27. March 2007, 00:01 von Adi »

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #1 am: 26. March 2007, 18:15 »
Du solltest evtl. die Register im Interrupthandler sichern... dazu ist halt ne C/C++ Funktion nicht so geeignet, deshalb empfehle ich da dann doch den C/C++ Interruptbehandlungsroutinen einen assemblerstub vorneanzustellen, welcher die Register speichert und danach auch wiederherstellt.

Sicher bin ich mir natürlich nicht, da du ein bisschen wenig informationen über den pagefault herausrückst :wink: Am besten wäre es natürlich wenn du bochs anwerfen würdest, beim logging für das cpu device alles auf "report" und dann sagen würdest, wo eip gerade ist beim pagefault ist (am besten dir vom compiler/linker ne datei mit den adressen aller symbole ausgeben lassen, dann weißt du auch gleich welche funktion da pagefaultet) und an welcher adresse der Pagefault auftritt.
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

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 26. March 2007, 19:32 »
Eine OffTopic-Anmerkung: Du kannst deine Beiträge auch editieren, dann steht unten zwar, dass es editiert wurde, aber das macht ja auch nichts.

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #3 am: 26. March 2007, 20:34 »
Zitat
dazu ist halt ne C/C++ Funktion nicht so geeignet
*duck und weg* :-P


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

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #4 am: 26. March 2007, 20:58 »
Zitat
dazu ist halt ne C/C++ Funktion nicht so geeignet
*duck und weg* :-P


bitmaster

Damit hast du deinem Titel mal wieder alle Ehre gemacht. Dieser Post bringt genau _nichts_

@Topic:
Mit irgendwelchen Compiler-Hacks wärs warscheinlich möglich, das auch in C(++) zu erledigen. Das führt aber dazu, dass der Code compilerabhängig wird, und als sonderlich elegant würde ich diese Lösung auch nicht bezeichnen. Daher würde ich dir auch raten, das mit ASM-Stubs zu machen, die eigentlich nichts anderes machen als die Register zu sichern.
Hier kannst du dir anschauen, wie wir das in LOST gelöst haben:
http://lost.famkaufmann.info/websvn/filedetails.php?repname=Lost&path=%2Ftrunk%2Fsrc%2Fkernel%2Fsrc%2Fstubs.asm

Adi

  • Beiträge: 20
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 27. March 2007, 00:56 »
Text editiert ;-)

Hey, also danke für die Antworten!

Also zu Bochs... bisher nutzte ich VMware! werde aber umsteigen!
Dann kann ich euch sicher auch mehr Details zum Fehler liefern!

Zu den Register... dachte dass die CPU diese automatisch sichert und nach einem "iret" wiederherstellt! oder liege ich da falsch?
Schließlich funktioniert die ISR des Keyboard-Treiber doch auch einwandfrei?!

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #6 am: 27. March 2007, 07:08 »
Nein, iret sichert nur das eflags Register und cs:eip. Alle anderen Register wie eax-edx,esi,edi,ebp etc. musst du mittels push/pop selber sichern und wieder vom stack holen. Warum der keyboard irq funktioniert kann ich jetzt nicht sagen, aber sobald er aufgerufen wird und Register verändert werden, stimmen nach der rückkehr die Werte nicht mehr. Also als Beispiel:

irq1:
push eax
push ebx
push ecx ;Werte speichern

... ;Code der die Register eax, ebx und ecx verändert

mov al,20h
out 20h,al ;EOI

pop ecx ;Werte zurück holen
pop ebx
pop eax
iret


Multitasking hast du noch nicht, oder? Weil der irq0 da sonst ohne Sichern der Register alles kaput machen würde.


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

Adi

  • Beiträge: 20
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 27. March 2007, 10:51 »
@bitmaster
Danke für das Beispiel! Die X'e wurden ohne Page-Fault ausgegeben ;-)
Jedoch traten noch einige Grafikfehler auf... die hatten sich allerdings auch erledigt nach dem ich noch ein paar Register mehr gesichert hab!

Wie ich inzwischen glaube, sind wohl auch in der Keyboard-ISR Fehler aufgetreten wenn man die Register nicht sichert! Allerdings die Auswirkungen zeigten sich sehr selten!

Jetzt scheint alles zu funktionieren :-)
Gibt es eigentlich noch mehr Register die gesichert werden sollten? (siehe Code unten)

Und was genau bewirken die vorletzten 2 Zeilen? (hat wohl was mit dem Stack zu tun)

Wäre es nicht sinnvoller interrupt_enable() direkt vor "iret" zu schreiben?

void int_test(){
interrupt_disable();

asm("push %eax");
asm("push %ebx");
asm("push %ecx");
asm("push %edx");
asm("push %esi");
asm("push %edi");
asm("push %ebp");

std::cout << 'x';

outportb(0x20, 0x20);

asm("pop %ebp");
asm("pop %edi");
asm("pop %esi");
asm("pop %edx");
asm("pop %ecx");
asm("pop %ebx");
asm("pop %eax");

interrupt_enable();

asm("mov %ebp,%esp");
asm("pop %ebp");
asm("iret"); //return to executing code
}

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 27. March 2007, 12:31 »
Wäre es nicht sinnvoller interrupt_enable() direkt vor "iret" zu schreiben?
Am sinnvollsten wäre es, dieses disable() und enable() ganz wegzulassen. Ersteres ist impliziert, weil es ein Interrupt Gate ist, letzteres wird dann mit dem iret erledigt.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #9 am: 27. March 2007, 19:00 »
Ich habe nirgendwo enable und disable erwähnt. Meint ihr damit "cli" und "sti“ ? Und welche Register der C/C++ Code jetzt verändert, damit dürft ihr euch dann rumschlagen. In ASM weis ich genau welche Register verändert werden. Aber zu not kannst du einfach alle Register sichern und wiederherstellen. Im Protected Mode gibt es ja noch das Befehlspaar pusha und popa. Falls du die Segmentregister noch veränderst, vergesse nicht diese zwischenzuspeichern.

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

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #10 am: 27. March 2007, 19:28 »
Also ich muss nochmals sagen, dass es nicht sinnvoll ist eine C/C++ Funktion direkt als interrupthandler zu missbrauchen, da die zB das Register ebp bereits beim eintritt in die Funktion verändert wird und auch da eine C/C++ Funktion einfach ein bestimmtes Stacklayout vorsieht. Da kann man nicht einfach irgendwas auf den Stack pushen, da da C/C++ zB lokale Variablen anlegt.
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

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 27. March 2007, 19:46 »
Und welche Register der C/C++ Code jetzt verändert, damit dürft ihr euch dann rumschlagen. In ASM weis ich genau welche Register verändert werden.
Dann bewegt sich der Umfang deines Codes in Bereichen, die man allgemein als Mickey-Maus-Projekt bezeichnet.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #12 am: 27. March 2007, 20:00 »
@taljeth: Ach taljeth! Ich respektiere es das du in C/C++ codest. Ich glaube auch dass du Ahnung von OSDeveloping hast. Aber was ich bezweifle ist, dass du viel Ahnung von ASM hast. Ein guter ASM progger weis welche Register verändert werden, egal wie groß der Code ist bzw. wie viele Zeilen Code. Und lass es doch endlich. Ich weis das du meinst du seist der einzig Gute OSDever. Aber die Zeit wird kommen, in der du nicht mehr so denkst. In ASM weis man immer welche Register verändert werden (es sei denn man hat kA von den Befehlen). Und spar dir bitte einen weiteren Kommentar der Anzweifel zum Ausdruck bringt.

Ein guter ASM progger macht weniger Fehler als ein Hochsprachen progger.

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

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 27. March 2007, 20:06 »
Ein guter ASM progger weis welche Register verändert werden, egal wie groß der Code ist bzw. wie viele Zeilen Code.
Wenn der Umfang größer ist - so ziemlich alle? ;) So viel weiß ich dann auch noch über meinen C-Code. Ist ja nicht so, daß der Compiler schwarze Magie wäre.

Zitat
Ich weis das du meinst du seist der einzig Gute OSDever. Aber die Zeit wird kommen, in der du nicht mehr so denkst.
Prophetische Worte. ;) Aber offensichtlich hast du mir nie recht zugehört. Ich halte mich unter anderem deswegen immer wieder zurück, weil ich einfach nicht genug Ahnung vom Thema habe. Und das gebe ich auch ganz offen zu.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Adi

  • Beiträge: 20
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 28. March 2007, 09:13 »
Hi,

also interrupt_disable(); und interrupt_enable();
entsprechen "cli" und "sti"...
Hab sie nun aber wie empfohlen rausgenommen  :wink:

Kann mir noch jemand die Frage zu den vorletzten 2 Zeilen beantworten? :-)

Hier mal ein link zum aktuellen IMG:
http://www.hib-elemente.de/OS.img
Das ding hat bisher keinen Namen und ich beginne ja auch erst mich mit OS development zu beschäftigen... aber was haltet ihr bis jetzt davon?

Also als nächstes werde ich nun versuchen Multitasking zu implementieren, und der Keyboard-Treiber sollte auch neu geschrieben werden damit zusätzlich das deutsche Tastatur-layout unterstützt wird ;-)
« Letzte Änderung: 28. March 2007, 09:36 von Adi »

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #15 am: 28. March 2007, 10:10 »
Kann mir noch jemand die Frage zu den vorletzten 2 Zeilen beantworten? :-)
Beim Einstieg in die Funktion erstellt der C/C++ Compiler einen neuen Stackframe, d.h. er pusht ebp und setzt ebp = esp. Dadurch kann der Compiler weiterhin auf den Stackpushen und gleichzeitig die Parameter über ebp+X adressieren, ohne das man X ständig anpassen müsste. Außerdem dient dieser Stackframe dem Debuggen, da dadurch stack backtraces erst möglich werden. Man kann das aber auch bei gcc über --fomit-frame-pointer abstellen. Dieser Stackframe muss natürlich danach wieder rückgangig gemacht werden.
Problem dabei ist nur, dass du keine Möglichkeit hast das register ebp zu sichern, aber ich red scheinbar eh momentan gegen ne Mauer :-P
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

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 28. March 2007, 13:31 »
Beim Einstieg in die Funktion erstellt der C/C++ Compiler einen neuen Stackframe, d.h. er pusht ebp und setzt ebp = esp.
Zitat
Problem dabei ist nur, dass du keine Möglichkeit hast das register ebp zu sichern, aber ich red scheinbar eh momentan gegen ne Mauer :-P
Man möge mir verzeihen, wenn ich Unsinn rede, dann bin ich wohl nur noch nicht richtig wach... ;) Aber das push ebp, das der Compiler macht, ist doch ein Sichern? Nur darf man halt nicht auf die Idee kommen, -fomit-frame-pointer zu benutzen, wenn man sich darauf verlassen will.
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 #17 am: 28. March 2007, 14:13 »
Aber das push ebp, das der Compiler macht, ist doch ein Sichern?
Irgendwas sagt mir, dass du Recht hast und ich nicht :-D
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

Adi

  • Beiträge: 20
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 29. March 2007, 10:59 »
Danke für die Erklärung! Habs jetzt so einigermaßen verstanden ;-)

Wie schon erwähnt versuche ich gerade "Software"-Multitasking zu implementieren... nur klappt das nicht so wirklich... kennt ihr ein gutes Tutorial das sich damit beschäftigt :?
Am besten wärs wenn es anhand eines "C" Kernels erklärt wird! :-P

Die Lowlevel-Magazin Ausgabe 7 beschäftigt sich ja lediglich mit Hardware-Multitasking!

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #19 am: 29. March 2007, 13:52 »
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