Autor Thema: Probleme mit Interrupts/Exceptions  (Gelesen 6120 mal)

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« am: 03. November 2014, 20:07 »
´Hallo zusammen,

Ich habe ein Problem bezüglich Interrupts/Exceptions und bin leider trotz sorgfäliger Analyse noch nicht dahinter gekommen wo genau mein Fehler liegt.

Ich habe eine Datei "idt.c" (siehe Anhang) in der (vlt noch etwas unsauber) meine Funktionen zum Laden und zur Initialisierung der IDT und die Funktionen zum Interrupthandling liegen.

Außerdem habe ich eine Datei "isr.S" (ebenfalls im Anhang) in der in Assemblercode die ISR's liegen.

Mein Problem ist jetzt dass ich nachdem ich in der "init.c" die GDT und die IDT initialisiert, sowie den PIC konfiguriert habe versuche testweise mit asm volatile("int $0x01"); die Exception Nr. 1 herbeizuführen, jedoch wird meine isr zur behandlung dabei nicht aufgerufen, die Exception also nicht behandelt -> Triple Fault -> Neustart des Rechners..

Die einzige Exception die ich fehlerfrei herbeiführen kann ist Nr. 0, dabei wird dann mein Handler aufgerufen und die Exception bearbeitet.

Schon mal Vielen Dank im Vorraus
s137

P.S. Einen Fehler der GDT kann ich ausschließen, diese habe ich schon seperat getetet.
« Letzte Änderung: 03. November 2014, 20:29 von s137 »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 03. November 2014, 20:21 »
Hi und willkommen an Board!

Zitat
#define IDT_ENTRIES 1
Das sollte wohl mindestens 49 sein.
Dieser Text wird unter jedem Beitrag angezeigt.

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 03. November 2014, 20:25 »
ach mist.. ich wusste doch ich hab was übersehen... imme diese leichsinnsfehler^^ hatte anfangs eben nur einen eintrag...

Vielen Dank für die Hilfe :) Es funktioniert jetzt einwandfrei^^
s137
« Letzte Änderung: 03. November 2014, 20:29 von s137 »

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 03. November 2014, 20:36 »
Eine Frage noch, wieso passiert nichts, wenn ich Hardwareinterrupts aktiviere und Tasten auf der Tastatur drücke, das müsste doch eigtl IRQ's auslösen, die wiederrum behandelt werden?

Kann das daran liegen dass ich noch keinen Keyboardtreiber habe? Aber dan müsste ich doch immerhin den IRQ 0 vom Timer bekommen oder?
« Letzte Änderung: 03. November 2014, 20:41 von s137 »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 03. November 2014, 22:01 »
Ja, wenn du IRQs am PIC und in der CPU (mit STI) aktiviert hast, solltest du zumindest Timer Interrupts bekommen. Für Keyboardinterrupts musst du eventuell den Puffer vorher leeren, und bei jedem Keyboard-Interrupt ebenfalls aus dem Puffer lesen.
Dieser Text wird unter jedem Beitrag angezeigt.

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 04. November 2014, 18:32 »
Also ich habe die IRQs in meiner init.c folgendermaßen (siehe unten) am PIC initialisiert und demaskiert und außerdem auch die Hardwareinterrupts (sti) eingeschaltet. Aber ich bekomme trotz Handling in meinem common InterruptHandler mit:

 
        if (cpu->intr <= 0x1f) {
        // kprintf("Exception %d, Kernel angehalten!\n", cpu->intr);
           kputs("Exception: n/a, Kernel angehalten!\n");
        // Hier den CPU-Zustand ausgeben

        while(1) {
            // Prozessor anhalten
            asm volatile("cli; hlt");
        }
    } else {
        // Hier den Hardwareinterrupt behandeln
        kputs("Hardwareinterrupt");

        if (cpu->intr >= 0x20 && cpu->intr <= 0x2f) {

           if (cpu->intr == 0x20) {
            kputs("Timerinterrupt");
           }
           if (cpu->intr == 0x21) {
            kputs("Tastaturinterrupt");
           }

         if (cpu->intr >= 0x28) {
               outb(0xa0, 0x20); // End of Interrupt: Slave PIC
            }

            outb(0x20, 0x20); // End of Interrupt: Master PIC
        }
    }


