Autor Thema: IDT laden  (Gelesen 6289 mal)

boom1

  • Beiträge: 6
    • Profil anzeigen
Gespeichert
« am: 23. July 2008, 18:08 »
Hi,

Nachdem ich es jetzt hinbekommen habe, die GDT zu laden, habe ich nun versucht die IDT zu laden und die ISRs für die Exceptions zu definieren.  :wink:

Ich habe folgenden Code in meinem C-Kernel:


#include "kernelc.h"

int main()
{
/* Build-up the GDT */
gdt_setup();
/* Build-up the IDT */
idt_setup();
/* Install the first 32 Exception handler in the IDT */
isrs_install();

// Pointer zum Videospeicher
char *video = (char*)0xB8000;

// Pointer auf die Nummer, des nächsten Zeichens im Videospeicher
//int iVideoPtr = 0;

// String zum Ausgeben
char *hello = "Hello World One\r\n";
    char *hello2 = "Hello World Two\r\n";
 
// Zuerst den Speicher leeren
ClearScreen(video);

// String ausgeben
printk(hello);
printk(hello2);

//Exception asulösen
int n = n/((n/n)-1);

// jetzt wo wir schon im Kernel drin sind, wollen wir auch nicht mehr raus ;)
while (1);
return 0;
}

Der Ausschnitt aus meiner kernel.asm, in welchem ich die IDT lade:
[...]
idt_load_asm:
lidt [idtp] ; IDT laden
ret
[...]

Und ich habe eine Datei idt.c, in welcher ich Funktionen etc. zur IDT habe;
/******************** == IDT == ****************/

/* Defines a single IDT entry */
struct idt_entry
{
unsigned short base_low;
unsigned short selector;
unsigned char always0;
unsigned char access;
unsigned short base_high;
} __attribute__((packed));

/* Defines a IDT pointer */
struct idt_ptr
{
unsigned int base;
unsigned short size;
} __attribute__((packed));

struct idt_entry idt[256];
struct idt_ptr idtp;

/* Load the IDT.
Defined in the ASM-Lernel, so declared as extern. */
extern void idt_load_asm ();

/* Setup a new descriptor */
void idt_setup_entry (unsigned char cNum, unsigned int iBase, unsigned short shSelector,
unsigned char cAccess)
{
idt[cNum].base_low = (iBase & 0xFFFF);
idt[cNum].selector = shSelector;
idt[cNum].always0 = 0;
idt[cNum].access = cAccess;
idt[cNum].base_high = ((iBase >> 16) & 0xFFFF);
}

/* Setup the IDT pointer */
void idt_ptr_setup ()
{
idtp.base = (unsigned int) &idt;
idtp.size = (sizeof(struct idt_entry)*256) - 1;
}

/* Declare the MemSet function in kernel/memset.c as extern */
extern void memset (void *pDest, char cValue, unsigned int iCount);

/* Setup the whole IDT */
void idt_setup ()
{
idt_ptr_setup ();

/* Clear the entire IDT */
memset (&idt, 0, sizeof(struct idt_entry)*256);

idt_load_asm ();
}

Ausserdem habe ich noch eine isr.c und isr.asm, in welcher ich die ISRs definiere.
isr.c:
/********************** == ISR == ************************/

/* declare a function to print on the output as extern */
extern void printk (char *pText);

/* the external function prototypes for all
of the exception handlers. The first 32 entries
in the IDT are reserved by Intel */
extern void isr0();
extern void isr1();
extern void isr2();
extern void isr3();
extern void isr4();
extern void isr5();
extern void isr6();
extern void isr7();
extern void isr8();
extern void isr9();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();

/* Declare the idt_setup_entry function as extern.
This function sets an IDT entry and is defined in
/tables/idt/idt.c */
extern void idt_setup_entry (unsigned char cNum, unsigned int iBase, unsigned short shSelector,
unsigned char cAccess);

/* A structure containing the register */
struct registers
{
unsigned int gs, fs, es, ds;      /* pushed the segs last */
    unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;  /* pushed by 'pusha' */
    unsigned int int_no, err_code;    /* our 'push byte #' and ecodes do this */
    unsigned int eip, cs, eflags, useresp, ss;    /* pushed by the processor automatically */
};

