Autor Thema: IRQ 11 auf Hardware  (Gelesen 6352 mal)

timon

  • Beiträge: 13
    • Profil anzeigen
Gespeichert
« am: 23. July 2013, 12:14 »
Hallo Zusammen

Neulich hat mir ein altes Problem von mir wieder einmal viel Ärger und Kopfschmerzen bereitet.
Mein Betriebssystem, das fehlerfrei unter Qemu läuft, funktioniert auf meinem Laptop nicht richtig.

Der Laptop wirft andauernd den IRQ 11. Mit andauernd meine ich, dass sobald ich die Interrupts aktiviere(sti), ich keinen weitern Code ausser Interrupthandler ausführen kann. Dazu foldender Ausschnitt:

    init_idt();
    while(1)
    {
        debug_kprintf( (str)"Hallo");
    }
Direkt am Ende von init_idt setze ich das Interruptflag.
Ab dort wird auf meinem Laptop kein Code aus meiner Main funktion mehr ausgeführt. Der Keyboardhandler(und alle meine anderen Handler) funktionieren jedoch einwandfrei.
Unter Qemu werde ich mit Hallos zugespamt was eigentlich auch zu erwarten war.

Nun probierte ich einen dummen Workaround (nämlich den IRQ11 zu maskieren). Nur kommt der IRQ trozdem weiterhin.

Ich bin mir ziemlich sicher, dass mein Code stimmt, ich habe ihn mehrere Male mit dem Wiki überprüft und auch gegoogelt wegen dem IRQ 11.

Auf einem anderen Computer habe ich mein OS noch nicht getestet(aus Faulheit) und momentan kann ich ihn nicht auf einem anderen Computer testen, weil ich in den Ferien bin und nur meinen Laptop dabei habe.

Ich hoffe ihr könnt mir mit diesem Problem helfen

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 23. July 2013, 13:16 »
Ich bin mir ziemlich sicher, dass mein Code stimmt, ich habe ihn mehrere Male mit dem Wiki überprüft und auch gegoogelt wegen dem IRQ 11.
Ich bin mir ziemlich sicher, dass dein Code in irgendeiner Hinsicht nicht stimmt, sonst würdest du hier nicht fragen. ;)

Wie maskierst du denn den IRQ? Zumindest der Teil muss auf jeden Fall funktionieren, wenn es wirklich ein IRQ ist (und die Tatsache, dass es nach dem sti anfängt, spricht stark dafür).

Wenn du die wirkliche Ursache wissen willst, musst du natürlich rausfinden, welches Stück Hardware dir diesen IRQ schickt und wieso es das tut.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

timon

  • Beiträge: 13
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 23. July 2013, 13:45 »
Ich maskiere den Interrupt so:
    init_pic();
    irq_mask((u16)0b1111111011111000);
Ich maskiere gleich alles was ich nicht brauche. Später wenn ich mich mit PCI beschäftige, werde ich das ändern.
irq_mask sieht so aus:
void irq_mask(u16 mask)
{
   outb(0x21, (u8)mask);
   outb(0xA1, (u8)mask>>8);
}
Dieser Code wird garantiert korrekt und vor dem sti ausgeführt.
Ich habe noch keine Hardare initialisiert, die diesen IRQ wirft. Vielleicht ist es Grub2, der unsauber arbeitet aber ich denke eher nicht.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 23. July 2013, 17:16 »
Wie initialisierst du den PIC?

Vielleicht würde es auch weiteren Aufschluss geben, wenn du versuchst rauszukriegen welches Gerät an IRQ 11 hängt. Ich hab mir sagen lassen, dass es unter Linux mit cat /proc/interrupts geht und unter Windows kannst du dir das im Gerätemanager anzeigen lassen, wenn du Ansicht -> Resourcen nach Typ wählst. (Das ist natürlich keine Garantie, weil die anderen Betriebssysteme die IRQs vielleicht anders als das BIOS belegen.)

Ansonsten habe ich wie immer die üblichen Zweifel an der Ermittlung der IRQ-Nummer und der Funktionsfähigkeit der Ausgabefunktion. Es ist schon mehrfach vorgekommen, dass die nicht richtig waren.
« Letzte Änderung: 23. July 2013, 17:18 von Jidder »
Dieser Text wird unter jedem Beitrag angezeigt.

streetrunner

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 23. July 2013, 17:19 »
Ich würde eher sagen sein Code ist falsch. In der zweiten Zeile in irq_mask() castet er erst seinen u16-Wert in ein u8, um ihn dann um 8 Stellen nach rechts zu verschieben. Wenn mich nicht alles täuscht dann sollte sein Wert dadurch mit Nullen aufgefüllt werden, wodurch alle Interrupts Demaskiert werden.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 23. July 2013, 17:24 »
Jo, das klingt logisch. Ich vermute das wird's sein.
Dieser Text wird unter jedem Beitrag angezeigt.

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 23. July 2013, 18:19 »
Ich war mir sicher das GCC in so einem Fall warnt. Aber das tut er scheinbar nur wenn die shift-Weite >= 32 ist, egal ob u8 oder char.
Darunter wird das tatsächlich still und heimlich zu einer 0 optimiert.  :?
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #7 am: 23. July 2013, 19:11 »
Ich war mir sicher das GCC in so einem Fall warnt. Aber das tut er scheinbar nur wenn die shift-Weite >= 32 ist, egal ob u8 oder char.
Darunter wird das tatsächlich still und heimlich zu einer 0 optimiert.  :?
Das kommt übrigens, weil der zu shiftende Operand erstmal implizit zu int konvertiert wird (wenn er reinpasst; C11, 6.5.7 Abs. 3 bzw. 6.3.1.1 Abs. 2). Deshalb ist die Anzahl der zu shiftenden Bit nicht größer/gleich der Operandenbreite (die eben sizeof(int) * 8 = 32 ist) und es gibt keinen Grund zu warnen.