irgendwie keine Ausgabe...

Hier mal meine init.c:

#include "console.h"
#include "gdt.h"
#include "idt.h"
#include "keyboard.h"

static inline void outb(unsigned short port, unsigned char data)
{
    asm volatile ("outb %0, %1" : : "a" (data), "Nd" (port));
}

void init(void)
{

    // Global Descriptor Table initialisieren
    init_gdt();

    // Master-PIC initialisieren ( nur 7 IRQs )
    outb(0x20, 0x11); // Initialisierungsbefehl fuer den PIC | CmdPort: 0x20
    outb(0x21, 0x20); // Interruptnummer fuer IRQ 0 | DataPort: 0x21
    outb(0x21, 0x04); // An IRQ 4 haengt der Master ?!
    outb(0x21, 0x01); // ICW 4

    // Slave-PIC initialisieren ( restliche IRQs )
    outb(0xa0, 0x11); // Initialisierungsbefehl fuer den PIC | CmdPort: 0xA0
    outb(0xa1, 0x28); // Interruptnummer fuer IRQ 8 | DataPort: 0xA1
    outb(0xa1, 0x02); // An IRQ 2 haengt der Slave
    outb(0xa1, 0x01); // ICW 4

    // Alle IRQs aktivieren (demaskieren)
    outb(0x20, 0x0);
    outb(0xa0, 0x0);

     // Interrupt Descriptor Table initialisieren
    init_idt();

    init_keyboard();

    // Test Things
    clrscr();
    kputc('A', 0x01, 0, 0);
    kputs("Hello World");
    kputc('B', 0x04, 4, 5);
    kputs("Test\n");
    kputs("New Line?");
    int a = kprintf("test\n");
    kputn(a, 10);

    // Aktivieren von Hardware Interrupts
     asm volatile("sti");

}

Vielen Dank schonmal im Vorraus
s137

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 04. November 2014, 22:29 »
An dem Code, den du gepostet hast, liegts vermutlich nicht direkt. Zumindest kann ich da nichts entdecken. Ich halte es für am wahrscheinlichsten, dass anderer Code dazwischen funkt und die Interrupts sabotiert.

Hast du zum Beispiel diese Zeilen in entry.S aus dem Tutorial (ich nehme mal an dem folgst du) beachtet?
    // Falls wir jemals aus init zurueckkommen sollten, sperren wir die Interrupts und
    // halten einfach den Prozessor an. (man braucht ihn ja nicht unnötig heißlaufen lassen.)
_stop:
    cli
    hlt
« Letzte Änderung: 04. November 2014, 22:32 von Jidder »
Dieser Text wird unter jedem Beitrag angezeigt.

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 04. November 2014, 22:41 »
und schon hab ich meinen Fehler gefunden.. vielen Dank nochmals ^^ die 2 zeilen sperren mir natürlich dank "cli" meine interrupts und halten dann den Prozessor an.. daran hab ich irgendwie gar nicht mehr gedacht...

doch wenn ich diese 2 zeilen entferne läuft der kernel ja iwie nicht weiter... also zumindest bekomme ich immernoch keine IRQ's... was kann ich machen um den Kernel am laufen zu halten?
« Letzte Änderung: 04. November 2014, 22:47 von s137 »

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 04. November 2014, 22:58 »
ok frage hat sich erledigt.. eine einfach endlosschleife:

_furhter:

jmp _further

reicht aus ^^

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« Antwort #9 am: 05. November 2014, 15:50 »
Hallo,
du kannst in deine Endlosschlaufe noch ein "hlt" einbauen, dann läuft die CPU nicht "heiss". Sie hält eigentlich dann dort an mit arbeiten und nach einem Interrupt geht es hintendran weiter => Sprung zurück auf hlt.
Das hört man übrigens auch am Lüfter, wenn man sein OS auf echter Hardware testet. Wenn das "hlt" nicht steht, dann dreht der Lüfter "durch" :lol:
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 05. November 2014, 16:26 »
Dazu braucht man keine echte Hardware. qemu nimmt sich in dem Fall auch 100% CPU.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 05. November 2014, 17:12 »
oh ok danke, werds so machen.

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 05. November 2014, 17:33 »
Ich habe gerade nochmal ein Problem das TSS betreffend. Ich gehe ja nach dem Tutorial vor und habe gerade den Userspace für das Multitasking implementiert in Form eines TSS. Allerdingt startet sich der Rechner nach der Initialisierung der GDT jedesmal neu.