/* Install the first 32 ISRs, that handle the first
32 exceptions */
void isrs_install ()
{
idt_setup_entry (0, (unsigned int) isr0, 0x08, 0x8E);
idt_setup_entry (1, (unsigned int) isr1, 0x08, 0x8E);
idt_setup_entry (2, (unsigned int) isr2, 0x08, 0x8E);
idt_setup_entry (3, (unsigned int) isr3, 0x08, 0x8E);
idt_setup_entry (4, (unsigned int) isr4, 0x08, 0x8E);
idt_setup_entry (5, (unsigned int) isr5, 0x08, 0x8E);
idt_setup_entry (6, (unsigned int) isr6, 0x08, 0x8E);
idt_setup_entry (7, (unsigned int) isr7, 0x08, 0x8E);
idt_setup_entry (8, (unsigned int) isr8, 0x08, 0x8E);
idt_setup_entry (9, (unsigned int) isr9, 0x08, 0x8E);
idt_setup_entry (10, (unsigned int) isr10, 0x08, 0x8E);
idt_setup_entry (11, (unsigned int) isr11, 0x08, 0x8E);
idt_setup_entry (12, (unsigned int) isr12, 0x08, 0x8E);
idt_setup_entry (13, (unsigned int) isr13, 0x08, 0x8E);
idt_setup_entry (14, (unsigned int) isr14, 0x08, 0x8E);
idt_setup_entry (15, (unsigned int) isr15, 0x08, 0x8E);
idt_setup_entry (16, (unsigned int) isr16, 0x08, 0x8E);
idt_setup_entry (17, (unsigned int) isr17, 0x08, 0x8E);
idt_setup_entry (18, (unsigned int) isr18, 0x08, 0x8E);
idt_setup_entry (19, (unsigned int) isr19, 0x08, 0x8E);
idt_setup_entry (20, (unsigned int) isr20, 0x08, 0x8E);
idt_setup_entry (21, (unsigned int) isr21, 0x08, 0x8E);
idt_setup_entry (22, (unsigned int) isr22, 0x08, 0x8E);
idt_setup_entry (23, (unsigned int) isr23, 0x08, 0x8E);
idt_setup_entry (24, (unsigned int) isr24, 0x08, 0x8E);
idt_setup_entry (25, (unsigned int) isr25, 0x08, 0x8E);
idt_setup_entry (26, (unsigned int) isr26, 0x08, 0x8E);
idt_setup_entry (27, (unsigned int) isr27, 0x08, 0x8E);
idt_setup_entry (28, (unsigned int) isr28, 0x08, 0x8E);
idt_setup_entry (29, (unsigned int) isr29, 0x08, 0x8E);
idt_setup_entry (30, (unsigned int) isr30, 0x08, 0x8E);
idt_setup_entry (31, (unsigned int) isr31, 0x08, 0x8E);
}

char *exception_name[] =
{
"Division By Zero Exception", /* 0 */
"Debug Exception",
"Non Maskable Interrupt Exception",
"Breakpoint Exception",
"Into Detected Overflow Exception",
"Out of Bounds Exception", /* 5 */
"Invalid Opcode Exception",
"No Coprocessor Exception",
"Double Fault Exception",
"Coprocessor Segment Overrun Exception",
"Bad TSS Exception",
"Segment Not Present Exception",
"Stack Fault Exception",
"General Protection Fault Exception",
"Page Fault Exception",
"Unknown Interrupt Exception",
"Coprocessor Fault Exception",
"Alignment Check Exception (486+)",
"Machine Check Exception (Pentium/586+)",
"Reserved Exception", /* 19 */
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception" /* 31 */
};

void fault_handler (struct registers *regs)
{
if (regs->int_no <= 31)
{
/* Display the description of the exception */
printk (exception_name[regs->int_no]);
printk ((char *) " Exception. System will now halt!\r\n");
for (;;) ;
}
}

und hier die isr.asm --> Link
(die ist etwas lang, deshalb will ich die nicht hier posten)


Wenn ich jetzt allerdings, meinen kernel versuche mit qemu zu öffnen, stürtzt er mir ab.
Er zeigt mir folgendes:
qemu: fatal: triple fault
EAX=00000000 EBX=0002d8e4 ECX=0000005f EDX=00000000
ESI=00054527 EDI=00054528 EBP=001fffe8 ESP=001fffd0
EIP=00100942 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300
CS =0008 00000000 ffffffff 00cf9a00
SS =0010 00000000 ffffffff 00cf9300
DS =0010 00000000 ffffffff 00cf9300
FS =0010 00000000 ffffffff 00cf9300
GS =0010 00000000 ffffffff 00cf9300
LDT=0000 00000000 0000ffff 00008000
TR =0000 00000000 0000ffff 00008000
GDT=     00102080 00000017
[b]IDT=     07ff0010 000020c0[/b]
CR0=60000011 CR2=00000000 CR3=00000000 CR4=00000000
CCS=00000018 CCD=001fffc0 CCO=ADDL   
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
Aborted

