Lowlevel

Lowlevel => Lowlevel-Coding => Thema gestartet von: Roadrunner am 14. September 2012, 16:58

Titel: General Protection Fault
Beitrag von: Roadrunner am 14. September 2012, 16:58
Ich habe vor kurzem ein neues OS begonnen, bei dem ich die ISRs in Assembler implementieren wollte. Das hat auch soweit gut funktioniert, allerdings kehrt der Handler nie zurück, wenn ich zum Testen der IDT im Kernel z. B. den Interrupt 55 auslöse, der noch nicht eingetragen ist. Der Handler wird auch tatsächlich aufgerufen, allerdings funktioniert der Befehl "iret" nicht. Hier der Code:

isr_0D:
    pop dword [int_ec] ;Den Error-Code vom Stack nehmen
    iret

Habe ich hier irgend was übersehen? Ich weiß echt nicht mehr weiter...
Titel: Re: General Protection Fault
Beitrag von: micha am 14. September 2012, 17:11
bevor du mit iret aus deinen interrupthandler springst, musst du ein EOI (end of interrupt) an den PIC senden.
Titel: Re: General Protection Fault
Beitrag von: Jidder am 14. September 2012, 17:37
bevor du mit iret aus deinen interrupthandler springst, musst du ein EOI (end of interrupt) an den PIC senden.
Nur bei IRQs, nicht bei Softwareinterrupts.

Meine Vermutung ist, dass der Stack nicht richtig eingerichtet ist. Kannst du prüfen, ob der Stackpointer einen sinnvollen Wert hat?
Titel: Re: General Protection Fault
Beitrag von: Roadrunner am 15. September 2012, 13:28
Ja. Hier die ersten Einträge des Stacks (esp hat den Wert 0xFFFFD0; das kommt hin, da esp am Anfang auf 1 MiB gesetzt wurde):

0xAAA ;Letzter Wert (oben)
0x007
0x246
0x008
0x0BE
0x1BA ;Erster Wert (unten)
Titel: Re: General Protection Fault
Beitrag von: Jidder am 15. September 2012, 13:36
Ja. Hier die ersten Einträge des Stacks (esp hat den Wert 0xFFFFD0; das kommt hin, da esp am Anfang auf 1 MiB gesetzt wurde):
0xffffd0 ist nicht in der Nähe von 1MB, sondern 16MB. Den Stack auf 1 MB (0x100000) zu setzen ist außerdem nicht korrekt, weil das im BIOS liegt. Das ist ein ROM, das in den physischen Adressraum gemappt wurde, und ist nicht beschreibbar. Das heißt wenn ein Interrupt auftritt, werden keine Werte auf den Stack geschrieben, und das IRET liest ungültige Werte vom Stack. Das würde den GPF erklären, wenn du den Stack tatsächlich an der Adresse 1 MB hast. Es gibt zwar die Möglichkeit, dass es auch unbeschreibbaren Speicher in der Nähe von 16 MB gibt, aber das sollte nicht der Fall sein. Du kannst trotzdem mal versuchen den Stack woanders hinzulegen, z.B. so wie in diesem Tutorial (http://www.lowlevel.eu/wiki/Teil_4_-_Hello_World) in einem eigens dafür reservierten Bereich im Kernel.

Zitat
0xAAA ;Letzter Wert (oben)
0x007
0x246
0x008
0x0BE
0x1BA ;Erster Wert (unten)
Das sind 12-Bit Werte. Du solltest 32-Bit Werte ausgeben lassen. (Oder Bytes)
Titel: Re: General Protection Fault
Beitrag von: Roadrunner am 15. September 2012, 13:42
Ich probier gleich mal, den Stack woanders hin zu legen. Was die Ausgabewerte betrifft: Meine Funktion zur Ausgabe von Zahlen gibt keine führenden Nullen aus. Die Werte hier waren alle nicht länger als 3 Stellen, also hab ich sie schnell mal ergänzt, damit es auch ordentlich aussieht. Die Funktion könnte aber auch Werte wie 0x78787878 ausgeben - sie benutzt als Parameter einen 32-Bit-Wert.