Page 1 of 1

Receiving GPF after almost any PIC Interrupt :(

Posted: Sat Feb 03, 2007 7:40 am
by HerrGanchev
Hello guys!

Sorry if such topic already exists.

I am trying to write a simple kernel, and I am trying to set up some sort of a floppy driver. Unfortunatelly I have a problem with the interrupts, managed by the PIC - when almost all of them are called (except the keyboard and timer interrupt), a general protection fault is raised. I think I have done everything needed to set up the interrupt system:

* create the IDT
* load it with LIDT
* remap the PIC - 0x20+, 0x28+ interrupt vectors
* STI

Also, at the end of every hardware interrupt, I send an EOI as necessary.

I am using Bochs 2.3 for testing.

Thanks.

Posted: Sat Feb 03, 2007 8:54 am
by Otter
Did you register handlers for all irqs ( 0x20 to 0x2F ) ? If not, have you masked the others ? I dunno if it's important for you but in your list you did mention that you set the pic masks.

Maybe you could give some code ...

Posted: Sat Feb 03, 2007 9:46 am
by HerrGanchev
No, I did not mask the interrupts - actually I did once but this didn't change anything, except that the masked ones don't trigger

I remapped the PIC so that IRQ0 becomes INT 32, etc.

I have the following code on init to make sure for every interrupt i have a handler

Code: Select all

	for (i = 0; i <= 48; i++)
		InterruptSet((BYTE)i, EmptyInterrupt, 8, 0x8E00);

	InterruptSet(13, GeneralProtectionInterrupt, 8, 0x8E00);
	InterruptSet(14, PageFaultInterrupt, 8, 0x8E00);
	InterruptSet(32, TimerInterrupt, 8, 0x8E00);
	InterruptSet(33, KeyboardInterrupt, 8, 0x8E00);

Posted: Sat Feb 03, 2007 12:48 pm
by Otter
What happens if you call one of these interrupts manually ? Do you get a gpf too ? Then, your EmptyInterrupt seems to produce it.

Have you isolated the instruction which is responsible for the exception ? Dunno how complex your exception handler is but it should tell you the CS/EIP of the instruction which raised the gpf. If you have the EIP you should be able to locate the responsible position. If it is in your handler for EmptyInterrupt, maybe you could give the code of it

Posted: Sat Feb 03, 2007 2:56 pm
by HerrGanchev
If called manually as a software interrupt, again a GPF occurs, the EIP pointer is exactly the "int 38" instruction
When I tested the floppy controller, the eip pointed at the outputb() function that allows the floppy controller interrupt.
Between the manual and the normal interrupt invoke the only difference in the stack is the EXT bit of the error code

here is the source in the boot sector that remaps the pic (I think I do it in real mode, is this a problem?):

Code: Select all

	mov	al,	0x11
	out	0x20, al
	
	call simpleLoop
	
	mov	al, 0x11
	out	0xA0, al
	
	call simpleLoop
	
	mov	al, 0x20
	out	0x21, al
	
	call simpleLoop
	
	mov	al, 0x28
	out	0xA1, al
	
	call simpleLoop
	
	mov	al, 0x04
	out	0x21, al
	
	call simpleLoop
	
	mov	al, 0x02
	out	0xA1, al
	
	call simpleLoop
	
	mov	al, 0x01
	out	0x21, al
	
	call simpleLoop
	
	mov	al, 0x01
	out	0xA1, al
	
	call simpleLoop
	
	sti
here are the two macros for the start and end of each interrupt handler

Code: Select all

#define START_INTERRUPT() \
	__asm__ __volatile__( \
		"cli\n" \
		"pusha\n" \
		"push %gs\n" \
		"push %fs\n" \
		"push %es\n" \
		"push %ds\n"); \
	BYTE byEmptyInterruptVariable

#define END_INTERRUPT()	\
	__asm__ __volatile__( \
		"movb $0x20, %al\n" \
		"outb %al, $0x20\n" \
		"pop %ds\n" \
		"pop %es\n" \
		"pop %fs\n" \
		"pop %gs\n" \
		"popa\n" \
		"sti\n" \
		"leave\n" \
		"iret\n" \
	)

Posted: Sat Feb 03, 2007 3:21 pm
by os64dev
you don't have a c function like the following code snippit do you ?

Code: Select all

void interrupt(void) {
    START_INTERRUPT();
    .....
    END_INTERRUPT() 
}
because that would be bad... see the FAQ. You should make the interrupt handlers in assembler, either nasm or as what ever you prefer, and call the c function from there like so:

Code: Select all


// file: isr.s
.extern   isr_c_part

isr_asm_part:
    pusha
    call    isr_c_part
    popa
    iret

//- file: isr.c
void isr_c_part(void) {
   ....
}

//- register interrupt.
InterruptSet(14, isr_asm_part, 8, 0x8E00); 
hopes this helps a bit.

http://www.osdev.org/osfaq2/index.php/I ... ceRoutines provides more details.

regards

Posted: Sun Feb 04, 2007 12:42 am
by HerrGanchev
I know, I read the article, yet I used the "BLACK MAGIC" technique :D
But I don't believe this is the problem since the execution doesn't reach the interrupt handler at all ;)

Anyway, I'll try using asm routines ...

Posted: Sun Feb 04, 2007 6:05 am
by HerrGanchev

Code: Select all

_irqEmpty:
pusha
call _EmptyInterrupt
mov al, 0x20
out 0x20, al
popa
iret
ok, so this is the new handler writen in assembler. Again, everything beyond IRQ1 crashes with GPF

Could it be a problem that I remap the PIC in real mode?

Posted: Sun Feb 04, 2007 7:52 am
by Otter
Could it be a problem that I remap the PIC in real mode?
No, that should be no problem.

I think the PIC is not the problem because you say that the gpf occurs even when you call the int manually, so I think the problem is in your idt.

Could you give the code for your idt ( all of it, including the LIDT ) ?

Posted: Sun Feb 04, 2007 8:41 am
by HerrGanchev
I was able to fix the problem, since you remind me to open the idt source :D

so the problem was that I uploaded a premade IDT directly from the second sector and the size of the IDT was up to the keyboard interrupt selector :D, now I set it to 1023 words und alles arbeitet problemloss :D

Thanks, Otter! Thanks os64dev! Sorry for taking your time :)