Interrupt handling, GDT, IDT PIC problem [SOLVED]

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.
yolda
Posts: 13
Joined: Wed May 27, 2009 12:56 pm

Interrupt handling, GDT, IDT PIC problem [SOLVED]

Post by yolda »

Hello all, i am new here and ive been trying to get a lil simple os running. I ty in advance for any help.
I ve been trying to get things to work step by step, right now i am stuck at interrupts.
For some reason i cant get them to work, the cpu seems to triple fault and reset(i really dont know where or how or why)

i got a simple GDT with just code and data sectores taking all the memory for now.
i made 256 IDT's all poining to the same asm proc. I tried pointing to a c proc but it gave me the same errors.

I think i initialized the PIC correctly, but when i press '1' i call an int 48(to be on the upside) with cli enabled and
if i enable sti (using '2') and some ints are not mapped to be ignored in the pic, the cpu also resets.

I use nasm for the assembly, and mingw for the c code.

the irq asm i scompiled using "..\nasm-2.05.01\nasm" -f win32 irq.asm -o irq.o and the rest is all linked using

"..\Dev-Cpp\bin\ld" -e _kernel -Ttext 0x1000 -o kernel.o main.o video.c.o ports.c.o keyboard.c.o std.c.o login.c.o shell.c.o memory.c.o scheduler.c.o irq.o

here is the bootloader important section.

Code: Select all


[BITS 32]                       ; We now need 32-bit instructions so we go into protected mode
clear_pipe:
        mov ax, 10h             ; Save data segment identifyer
        mov ds, ax              ; Move a valid data segment into the data segment register
        mov ss, ax              ; Move a valid data segment into the stack segment register
        mov es, ax
	xor eax, eax
	mov fs, ax
	mov gs, ax
	mov esp, 090000h        ; Move the stack pointer to 090000h
        jmp 08h:01000h          ; Jump to section 08h (code), offset 01000h


;http://www.jamesmolloy.co.uk/tutorial_html/4.-The%20GDT%20and%20IDT.html
gdt:                    ; Address for the GDT

gdt_null:               ; Null Segment
        dd 0
        dd 0

gdt_code:               ; Code segment, read/execute, nonconforming
        dw 0FFFFh	; The lower 16 bits of the limit.
        dw 0		; The lower 16 bits of the base.
        db 0		; The next 8 bits of the base.
        db 10011010b	 ; Access flags, determine what ring this segment can be used in.
        db 11001111b	;constant
        db 0		; The last 8 bits of the base.

gdt_data:               ; Data segment, read/write, expand down
        dw 0FFFFh
        dw 0
        db 0
        db 10010010b
        db 11001111b
        db 0

gdt_end:                ; Used to calculate the size of the GDT



gdt_desc:                       ; The GDT descriptor
        dw gdt_end - gdt - 1    ; Limit (size)
        dd gdt                  ; Address of the GDT

here is the irq.asm section on another asm

Code: Select all

[extern _irq_handler]

global  _irq0


section .code

_irq0:

loop:


	jmp loop

     pusha
     push ds
     push es
     push fs
     push gs
     mov eax,0x10    ; Data segment
     mov ds,eax
     mov es,eax
     cld
	
    call _irq_handler

     pop gs
     pop fs
     pop es
     pop ds
     popa
     iret

and finally the part i think the problem is in:

Code: Select all

struct idt {

	//! bits 0-16 of interrupt routine (ir) address
	unsigned short		baseLo;

	//! code selector in gdt
	unsigned short		sel;

	//! reserved, shold be 0
	unsigned char		reserved;

	//! bit flags. Set with flags above
	unsigned char		flags;

	//! bits 16-32 of ir address
	unsigned short		baseHi;
};

struct idtr {

	//! size of the interrupt descriptor table (idt)
	unsigned short		limit;

	//! base address of idt
	unsigned int		base;
};

struct idtr test;
struct idt int_[256];

void irq_handler()
{

    for( ; ;)

}


#define MASTER          0x20
#define MASTERDATA      0x21
#define SLAVE           0xA0
#define SLAVEDATA       0xA1
#define EOI             0x20
#define ICW1_INIT    0x10               // required for PIC initialisation
#define ICW1_EDGE    0x08               // edge triggered IRQs
#define ICW1_SINGLE  0x02               // only MASTER (not cascaded)
#define	ICW1_ICW4    0x01               // there IS an ICW4 control word