Nur, um es gesagt zu haben. :3

timon

  • Beiträge: 13
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 23. July 2013, 21:41 »
Hier habe ich nen link zum direkten output unter Linux:
http://pastebin.com/5CSzknUX
Dort ist aber nichts zum IRQ11
Der Code für die Maskfunktion stammt von dem PIC Tutorial im Wiki, als ich auf der Suche nach einer Lösung war, hab ich den gefunden. Ich habe den Code kopiert, weil er so einfach war habe ich ihn nicht hinterfragt.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 23. July 2013, 21:57 »
Den Code im Wiki habe ich mal korrigiert. Das ist vermutlich nicht der letzte verbuggte Code im Wiki.

Aber zum eigentlichen Problem fällt mir auch nichts mehr ein. Vermutlich hilft da nur selektiv nur die IRQs aktivieren, die du auch tatsächlich verarbeitest.
Dieser Text wird unter jedem Beitrag angezeigt.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 23. July 2013, 22:39 »
Hier habe ich nen link zum direkten output unter Linux:
http://pastebin.com/5CSzknUX
Dort ist aber nichts zum IRQ11
Das ist wohl so, weil Linux den APIC benutzt.

Du könntest deinen Kernel die PCI-Geräte mit zugehöriger IRQ-Nummer ausgeben lassen, aber vielleicht wäre das ein bisschen zu weit vorgegriffen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

timon

  • Beiträge: 13
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 24. July 2013, 11:13 »
Aber ich müsste PCI doch erstmal initialisieren bevor ein PCI Gerät mir Interrupts senden darf oder?

Edit: Ich habe gerade den Code gefixt und begonnen mit den Einstellungen für die übrigen Interrupts herumzuspielen. Dabei habe ich den Timer von 100 hz auf 1000hz verändert. Nur kann mein Notebook keine 1000 Timerinterrupts verarbeiten. Der Interruptzähler zählt nur etwa 300 Interrupts pro Sekunde. Ist mein PC wirklich so langsam oder ist das nur schrecklich ineffizienter Code den ich habe?
« Letzte Änderung: 24. July 2013, 12:43 von timon »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 24. July 2013, 17:48 »
Edit: Ich habe gerade den Code gefixt und begonnen mit den Einstellungen für die übrigen Interrupts herumzuspielen. Dabei habe ich den Timer von 100 hz auf 1000hz verändert. Nur kann mein Notebook keine 1000 Timerinterrupts verarbeiten. Der Interruptzähler zählt nur etwa 300 Interrupts pro Sekunde. Ist mein PC wirklich so langsam oder ist das nur schrecklich ineffizienter Code den ich habe?
Ein modernes System sollte 1000 Interrupts pro Sekunde problemlos schaffen. Aber wenn du in der Interruptroutine zum Beispiel Ausgaben auf dem Bildschirm machst, dann kann das durchaus knapp werden. Ohne Code kann man da keine genauere Aussage treffen.
Dieser Text wird unter jedem Beitrag angezeigt.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 25. July 2013, 00:00 »
Dort ist aber nichts zum IRQ11
Du könntest versuchen, den Linux-Kernel mit "noapic" zu booten und dann nochmal nachzuschauen.

timon

  • Beiträge: 13
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 25. July 2013, 23:14 »
Hallo Zusammen

Ich habe jetzt mit noapic gebootet und habe ein Ergebnis für IRQ11.
http://pastebin.com/CsqK8heQ
So wie es aussieht was mit USB2. Ich habs noch nicht gegoogelt.

Der Notebook schafft übrigens ohne Ausgabe auf dem Bilschirm bis zu 4000 timer interrupts.
Ich finde das ist immer noch zu wenig.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 26. July 2013, 01:22 »
Der Notebook schafft übrigens ohne Ausgabe auf dem Bilschirm bis zu 4000 timer interrupts.
Ich finde das ist immer noch zu wenig.

Zu wenig für was? Vielleicht wenn auf deinem OS die Steuerungssoftware für eine Rakete laufen soll.

Wenn du die Rate erhöhen willst, musst du die Zahl der Speicherzugriffe und Hardware I/O im Handler verringern. CPU-seitig kannst du da nur ein paar hundert Nanosekunden rausholen, wenn du Änderunge der Segmentregistern (inkl. Ring-Wechsel) vermeidest und natürlich einfach weniger Code ausführst. Aber das steht ja alles in Konflikt mit den Anforderungen an die Funktionalität.

Vielleicht weiß hier ja auch jemand, auf welche Raten der PIT normalerweise ausgelegt ist. Von Windows wird der ja gar nicht mit so hohen Raten betrieben. Kann ja sein, dass der einfach nicht mehr kann.
Dieser Text wird unter jedem Beitrag angezeigt.

 

Einloggen