Page 1 of 1

IDT

Posted: Mon Jan 09, 2012 7:04 pm
by sds2017
Hi,
I have had problems with the idt (software interrupts specifically) while using c for a while. I know assembly and have built a handler in assembly and when I call a interrupt(s) in assembly from a assembly kernel it does what I want it to do but, when I use most of the same code for my C kernel it doesn't work (just tripple faults). So, after spending weeks trying to fix it I went to the James Molloy Kernel Development tutorial and looked at how they implemented the idt. I then coded a similer version of it for my os just to see if it worked and it didn't. If you answer this question here is some more info:
I used nasm not another assembler or inline asm
I am coding the kernel in c (compilier is gcc)

For those of you who say "The OSDev.org wiki - Got a question? Search this first" to answer your question yes I have looked at it and I do understand what the tutorials are saying. I would appreciate it if you would answer the question of what you think the problem with implimenting the idt in asm and calling a interrupt in c and how to fix it.

Thank you,
Jackson

Re: IDT

Posted: Mon Jan 09, 2012 7:22 pm
by gerryg400
I would appreciate it if you would answer the question of what you think the problem with implimenting the idt in asm and calling a interrupt in c and how to fix it.
There's nothing wrong with what you're doing. You have a bug. I would recommend some code review.

Re: IDT

Posted: Mon Jan 09, 2012 7:23 pm
by sds2017
Well I have tested the code in my assembly kernel and it worked flawlessly.

Re: IDT

Posted: Mon Jan 09, 2012 7:42 pm
by gerryg400
sds2017 wrote:Well I have tested the code in my assembly kernel and it worked flawlessly.
I don't think that's important with respect to your problem with your C kernel.

My feeling is that you haven't supplied enough information to guarantee that others can help you. I recommended code-review. One method of code review is to post your code.

Re: IDT

Posted: Mon Jan 09, 2012 7:57 pm
by sds2017
Okay here's the code it's lengthy but pretty simple I know that I can make macro's but the sake of testing I did this:

Code: Select all

%define base_addr 0x100000
msg db "Exeption Handler: an unhandled interrupt has occured...", 0xA, 0

;Hardware Interrupts
EnableIrq:
	;ICW1
	mov al, 0x11 ;00010001 
	out 0x20, al
	out 0xA0, al

	;ICW2
	mov al, 0x20
	out 0x21, al ;(0x21 & 0xA1)port for all the other ICW's, 0x20 (32) because there are 31 hardware ints
	mov al, 0x28
	out 0xA1, al ;0x28(40) because there are 8 irqs per PIC is 

	;ICW3(Only allows keyboard interrupts)
	mov al, 0x4	
	out 0x21, al  ;00000100
	mov al, 0x2	
	out 0xA1, al  ;010

	;ICW4		
	mov al, 0x1
	out 0x21, al  ;000001
	out 0xA1, al  ;000001
	
	mov al, 0
	out 0x21, al
	out 0xA1, al
	ret



;Software Interrupts
isr0:
	cli
	push byte 0
	push byte 0
	jmp handler

isr1:
	cli
	push byte 0
	push byte 1
	jmp handler

isr2:
	cli
	push byte 0
	push byte 2
	jmp handler

isr3:
	cli
	push byte 0
	push byte 3
	jmp handler

isr4:
	cli
	push byte 0
	push byte 4
	jmp handler

isr5:
	cli
	push byte 0
	push byte 5
	jmp handler

isr6:
	cli
	push byte 0
	push byte 6
	jmp handler

isr7:
	cli
	push byte 0
	push byte 7
	jmp handler

isr8:
	cli
	push byte 8
	jmp handler

isr9:
	cli
	push byte 0
	push byte 9
	jmp handler

isr10:
	cli
	push byte 10
	jmp handler

isr11:
	cli
	push byte 11
	jmp handler

isr12:
	cli
	push byte 12
	jmp handler

isr13:
	cli
	push byte 13
	jmp handler

isr14:
	cli
	push byte 14
	jmp handler

isr15:
	cli
	push byte 0
	push byte 15
	jmp handler

