Autor Thema: Kleines IDT-Problem  (Gelesen 5286 mal)

presswurst

  • Beiträge: 13
    • Profil anzeigen
Gespeichert
« am: 04. August 2007, 17:58 »
Hallo Community,

Schon den ganzen Tag versuche ich eine IDT anzulegen, leider ohne Erfolg so dass ich mal Teile meines Codes hier poste, vllt findet ja jemand den Fehler:

Zuerst die Struktur (habe ich von http://www.osdev.org/wiki/IDT):

#pragma pack(push,2)
struct idt {
unsigned short offset1;
unsigned short select;
unsigned char reserved;
unsigned char attr;
unsigned short offset2;
};
#pragma pack(pop)
-- das pragma sollte alignment-bytes verhindern.

Auf globaler Ebene habe ich einen Speicherbereich fuer die IDT reserviert (struct idt idt[256]).

Nun kommt die Funktion mit der ich einzelne IDT-Eintraege setze:

void setidt(struct idt *idt, unsigned int offset) {
unsigned short codesel;

asm ("mov %%cs, %%ax\n\tmov %%ax, %0" : "=r" (codesel) :: "%eax");

idt->select = codesel;
idt->offset1 = offset & 0xffff;
idt->offset2 = (offset >> 16) & 0xffff;
idt->attr = 0x8e;
}
(Man beachte dass es sich bei 'offset' um eine Adresse einer Funktion handelt)

Ich habe mal einen Test-Eintrag erstellt:
setidt(&idt[0x7f], (unsigned int)do_nothing);
(do_nothing ist eine Funtion die nur eine Anweisung enthaelt: 'iret', daher kann der fehler als auch nicht kommen).

Als Letztes kommt noch eine Funktion um die IDT zu laden (void loadidt(struct idt*)):

.globl _loadidt
_loadidt:

push %ebp
mov %esp, %ebp
mov 8(%ebp), %eax
mov %eax, (bas)
lidt (idts)
leave
ret

idts:
lim: .word 256*8-1
bas: .long 0


Das Ausfuehren eines int 0x7f erzeugt folgenden Fehler:

00046832145e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting


Kann mir vllt jemand sagen wo mein Fehler liegt? Bin schon fast am verzweifeln... :(


lg, presswurst

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #1 am: 04. August 2007, 20:47 »
Das problem könnte die Funktion do_nothing sein. Ist die in C geschrieben? Dann fügt der compiler nämlich zu funktionsbeginn ein push ebp ein. Dieses bringt natürlich dein iret ziemlich durcheinander ;-)
btw. wenn du in bochs testest, dann setzt doch einfach mal in den logging optionen für CPU0 alles auf "report". Dann bekommst du eine bessere beschreibung des Problems.
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

presswurst

  • Beiträge: 13
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 04. August 2007, 21:29 »
lol ne, also so stoffelig bin ich ja auch nicht :p

Meine do_nothing Funktion sieht so aus:
.globl _do_nothing
_do_nothing: iret

Report? dann werd ich mich Morgen wohl durch die docs graben muessen - Aber danke fuer den Tip :)

EDIT:
hmpf, ich vergesse immer wieder dass man die Einstellungen vom bochs auch ganz bequem in der Console veraendern kann... hier kommt man der komplette auszug:

Zitat
00204344146i[CPU0 ] BxError: instruction with opcode=0xff
00204344146i[CPU0 ] mod was c0, nnn was 7, rm was 7
00204344146i[CPU0 ] WARNING: Encountered an unknown instruction (signalling ille
gal instruction)
00204344146e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00204344146e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00204344146i[CPU0 ] protected mode
00204344146i[CPU0 ] CS.d_b = 32 bit
00204344146i[CPU0 ] SS.d_b = 32 bit
00204344146i[CPU0 ] | EAX=00105000  EBX=0002bd20  ECX=0001c300  EDX=001053f8
00204344146i[CPU0 ] | ESP=00104fdc  EBP=00104ff0  ESI=0002be60  EDI=00000080
00204344146i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af pf cf
00204344146i[CPU0 ] | SEG selector     base    limit G D
00204344146i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00204344146i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00204344146i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00204344146i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00204344146i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00204344146i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00204344146i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00204344146i[CPU0 ] | EIP=e58955cf (e58955cf)
00204344146i[CPU0 ] | CR0=0x00000011 CR1=0 CR2=0x00000000
00204344146i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00204344146i[CPU0 ] >> (invalid)  : FFFF
00204344146e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown
 status is 00h, resetting
00204344146i[SYS  ] bx_pc_system_c::Reset(SOFTWARE) called

Kannst du damit was anfangen?
« Letzte Änderung: 04. August 2007, 21:42 von presswurst »

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #3 am: 05. August 2007, 12:45 »
Aus dem Log kann ich so auch nur entnehmen, dass er an eine falsche Adresse springt und irgendeinen Mist ausführt, was dann zum tripple fault führt.
Hast du IF auf 0 gesetzt (so das keine IRQs dich stören)? Hast du schonmal hinter das "lidt" ein hlt eingefügt und im bochs debugger mittels dump_cpu das IDTR überprüft? btw. kommt im bochs Log noch irgendwas interessantes vor dem was du gepostet hast?
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

presswurst

  • Beiträge: 13
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 06. August 2007, 19:18 »
Das ist es wohl gewesen. Ich musste feststellen das Grub das das Interrupt Flag geloescht hat. Allerdings kommen mit IF weitere Probleme auf:

Bei jedem call, int oder ret gibt es wieder eine exception (Ohne IF ist dies nicht der Fall). Woran koennte das liegen? Muss ich erst den PIC neu programmieren bzw fuer alle "reservierten" Interrupts (also Exception-Inerrupts und IRQ-Interrupts) eine Routine erstellen?

Die 256*8 Bytes der IDT stammen aus der BSS-Sektion alle Eintraege (abgesehen von Interrupt 0x7f) enthaelten deswegen nur 0x00-Bytes, kommt die CPU damit evtl nicht zurecht?

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 06. August 2007, 20:23 »
Nullen würde ich nicht gut finden. Aber du kannst ja alle Einträge auf einen Handler leiten der nichts als ein IRET beinhaltet.

Wenn ein Handler mit einem Interrupt-Gate aufgerufen wird, eben das IF-Flag wieder löschen...Das geht mit einem IRET nach jedem Interrupt-Handler.

Hast du denn jetzt das Flag per Hand gesetzt? Ich blick da nicht ganz durch das sollte nicht nötig sein...Hat bluecode nicht gemeint ob das Flag während des Handlers gesetzt ist? (Was eben durch einen Handler per Interrupt-Gate erreicht wird)

Gruss
Noooooooooooos

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #6 am: 06. August 2007, 20:52 »
Eigentlich wollte ich das IF generell auf 0 (und d.h. das IRQ DEaktiviert sind!), damit dir keine IRQs in die Quere kommen (da du ja keine Deskriptoren für diese Interrupts in der IDT hast).
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