Wenn ich mir jetzt den EIP Register anschaue, dann zeigt der genau auf dei Stelle, an der ich eine Exception provoziere:

Zitat
10093d:   89 d0                   mov    %edx,%eax
  10093f:   c1 fa 1f                sar    $0x1f,%edx
  100942:   f7 7d f8                idivl  -0x8(%ebp)
  100945:   83 e8 01                sub    $0x1,%eax
  100948:   8b 55 f8                mov    -0x8(%ebp),%edx

Aber eigentlich, habe ich doch eine eigene ISR gemacht, die eben das abfangen soll...
Eventuell liegt das daran, dass die IDT nicht richtig geladen wurde.
(in der Fehlermeldung von qemu gibt es eine Zeile, wo die IDT drinsteht, und da steht eine komische Zahl dran)
Allerdings kann ich es mir nicht erklären, dass die IDT nicht richtig geladen wurde...

Wisst ihr was ich da falsch mache?

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 23. July 2008, 18:58 »
Hi,

ich bin mir jetzt nicht sicher, aber müssen für Exceptions nicht die Interrupts aktiviert sein?
Dieser Text wird unter jedem Beitrag angezeigt.

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #2 am: 23. July 2008, 19:01 »
ich bin mir jetzt nicht sicher, aber müssen für Exceptions nicht die Interrupts aktiviert sein?
Nein.
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

jgraef

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 23. July 2008, 21:19 »
Hi,

Sieht eigentlich super aus. Wahrscheinlich ist das irgendein fieser kleiner Fehler. Der Triple-Fault bedeutet, dass die Exceptions nicht aufgelöst werden können, d.h was mit deiner IDT/ISRs nicht stimmt. Das Problem bei solchen Fehlern ist, dass man sie schlecht debuggen kann. Du musst wohl oder übel noch mal alles genau durchgehen.

PS: Damit man nicht immer die ganzen externen Funktionen in den Sourcen einzeln deklarieren muss, baut man sich Header. Du hast z.B memset in isr.c "per Hand" deklariert.

EDIT: Dein Allgemeiner ISR-Handler addiert am Ende 8 zu ESP, wobei du ja nicht immer einen Dummy-Errorcode auf den Stack legst. Da wo von der CPU ein Errorcode auf den Stack gelegt wird, musst du diesen auch nicht wieder vom Stack "löschen". Außerdem ist das CLI am Anfang aller ISRs unnötig, da während eines Interrupts, Interrupts ausgeschaltet sind.
« Letzte Änderung: 24. July 2008, 01:01 von jgraef »

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #4 am: 24. July 2008, 06:43 »
Wenn du beim qemu-Aufruf "-d int" mitübergibst, dann logt qemu die Interrupts/Exceptions und die Adresse an der sie auftreten. Unter Linux steht das ganze dann unter /tmp/qemu.log, kA wo das bei Windows ist. Dann schaust du wo in deinem Code die erste Exception auftritt und bist hoffentlich schlauer als vorher :-)
In welcher deiner Funktionen ist denn das idivl? Wenn das vor dem Laden der IDT ist, dann ist wohl klar, dass es nicht von deinen Exception-Handlern abgefangen wird.
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

boom1

  • Beiträge: 6
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 24. July 2008, 11:05 »
Das idivl ist in der main-Funktion. Und es ist genau da, wo ich in der main Funktion die Exception provoziere, da ich durch 0 teile. Das ist hinter dem Laden den IDT:
Deshalb hab ich vermutet, dass die IDT nicht richtig geladen wurde, weil doch sonst die Exception durch dei isr0() abgefangen worden wäre...

Ich bin gerade nochmal alles Schritt für Schritt durchgegangen, hab den Fehler aber leider nicht gefunden...

Korona

  • Beiträge: 94
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 24. July 2008, 16:54 »
/* Defines a IDT pointer */
struct idt_ptr
{
unsigned int base;
unsigned short size;
} __attribute__((packed));
ist falsch. Die Größe steht in den ersten zwei Bytes, nicht in den letzten.

boom1

  • Beiträge: 6
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 24. July 2008, 18:41 »
Danke, du hast recht! Ich trottel... ;-) Deshalb stand in der Ausgabe auch so eine komische Adresse bei der IDT. Zumindest geht es jetzt endlich

 

Einloggen