IDT works partially
Posted: Fri Sep 07, 2012 4:52 pm
Hi, I have a strange problem with the IDT. I have read the topics about it in the wiki:
http://wiki.osdev.org/IDT
http://wiki.osdev.org/IDT_problems#Problems_with_IDTs
and in the AMD 64 manual...
The problem is that, my IDT catch the exceptions but I can´t activate the interruptions, I got a Double Fault when I activate it.
I show you my GDT.
The idt_ptr is in interrupts.asm:
I think that the exceptions work fine:
Thanks for advance.
http://wiki.osdev.org/IDT
http://wiki.osdev.org/IDT_problems#Problems_with_IDTs
and in the AMD 64 manual...
The problem is that, my IDT catch the exceptions but I can´t activate the interruptions, I got a Double Fault when I activate it.
I show you my GDT.
Code: Select all
; Enable paging to activate long mode
mov eax, cr0
or eax, 0x80000000 ; PG (Bit 31)
mov cr0, eax
jmp GDT64.Code:long_mode
GDT64: ; Global Descriptor Table (64-bit).
.Null: equ $ - GDT64 ; The null descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 0 ; Access.
db 0 ; Granularity.
db 0 ; Base (high).
.Code: equ $ - GDT64 ; The code descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 10011000b ; Access.
db 00100000b ; Granularity.
db 0 ; Base (high).
.Data: equ $ - GDT64 ; The data descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 10010000b ; Access.
db 00000000b ; Granularity.
db 0 ; Base (high).
.Pointer: ; The GDT-pointer.
dw $ - GDT64 - 1 ; Limit.
dq GDT64 ; Base.
[BITS 64]
long_mode:
cli ; Clear the interrupt flag.
mov ax, GDT64.Data ; Set the A-register to the data descriptor.
mov ds, ax ; Set the data segment to the A-register.
mov es, ax ; Set the extra segment to the A-register.
mov fs, ax ; Set the F-segment to the A-register.
mov gs, ax ; Set the G-segment to the A-register.
cpp_kernel:
Code: Select all
void idt::init_idt()
{
idt_ptr.limit = (sizeof(idt_entry_t) * IDT_NUMBER_OF_ENTRIES) - 1;
idt_ptr.offset = (QWORD)&::idt_entries;
clean_gates();
idt_set_gate(0, (QWORD)isr0, 0x08, 0x8E);
idt_set_gate(1, (QWORD)isr1, 0x08, 0x8E);
idt_set_gate(2, (QWORD)isr2, 0x08, 0x8E);
idt_set_gate(3, (QWORD)isr3, 0x08, 0x8E);
idt_set_gate(4, (QWORD)isr4, 0x08, 0x8E);
idt_set_gate(5, (QWORD)isr5, 0x08, 0x8E);
idt_set_gate(6, (QWORD)isr6, 0x08, 0x8E);
idt_set_gate(7, (QWORD)isr7, 0x08, 0x8E);
idt_set_gate(8, (QWORD)isr8, 0x08, 0x8E);
idt_set_gate(9, (QWORD)isr9, 0x08, 0x8E);
idt_set_gate(10, (QWORD)isr10, 0x08, 0x8E);
idt_set_gate(11, (QWORD)isr11, 0x08, 0x8E);
idt_set_gate(12, (QWORD)isr12, 0x08, 0x8E);
idt_set_gate(13, (QWORD)isr13, 0x08, 0x8E);
idt_set_gate(14, (QWORD)isr14, 0x08, 0x8E);
idt_set_gate(15, (QWORD)isr15, 0x08, 0x8E);
idt_set_gate(16, (QWORD)isr16, 0x08, 0x8E);
idt_set_gate(17, (QWORD)isr17, 0x08, 0x8E);
idt_set_gate(18, (QWORD)isr18, 0x08, 0x8E);
idt_set_gate(19, (QWORD)isr19, 0x08, 0x8E);
idt_set_gate(20, (QWORD)isr20, 0x08, 0x8E);
idt_set_gate(21, (QWORD)isr21, 0x08, 0x8E);
idt_set_gate(22, (QWORD)isr22, 0x08, 0x8E);
idt_set_gate(23, (QWORD)isr23, 0x08, 0x8E);
idt_set_gate(24, (QWORD)isr24, 0x08, 0x8E);
idt_set_gate(25, (QWORD)isr25, 0x08, 0x8E);
idt_set_gate(26, (QWORD)isr26, 0x08, 0x8E);
idt_set_gate(27, (QWORD)isr27, 0x08, 0x8E);
idt_set_gate(28, (QWORD)isr28, 0x08, 0x8E);
idt_set_gate(29, (QWORD)isr29, 0x08, 0x8E);
idt_set_gate(30, (QWORD)isr30, 0x08, 0x8E);
idt_set_gate(31, (QWORD)isr31, 0x08, 0x8E);
idt_flush();
}
void idt::clean_gates()
{
for (int i = 0; i < IDT_NUMBER_OF_ENTRIES; i++)
{
idt_entries[i].flag0 = 0;
idt_entries[i].flags = 0;
idt_entries[i].high_base_addr = 0;
idt_entries[i].low_base_addr = 0;
idt_entries[i].middle_base_addr = 0;
idt_entries[i].segment_sel = 0;
idt_entries[i].zero = 0;
}
}
void idt::idt_set_gate(BYTE idt_num, QWORD base_addr, WORD segment_sel, BYTE flags)
{
idt_entries[idt_num].low_base_addr = (WORD) (base_addr & 0x000000000000FFFF);
idt_entries[idt_num].middle_base_addr = (WORD) ((base_addr & 0x00000000FFFF0000) >> 16);
idt_entries[idt_num].high_base_addr = (DWORD)(base_addr >> 32);
idt_entries[idt_num].segment_sel = segment_sel;
idt_entries[idt_num].flag0 = NULL;
idt_entries[idt_num].flags = flags;
idt_entries[idt_num].zero = NULL;
}
Code: Select all
section .text
global idt_ptr
idt_ptr:
idt_limit dw 0
idt_address dq 0
global idt_flush
idt_flush:
lidt [idt_ptr]
ret
Code: Select all
/*
* Kernel.cpp
*
* Kernel Entry Point
*
*/
#include <Drivers\screen.h>
#include <idt.h>
#include <irq.h>
/* http://wiki.osdev.org/I_Cant_Get_Interrupts_Working */
/* http://wiki.osdev.org/Memory_Map_%28x86%29#Overview */
extern "C" void kmain()
{
screen::clear_screen();
screen::hide_cursor();
idt::init_idt();
screen::kprintf("Starting IDT...\n");
/*irq::init_irq();
screen::kprintf("Starting IRQs...\n\n");*/
screen::set_text_attributes(VGA::LIGHT_RED, VGA::BLACK);
screen::kputs("> ");
screen::set_text_attributes(VGA::WHITE, VGA::BLACK);
screen::kputs("khronos#: ");
int i = 5 / 0;
//asm("sti");
for (;;){
}
}