isr16:
	cli
	push byte 0
	push byte 16
	jmp handler

isr17:
	cli
	push byte 0
	push byte 17
	jmp handler

isr18:
	cli
	push byte 0
	push byte 18
	jmp handler

isr19:
	cli
	push byte 0
	push byte 19
	jmp handler

isr20:
	cli
	push byte 0
	push byte 20
	jmp handler

isr21:
	cli
	push byte 0
	push byte 21
	jmp handler

isr22:
	cli
	push byte 0
	push byte 22
	jmp handler

isr23:
	cli
	push byte 0
	push byte 23
	jmp handler

isr24:
	cli
	push byte 0
	push byte 24
	jmp handler

isr25:
	cli
	push byte 0
	push byte 25
	jmp handler

isr26:
	cli
	push byte 0
	push byte 26
	jmp handler

isr27:
	cli
	push byte 0
	push byte 27
	jmp handler

isr28:
	cli
	push byte 0
	push byte 28
	jmp handler

isr29:
	cli
	push byte 0
	push byte 29
	jmp handler

isr30:
	cli
	push byte 0
	push byte 30
	jmp handler

isr31:
	cli
	push byte 0
	push byte 31
	jmp handler
irq0:
	cli
	push byte 0
	push byte 32
	jmp irq_handler

irq1:
	cli
	push byte 0
	push byte 33
	jmp irq_handler


irq2:
	cli
	push byte 0
	push byte 34
	jmp irq_handler

irq3:
	cli
	push byte 0
	push byte 35
	jmp irq_handler

irq4:
	cli
	push byte 0
	push byte 36
	jmp irq_handler

irq5:
	cli
	push byte 0
	push byte 37
	jmp irq_handler

irq6:
	cli
	push byte 0
	push byte 38
	jmp irq_handler

irq7:
	cli
	push byte 0
	push byte 39
	jmp irq_handler

irq8:
	cli
	push byte 0
	push byte 40
	jmp irq_handler

irq9:
	cli
	push byte 0
	push byte 41
	jmp irq_handler

irq10:
	cli
	push byte 0
	push byte 42
	jmp irq_handler

irq11:
	cli
	push byte 0
	push byte 43
	jmp irq_handler

irq12:
	cli
	push byte 0
	push byte 44
	jmp irq_handler

irq13:
	cli
	push byte 0
	push byte 45
	jmp irq_handler

irq14:
	cli
	push byte 0
	push byte 46
	jmp irq_handler

irq15:
	cli
	push byte 0
	push byte 47
	jmp irq_handler


irq_handler:
	pusha
	mov ax, ds
	push eax
	mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax

	mov ebx, msg
	call Print32

	mov al, 0x20
	out 0xA0, al
	out 0x20, al

	pop ebx
	mov ds, bx
	mov es, bx
	mov fs, bx
	mov gs, bx
	popa
	add esp, 8
	sti
	iret

handler:	
	pusha
	mov ax, ds
	push eax
	mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax

	mov ebx, msg
	call Print32

	pop ebx
	mov ds, bx
	mov es, bx
	mov fs, bx
	mov gs, bx
	popa
	add esp, 8
	sti
	iret

[GLOBAL InstallIDT]
InstallIDT:
	cli                  
	pusha			
	lidt 	[load]        		               
	popa                 	
	ret	                



_CurY db 0
_CurX db 0

%define		VIDMEM	0xB8000			
%define		COLS	80			
%define		LINES	25
%define		CHAR_ATTRIB 0x02


PrintChar32:

	pusha				
	mov	edi, VIDMEM		

	xor	eax, eax		

	mov	ecx, COLS*2		
	mov	al, byte [_CurY]	
	mul	ecx			
	push	eax			

	mov	al, byte [_CurX]	
	mov	cl, 2
	mul	cl
	pop	ecx			
	add	eax, ecx

	xor	ecx, ecx
	add	edi, eax		

	cmp	bl, 0x0A	
	je	.Row	

	cmp bl, 0x08
	je .Backspace

	mov	dl, bl			
	mov	dh, CHAR_ATTRIB		
	mov	word [edi], dx		

	inc	byte [_CurX]			
	jmp	.done			