#define ICW4_SFNM    0x10               // Special Fully Nested Mode
#define ICW4_BUFFER  0x08               // Buffered Mode
#define ICW4_MASTER  0x04               // this is the Master PIC
#define ICW4_AEOI    0x02               // Auto EOI
#define ICW4_8086    0x01               // 80/86 Mode
void remapPIC(int pic1, int pic2)
{
	unsigned char md,sd;

	md=in(MASTERDATA);                     // save state of MASTER DATA
	sd=in(SLAVEDATA);                      // save state of SLAVE DATA

	out(MASTER, EOI);                      // Send EOI | resets the chip

	out(MASTER, ICW1_INIT+ICW1_ICW4);      // ICW1 control word setup | just basic PIC stuff
	out(SLAVE, ICW1_INIT+ICW1_ICW4);       // see pic.h for more details about the values

	out(MASTERDATA, pic1);                 // ICW2 maps IRQs 0-7 to whatever kernel passes
	out(SLAVEDATA, pic2);                  // and same here except with IRQs 8-15

	out(MASTERDATA, 0x04);                 // ICW3
	out(SLAVEDATA, 0x02);

	out(MASTERDATA, ICW4_8086);            // ICW4 control word setup
	out(SLAVEDATA, ICW4_8086);

	out(MASTERDATA,md);                    // restore both MASTER DATA
	out(SLAVEDATA,sd);                     // restore SLAVE DATA
}

extern void irq0();

void initiateTimer()
{


    remapPIC(0x20, 0x28);

    out(0x21, 0xFE);
    out(0xA1, 0xFE);

    test.limit = sizeof (struct idt)*256 -1;
    test.base = (unsigned int) int_;



    unsigned int base = (unsigned int) &irq0;



    int e;

    for( e= 0; e < 256; e++)
    {
        int_[e].baseLo		=	base & 0xffff;


        int_[e].baseHi		=	(base >> 16) & 0xffff;

        int_[e].reserved    =	0;
        int_[e].flags	    =	0x8E ;

        int_[e].sel		    =	0x08;


    }

    __asm__("lidt [ bx ]" : : "b" (&test));

}


Am i mapping the irs correctly?, how about the GDT? is it correct? waht aout hte rings, i still dont have those very clear?
Are the IDT's correctly used? Is theproblem in the resulting adress of th efunciont to call?

TY :D
Last edited by yolda on Wed May 27, 2009 9:59 pm, edited 1 time in total.
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: Interrupt handling, GDT, IDT PIC problem

Post by Combuster »

Code: Select all

__asm__("lidt [ bx ]" : : "b" (&test));
16-bit code in a 32-bit OS?

Code: Select all

struct idtr {

   //! size of the interrupt descriptor table (idt)
   unsigned short      limit;

   //! base address of idt
   unsigned int      base;
};
beware of struct packing! (sizeof(idtr) == 8...)
and mingw for the c code.
*shudders* GCC Cross-Compiler
"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 ]
yolda
Posts: 13
Joined: Wed May 27, 2009 12:56 pm

Re: Interrupt handling, GDT, IDT PIC problem

Post by yolda »

Combuster wrote:

Code: Select all

__asm__("lidt [ bx ]" : : "b" (&test));
16-bit code in a 32-bit OS?

i corrected this allready :P ty, still same problem.

Code: Select all

struct idtr {

   //! size of the interrupt descriptor table (idt)
   unsigned short      limit;

   //! base address of idt
   unsigned int      base;
};
beware of struct packing! (sizeof(idtr) == 8...)

how can be sure its if the right size?

Whats the problem with my compiler? i am running my OS on vmware using an iso image.
and mingw for the c code.
*shudders* GCC Cross-Compiler
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: Interrupt handling, GDT, IDT PIC problem

Post by Troy Martin »

Code: Select all

_irq0:

loop:


   jmp loop
This looks quite odd, your irq is continuously doing an infinite loop...
Image
Image
Solar wrote:It keeps stunning me how friendly we - as a community - are towards people who start programming "their first OS" who don't even have a solid understanding of pointers, their compiler, or how a OS is structured.
I wish I could add more tex
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: Interrupt handling, GDT, IDT PIC problem

Post by NickJohnson »

Code: Select all

:
struct idtr {

   //! size of the interrupt descriptor table (idt)
   unsigned short      limit;

   //! base address of idt
   unsigned int      base;
};
beware of struct packing! (sizeof(idtr) == 8...)

how can be sure its if the right size?

Whats the problem with my compiler? i am running my OS on vmware using an iso image.
The compiler will try to optimize that structure by putting base before limit, which will not load correctly. Use this instead to force the same order:

Code: Select all

:
struct idtr {

   //! size of the interrupt descriptor table (idt)
   unsigned short      limit;

   //! base address of idt
   unsigned int      base;
} __attribute__ ((packed));
That should fix at least one problem. :)
yolda
Posts: 13
Joined: Wed May 27, 2009 12:56 pm

Re: Interrupt handling, GDT, IDT PIC problem

Post by yolda »

Troy Martin wrote:

Code: Select all

_irq0:

loop:


   jmp loop
This looks quite odd, your irq is continuously doing an infinite loop...
I put this here on pourpuse to see if the system hanged, but all it does is reset. it doesnt even get there.

My guess is that the problem is in how the system calculates the address where it should jump to call the IRQ. The segment in GDT is either wrong, or perhaps the ring?

Code: Select all

:
struct idtr {

   //! size of the interrupt descriptor table (idt)
   unsigned short      limit;

