IDT works partially

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Khronos
Posts: 23
Joined: Sat Jul 21, 2012 5:29 am

IDT works partially

Post by Khronos »

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.
int8.png


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;
}
The idt_ptr is in interrupts.asm:

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
I think that the exceptions work fine:

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 (;;){
	}
}
int0.png
Thanks for advance.
User avatar
eryjus
Member
Member
Posts: 286
Joined: Fri Oct 21, 2011 9:47 pm
Libera.chat IRC: eryjus
Location: Tustin, CA USA

Re: IDT works partially

Post by eryjus »

I suspect idt_entries[].* is not packed... You didn't post its definition, but it will be of interest.
Adam

The name is fitting: Century Hobby OS -- At this rate, it's gonna take me that long!
Read about my mistakes and missteps with this iteration: Journal

"Sometimes things just don't make sense until you figure them out." -- Phil Stahlheber
Khronos
Posts: 23
Joined: Sat Jul 21, 2012 5:29 am

Re: IDT works partially

Post by Khronos »

Hi eryjus, yes, you are right. Here is their definition:

Code: Select all

idt_entry_t idt_entries[IDT_NUMBER_OF_ENTRIES];

Code: Select all

#define IDT_NUMBER_OF_ENTRIES 256

struct idt_entry
{
    WORD low_base_addr; //The lower 16 bits of the address to jump to when this interrupt fires.
    WORD segment_sel; //Kernel segment selector.
    BYTE  flag0; //This must always be zero.
    BYTE  flags; //More flags. See documentation.
	WORD middle_base_addr;
    DWORD high_base_addr; //The upper 16 bits of the address to jump to.
	DWORD zero;
} __attribute__((packed));
typedef struct idt_entry idt_entry_t;

struct idt_ptr
{
    WORD limit;
    QWORD offset; //The address of the first element in our idt_entry_t array.
} __attribute__((packed));
typedef struct idt_ptr idt_ptr_t;
Thanks.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: IDT works partially

Post by Combuster »

Sounds like you got an IRQ0 just fine.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: IDT works partially

Post by bluemoon »

Khronos wrote: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.
Check the IRQ, PIC configuration, and related handlers.
Note: To eliminate causes, try do the handler with just IRETQ, without ack the PIC.

Note2: If you implement CPU exceptions (#GP, #PF, #SS, are the 3 most important to implement first), this should help you catch the bug before #DF.
Post Reply