.Backspace:
	cmp byte [_CurX], 2
	je .done
	dec byte [_CurX]
	mov bl, " "
	call PrintChar32
	dec byte [_CurX]	
	jmp .done

.Row:
	mov	byte [_CurX], 0		
	inc	byte [_CurY]		
.done:
	popa				
	ret

Print32:
	pusha				
	push	ebx			
	pop	edi

.loop:
	mov	bl, byte [edi]		
	cmp	bl, 0			
	je	.done

	call	PrintChar32			

	inc	edi			
	jmp	.loop

.done:
	mov	bh, byte [_CurY]	
	mov	bl, byte [_CurX]
	call	MovCur			

	popa				
	ret

MovCur:

	pusha		

	xor	eax, eax
	mov	ecx, COLS
	mov	al, bh			
	mul	ecx			
	add	al, bl			
	mov	ebx, eax

	mov	al, 0x0f
	mov	dx, 0x03D4
	out	dx, al

	mov	al, bl
	mov	dx, 0x03D5
	out	dx, al			

	xor	eax, eax

	mov	al, 0x0e
	mov	dx, 0x03D4
	out	dx, al

	mov	al, bh
	mov	dx, 0x03D5
	out	dx, al			

	popa
	ret

GotoXY:
	pusha
	mov	[_CurX], al		
	mov	[_CurY], ah
	popa
	ret

idt_data:
	dw (base_addr + isr0 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr1 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr2 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr3 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr4 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr5 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr6 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr7 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr8 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr9 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr10 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr11 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr12 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr13 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr14 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr15 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr16 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr17 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr18 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr19 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr20 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr21 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr22 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr23 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr24 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr25 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr26 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr27 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr28 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr29 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr30 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	dw (base_addr + isr31 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + handler - $$) >> 16

	;irq0
	dw (base_addr + irq0 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + irq0 - $$) >> 16

	;irq1
	dw (base_addr + irq1 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + irq1 - $$) >> 16

	;irq2
	dw (base_addr + irq2 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + irq2 - $$) >> 16

	;irq3
	dw (base_addr + irq3 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + irq3 - $$) >> 16

	;irq4
	dw (base_addr + irq4 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + irq4 - $$) >> 16

	;irq5
	dw (base_addr + irq5 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + irq5 - $$) >> 16

	;irq6
	dw (base_addr + irq6 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + irq6 - $$) >> 16

	;irq7
	dw (base_addr + irq7 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + irq7 - $$) >> 16

	;irq8
	dw (base_addr + irq8 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + irq8 - $$) >> 16

	;irq9
	dw (base_addr + irq9 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + irq9 - $$) >> 16

	;irq10
	dw (base_addr + irq10 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + irq10 - $$) >> 16

	;irq11
	dw (base_addr + irq11 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + irq11 - $$) >> 16

	;irq12
	dw (base_addr + irq12 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + irq12 - $$) >> 16

	;irq13
	dw (base_addr + irq13 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + irq13 - $$) >> 16

	;irq14
	dw (base_addr + irq14 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + irq14 - $$) >> 16

	;irq15
	dw (base_addr + irq15 - $$) & 0xFFFF
	dw 0x8
	db 0x0
	db 0x8E
	dw (base_addr + irq15 - $$) >> 16

 

end_of_idt:
load: 
	dw end_of_idt - idt_data - 1 	
	dd idt_data
I understand your point of the code but if you can explain to me why it doesn't work in C then your right. The only reason I say it has something to do with C is because it works in assembly. the way I impliment this code is by this in C:

Code: Select all

extern void InstallIDT();
and in the hal init function

Code: Select all

void init_hal()
{
        InstallGDT
        InstallIDT
}

Re: IDT

Posted: Mon Jan 09, 2012 10:12 pm
by evoex
I haven't actually read any of your code, but you do realize the code you posted does nothing at all:

Code: Select all

void init_hal()
{
        InstallGDT
        InstallIDT
}
This doesn't call any functions and, really, doesn't do anything. You should really compile with all warnings enabled and it should warn about this. Either that or you didn't copy your code properly, in which case there's a reason to read the rest of your code ;-).