Definiert ist mein TSS so:

static unsigned long tss[32] = { 0, 0, 0x10 };
und hier (innerhalb der init_gdt Funktion) wird das TSS in die GDT eingetragen und das Taskregister neu geladen:


    set_entry(5, (unsigned long) tss, sizeof(tss), GDT_FLAG_TSS | GDT_FLAG_PRESENT | GDT_FLAG_RING3);

    // Taskregister neu laden
    asm volatile("ltr %%ax" : : "a" (5 << 3));

Wieso lädt der Rechner die GDT nicht ordnungsgemäß? Habe ich hier irgendwo einen Syntaxfehler gemacht?

Viele Grüße
s137
« Letzte Änderung: 05. November 2014, 17:35 von s137 »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 05. November 2014, 17:37 »
Was heißt "nach der Initialisierung der GDT" genau? Also bei welcher Codezeile kriegst du den Triple Fault?

Wo steht dein lgdt? Also hast du die GDT vor dem ltr überhaupt schon geladen?
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 05. November 2014, 17:45 »
Hier in der init.c habe ich mal provisorisch nach der Initialisierung der GDT, des PIC und der IDT:

// Global Descriptor Table initialisieren
    init_gdt();

    // Master-PIC initialisieren ( nur 7 IRQs )
    outb(0x20, 0x11); // Initialisierungsbefehl fuer den PIC | CmdPort: 0x20
    outb(0x21, 0x20); // Interruptnummer fuer IRQ 0 | DataPort: 0x21
    outb(0x21, 0x04); // An IRQ 4 haengt der Master ?!
    outb(0x21, 0x01); // ICW 4

    // Slave-PIC initialisieren ( restliche IRQs )
    outb(0xa0, 0x11); // Initialisierungsbefehl fuer den PIC | CmdPort: 0xA0
    outb(0xa1, 0x28); // Interruptnummer fuer IRQ 8 | DataPort: 0xA1
    outb(0xa1, 0x02); // An IRQ 2 haengt der Slave
    outb(0xa1, 0x01); // ICW 4

    // Alle IRQs aktivieren (demaskieren)
    outb(0x20, 0x0);
    outb(0xa0, 0x0);

     // Interrupt Descriptor Table initialisieren
    init_idt();

noch eine Endlosschleife mit asm volatile("cli; hlt;"); eingebaut um den Kernel mal dort anzuhalten und zu schauen ob er überhaupt soweit kommt. Ich weißt dass es nicht am PIC oder de IDT liegt, weil die GDT das einzige ist was ich verändert habe.

meine GDT wird nach dem ltr geladen.. ist das ein problem sollte das neuladen des TR's erst nach dem Laden der GDT erfolgen?

Edit: habs getestet, auch wenn das neuladen des TR's erst nach dem Laden der GDT erfolgt gibts nen Triple Fault..
« Letzte Änderung: 05. November 2014, 18:02 von s137 »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 05. November 2014, 19:21 »
Wie viele Einträge hat deine GDT und hat sie wirklich so viele Einträge?
Dieser Text wird unter jedem Beitrag angezeigt.

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 05. November 2014, 19:29 »
ach man... ich hab schon wieder vegessen die Konstante anzupassen.. ich schäme mich grad wirklich dass ich den selben Fehler 2x gemacht habe...

Nochmals vielen Dank für deine Hilfe..

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 05. November 2014, 19:34 »
Bist nicht der erste, dem das passiert. Das ist zwar im Artikel erwähnt, aber sowas überliest man ja schnell.
Dieser Text wird unter jedem Beitrag angezeigt.

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 05. November 2014, 19:49 »
Jaah stimmt auch wieder^^

Ja beim 2.Mal lesen merkt mans dann^^

Muss ich wohl irgendwie überlesen haben. Also tdem danke nochmal^^

 

Einloggen