   //! base address of idt
   unsigned int      base;
} __attribute__ ((packed));
I tired this and my compiler says it will be ignored in a warning. What other compiler can i use besides MinGW? is there another attribute that does the same thing? or can i declare another kind of data structure?
User avatar
kop99
Member
Member
Posts: 120
Joined: Fri May 15, 2009 2:58 am

Re: Interrupt handling, GDT, IDT PIC problem

Post by kop99 »

I tired this and my compiler says it will be ignored in a warning. What other compiler can i use besides MinGW? is there another attribute that does the same thing? or can i declare another kind of data structure?
try following...

Code: Select all

#pragma pack(push, 1)

struct idtr {

   //! size of the interrupt descriptor table (idt)
   unsigned short      limit;

   //! base address of idt
   unsigned int      base;
}

#pragma pack(pop)
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: Interrupt handling, GDT, IDT PIC problem

Post by Troy Martin »

yolda wrote:I put this here on pourpuse to see if the system hanged, but all it does is reset. it doesnt even get there.
I'd like to point out that if interrupts aren't disabled in irq0, it could keep "nesting" an IRQ running from within and IRQ etc. etc. Other interrupts can keep going inside and you could have an IRQ0 inside an IRQ0 inside an IRQ3 inside an IRQ0 inside an IRQ1 inside an IRQ0 inside an IRQ0 inside an IRQ1 inside an IRQ0...
Image
Image
Solar wrote:It keeps stunning me how friendly we - as a community - are towards people who start programming "their first OS" who don't even have a solid understanding of pointers, their compiler, or how a OS is structured.
I wish I could add more tex
yolda
Posts: 13
Joined: Wed May 27, 2009 12:56 pm

Re: Interrupt handling, GDT, IDT PIC problem

Post by yolda »

kop99 wrote:
I tired this and my compiler says it will be ignored in a warning. What other compiler can i use besides MinGW? is there another attribute that does the same thing? or can i declare another kind of data structure?
try following...

Code: Select all

#pragma pack(push, 1)

struct idtr {

   //! size of the interrupt descriptor table (idt)
   unsigned short      limit;

   //! base address of idt
   unsigned int      base;
}

#pragma pack(pop)
great! ty it worked! problem i snow solved! i tried declaring my own set of bytes and allocate mem manually using pointers and taking little endian into account, didnt work tho, but this did!
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: Interrupt handling, GDT, IDT PIC problem

Post by Troy Martin »

A good thing would to understand what the fix is. Do you know what it does? What are the pragma pack things and what do the two lines do?
Image
Image
Solar wrote:It keeps stunning me how friendly we - as a community - are towards people who start programming "their first OS" who don't even have a solid understanding of pointers, their compiler, or how a OS is structured.
I wish I could add more tex
User avatar
kop99
Member
Member
Posts: 120
Joined: Fri May 15, 2009 2:58 am

Re: Interrupt handling, GDT, IDT PIC problem

Post by kop99 »

i'm pleasure it works, yolda...
Troy Martin, refer that url...
http://msdn.microsoft.com/en-us/library ... S.80).aspx
whowhatwhere
Member
Member
Posts: 199
Joined: Sat Jun 28, 2008 6:44 pm

Re: Interrupt handling, GDT, IDT PIC problem

Post by whowhatwhere »

Troy Martin wrote:A good thing would to understand what the fix is. Do you know what it does? What are the pragma pack things and what do the two lines do?
From: Source
When #pragma first came into usage, the people behind GCC weren't able to put in support for it right away, so instead they quickly hacked in a very odd little quick-fix.
With these certain earlier versions of gcc, if you compiled a file containing a #pragma, GCC would attempt each of the following in turn:

1. Attempt to launch a game of nethack.
2. Attempt to launch a game of rogue.
3. Attempt to launch a game of Towers of Hanoi via emacs.
4. Print the message "You are in a maze of twisty compiler features, all different."

I don't think the GCC people liked the idea of #pragma very much.
Just my $0.02
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: Interrupt handling, GDT, IDT PIC problem [SOLVED]

Post by Combuster »

Have you even read about GCC Cross-Compiler - especially the why?
"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
quanganht
Member
Member
Posts: 301
Joined: Fri May 16, 2008 7:13 pm
Location: Hanoi, Vietnam

Re: Interrupt handling, GDT, IDT PIC problem [SOLVED]

Post by quanganht »

Just a question: Does it really necessary to init GDT *BEFORE* IDT?
"Programmers are tools for converting caffeine into code."
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: Interrupt handling, GDT, IDT PIC problem [SOLVED]

Post by Combuster »

short answer: yes.

long answer:
The IDT points to entries in the GDT. If you have an IDT without GDT, then any accesses to the idt will break since the referenced part in the GDT is invalid. Hence it makes more sense to have a GDT and be able to rely on that while you're making the IDT. The CPU will nevertheless accept the addresses of the IDT and GDT in either order, so if you initialize one directly after the other it won't make much of a difference.
"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 ]
Post Reply