Re: IDT

Posted: Tue Jan 10, 2012 4:21 pm
by sds2017
actually i did put InstallIDT(); and the warnings are enabled I just accidentally wrote that because I had been working on other functions in the Hal function so I just wrote that part in the forum Sorry about that... Here's what it actually looked like:

#include <HAL.h>
#include <console.h>

extern void InstallIDT();

void init_hal()
{
InstallGDT();
InstallIDT();
}

I promise you I've looked at this code since Thanksgiving.

Re: IDT

Posted: Tue Jan 10, 2012 6:32 pm
by evoex
So when does it actually triple fault? Is that whenever an interrupt is fired? Try debugging until the fault happens.
Are you sure the idt_data address is actually its physical address, and not virtual?

Re: IDT

Posted: Tue Jan 10, 2012 6:50 pm
by sds2017
It tripple faults when a interrupt is occurs. It works fine if you don't call a interrupt. Also idt_data is just the start to the end of the code of the idt (It's the function after GotoXY). As I said in earlier posts it works when I call it from assembly but when I declare a external function in c and call it their it doesn't.

Re: IDT

Posted: Tue Jan 10, 2012 7:01 pm
by evoex
sds2017 wrote:It tripple faults when a interrupt is occurs. It works fine if you don't call a interrupt. Also idt_data is just the start to the end of the code of the idt (It's the function after GotoXY). As I said in earlier posts it works when I call it from assembly but when I declare a external function in c and call it their it doesn't.
I understand where the idt_data is, but is it a physical address? E.g. are you using "org 0" for this source file? Because lidt expects the address to be physical, not virtual.

If not, put a magic breakpoint before the interrupt call, then have a look at the gdt and idt to see if they are what you expect them to be.

Re: IDT

Posted: Tue Jan 10, 2012 7:43 pm
by sds2017
No I didn't put org because the assembler wouldn't let me but, still how could the idt work in an assembly kernel; my assembly kernel doesn't use org in it anywhere. So logically yes, it does use the physical address. My asm kernel uses my custom bootloader and my c uses grub, in my c kernel I tried to load the idt in the entry file but grub didn't like that so it didn't boot saying that you cannot do that.

Re: IDT

Posted: Wed Jan 11, 2012 3:13 am
by harvey
berkus wrote:2. debug till you bleed
I like this one! I just spent a week, day and night finding a bug related with interrupts.

Re: IDT

Posted: Wed Jan 11, 2012 3:18 am
by harvey
sds2017 wrote:Hi,
I have had problems with the idt (software interrupts specifically) while using c for a while. I know assembly and have built a handler in assembly and when I call a interrupt(s) in assembly from a assembly kernel it does what I want it to do but, when I use most of the same code for my C kernel it doesn't work (just tripple faults). So, after spending weeks trying to fix it I went to the James Molloy Kernel Development tutorial and looked at how they implemented the idt. I then coded a similer version of it for my os just to see if it worked and it didn't. If you answer this question here is some more info:
I used nasm not another assembler or inline asm
I am coding the kernel in c (compilier is gcc)

For those of you who say "The OSDev.org wiki - Got a question? Search this first" to answer your question yes I have looked at it and I do understand what the tutorials are saying. I would appreciate it if you would answer the question of what you think the problem with implimenting the idt in asm and calling a interrupt in c and how to fix it.

Thank you,
Jackson

1, Make sure you're familiar with interaction between assembly code and c code
2, Check every byte and every bit within IDT. Trust me.
3, Be careful when you enable or disable local interrupts using sti or cli.

Re: IDT

Posted: Wed Jan 11, 2012 6:36 pm
by sds2017
Sorry about that I just realized that code only works on a flat binary which is what my asm kernel was compiled to while my c kernel was compiled to elf. I've recoded the thing in C and I've got it to work. Thank you for your help.