Receiving GPF after almost any PIC Interrupt :(

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
User avatar
HerrGanchev
Posts: 6
Joined: Sat Feb 03, 2007 7:33 am
Location: Sofia, Bulgaria

Receiving GPF after almost any PIC Interrupt :(

Post 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.
Otter
Member
Member
Posts: 75
Joined: Sun Dec 31, 2006 11:56 am
Location: Germany

Post 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 ...
User avatar
HerrGanchev
Posts: 6
Joined: Sat Feb 03, 2007 7:33 am
Location: Sofia, Bulgaria

Post 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);
Otter
Member
Member
Posts: 75
Joined: Sun Dec 31, 2006 11:56 am
Location: Germany

Post 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
User avatar
HerrGanchev
Posts: 6
Joined: Sat Feb 03, 2007 7:33 am
Location: Sofia, Bulgaria

Post 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" \
	)
User avatar
os64dev
Member
Member
Posts: 553
Joined: Sat Jan 27, 2007 3:21 pm
Location: Best, Netherlands

Post 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
Author of COBOS
User avatar
HerrGanchev
Posts: 6
Joined: Sat Feb 03, 2007 7:33 am
Location: Sofia, Bulgaria

Post 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 ...
User avatar
HerrGanchev
Posts: 6
Joined: Sat Feb 03, 2007 7:33 am
Location: Sofia, Bulgaria

Post 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?
Otter
Member
Member
Posts: 75
Joined: Sun Dec 31, 2006 11:56 am
Location: Germany

Post 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 ) ?
User avatar
HerrGanchev
Posts: 6
Joined: Sat Feb 03, 2007 7:33 am
Location: Sofia, Bulgaria

Post 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 :)
Post Reply