Lowlevel

Lowlevel => Lowlevel-Coding => Thema gestartet von: Drako am 22. October 2008, 14:46

Titel: Triple Fault bei Division By Zero
Beitrag von: Drako am 22. October 2008, 14:46
hallöchen,

also, mit Hilfe dieser beiden Seiten:
http://www.osdever.net/bkerndev/Docs/idt.htm
http://www.osdever.net/bkerndev/Docs/isrs.htm

hab ich versucht mir eine IDT und die ersten 32 ISRs einzurichten.

bis auf geringfügige Namensänderungen hab ich die Sachen aus den Tuts weitestgehend übernommen.
zum Test hab ich ans Ende der main() ein 10 / 0 stehen.
Aber anstatt, dass mein fault_handler() mir die Fehlermeldung zeigt,
startet der Rechner/Bochs einfach neu.

Hier mein Kernel:
#include "screen.h"
#include "multiboot.h"
#include "gdt.h"
#include "idt.h"

int main(struct mbs* pMBS)
{
int div_by_zero;
gdt_install();
idt_install();
clrscr();
set_color(COLOR_LIGHTGREEN);
printstr("DrakOS Version 1.0\n");
printstr("Copyright (C) 2008, Felix Bytow\n\n");
set_color(COLOR_LIGHTGREY);
printstr("Gebootet von: ");
printstr((char*)(pMBS->mbs_boot_loader_name));
div_by_zero = 10 / 0; // Hier bricht alles zusammen
while(true);
return 0;
}

meine IDT:
// idt.h
#if !defined(IDT_H)
#define IDT_H

#include "types.h"

struct idt_entry
{
word offset_low;
word selector;
byte null;
byte flags;
byte offset_high;
} __attribute__((packed));

struct idt_ptr
{
word limit;
dword base;
} __attribute__((packed));

#define IDT_SIZE 256

void idt_fill_descriptor(byte entry, dword base, word sel, byte flags);
void idt_install(void);
void idt_load(void);

void enable_interrupts(void);
void disable_interrupts(void);

#endif


// idt.c
#include "idt.h"
#include "memory.h"
#include "isr.h"

struct idt_entry idt[IDT_SIZE];
struct idt_ptr idtp;

void idt_fill_descriptor(byte entry, dword base, word sel, byte flags)
{
idt[entry].offset_low = (base & 0xFFFF);
idt[entry].selector = sel;
idt[entry].null = 0;
idt[entry].flags = flags;
idt[entry].offset_high = ((base >> 16) & 0xFFFF);
}

void idt_install(void)
{
idtp.limit = (sizeof(struct idt_entry) * IDT_SIZE) - 1;
idtp.base = (dword)&idt;

memset(&idt, 0, sizeof(struct idt_entry) * IDT_SIZE);

isrs_install();
// TODO: Neue Interrupts setzen

idt_load();
}

void enable_interrupts(void)
{
asm("sti");
}

void disable_interrupts(void)
{
asm("cli");
}

und hier die isrs (gekürzt)
// isr.h
#if !defined(ISR_H)
#define ISR_H

#include "types.h"

void isr0(void);
// ...
void isr31(void);

struct regs
{
dword gs, fs, es, ds;
dword edi, esi, ebp, esp, ebx, edx, ecx, eax;
dword int_no, err_code;
dword eip, cs, eflags, useresp, ss;
} __attribute__((packed));

void isrs_install(void);
void fault_handler(struct regs *r);

#endif

// isr.c
#include "isr.h"
#include "idt.h"
#include "screen.h"

void isrs_install(void)
{
idt_fill_descriptor(0, (dword)&isr0, 0x08, 0x8E);
// ...
idt_fill_descriptor(31, (dword)&isr31, 0x08, 0x8E);
}

char *exception_messages[] =
{
"Division By Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out Of Bounds",
"Invalid Opcode",
"No Coprocessor",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS",
"Segment Not Present",
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Unknown Interrupt",
"Coprocessor Fault",
"Alignment Check",
"Machine Check",
"Reserved",
// ...
"Reserved"
};

void fault_handler(struct regs *r)
{
if (r->int_no < 32)
{
set_color(COLOR_RED);
printstr(exception_messages[r->int_no]);
printstr(" Exception. System Halted!");
while (true);
}
}

und das Stückchen asm dazu:
global idt_load
extern idtp

idt_load:
    lidt [idtp]
    ret

ich kann beim besten Willen nichts finden, wo meine idt kaputt wäre...

würde mich freuen, wenn mir hier jmd weiterhelfen könnte.

MfG Drako
Titel: Re: Triple Fault bei Division By Zero
Beitrag von: Drako am 22. October 2008, 14:54
auf Grund der geschulten Augen der Leute im IRC ergab sich folgende Korrektur:

// ...
struct idt_entry
{
    word offset_low;
    word selector;
    byte null;
    byte flags;
    word offset_high;
} __attribute__((packed));
// ...

Leider stürzt der Kernel immer noch ab.
Titel: Re: Triple Fault bei Division By Zero
Beitrag von: ChristianF am 28. October 2008, 08:16
Nun...
Ich weiß ja nicht, ob das Problem noch besteht...
Folgenden Code hast du gepostet:
void idt_install(void)
{
idtp.limit = (sizeof(struct idt_entry) * IDT_SIZE) - 1;
idtp.base = (dword)&idt;

memset(&idt, 0, sizeof(struct idt_entry) * IDT_SIZE);

isrs_install();
// TODO: Neue Interrupts setzen

idt_load();
}
Allerdings solltest du erst die Funktion zum laden der idt "idt_load" und dann die Funktion zum setzen der ISRs "isrs_install" aufrufen.

Nach dem Tutorial musst du erst die IDT initialisieren und dann die ISRs setzen (so steht das dort). Also müsste die Funktion wie folgt aussehen:
void idt_install(void)
{
idtp.limit = (sizeof(struct idt_entry) * IDT_SIZE) - 1;
idtp.base = (dword)&idt;

memset(&idt, 0, sizeof(struct idt_entry) * IDT_SIZE);

// TODO: Neue Interrupts setzen

idt_load();
isrs_install();
}

Ich hoffe, ich konnte dir damit weiterhelfen.
Gruß Christian
Titel: Re: Triple Fault bei Division By Zero
Beitrag von: MNemo am 28. October 2008, 11:08
Nein, nein. Das stimmt schon so.
Das idt_load sollte erst aufgerufen werden, wenn die IDT fertig ist. Und die ISRs werden ja dierekt in die IDT eingetragen(sie ist also noch nicht fertig). Mit initialisieren ist nur die memset-Zeile gemeint.
Titel: Re: Triple Fault bei Division By Zero
Beitrag von: ChristianF am 29. October 2008, 12:04
Nun ich mache das wie im Tutorial, da ich dieses auch gelesen habe.  :roll:
Ich rufe bei mir zuerst idt_install() und dann isrs_install() auf und das funktioniert tadellos.
Ich dachte nur, dass es vielleicht daran liegt...
Titel: Re: Triple Fault bei Division By Zero
Beitrag von: MNemo am 29. October 2008, 13:02
@Drako:
was sagt denn eigentlich das log von bochs zu der ganzen sache

die logdatei ganzt du mit "log: <file>" in der bochsrc festlegen