Double fault on (presumed) PIC interrupt (IRQs are remapped)

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
schuirl
Posts: 6
Joined: Sat May 11, 2013 4:19 pm

Double fault on (presumed) PIC interrupt (IRQs are remapped)

Post by schuirl »

Hello,

I'm sitting on this one since over a week now and decided to bother you with this.
I have set up my GDT. I have set up an IDT. I can use software interrupts, thats no problem, so I presume its not because something went wrong with the segment. Some time after I activate the interrupts using sti I get a double fault (following by GPFs if I don't halt the kernel). The error code seems to change occasionally.

As mentioned in the title, I did remap the IRQ. I tried this with the code from several tutorials to ensure that it isn't a fault of my remapping code (I did it with far more macros but that shouldn't be that bad). The ISR machine code handlers wich invoke my C handlers are copied from tutorials (and I won't write own ones while this double fault occurs - after that you can bet on it). (By the way: on my research on the PIC I found out about this auto-end-of-interrupt bit. Why does no tutorial just set it and leave out the sending of end of interrupt in the IRQ handler? Where's the disadvantage?)

Here's the code of the IDT installation function:

Code: Select all

tidtPtr.limit = (sizeof(idtEntry) * IDT_ENTRIES)-1;
tidtPtr.base  = &idt;
	
memset((void *)idt, 0, sizeof(idtEntry)*IDT_ENTRIES);
	
//set gates for all exceptions
idtSetGate(0 , (uint32_t)isr0 , CALC_SEL(1), I_PRESENT | I_DPL(0) | I_INT_GATE);
.
.
.
idtSetGate(47, (uint32_t)irq15, CALC_SEL(1), I_PRESENT | I_DPL(0) | I_INT_GATE);
	
//flush :)
cli();
remapIrqs();
lidt(tidtPtr);
And idtSetGate:

Code: Select all

static void idtSetGate(const uint8_t index, const uint32_t entry, const uint16_t selector, const uint16_t attr)
{
	idt[index].zero = 0x00;
	idt[index].attr = attr;
	idt[index].selector 	= selector;
	idt[index].entryLow 	= 0xFFFF & entry;
	idt[index].entryHigh	= (entry>>16) & 0xFFFF;
}
(I don't use a cross compiler YET. I'm working on this.)

I have no clue where the bug can be. (I had a working version, but it was unstructured and evil, partly copied from tutorials.)
If I can post anything else (code, information...) just let me know.

Greetings,

Lasse
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Double fault on (presumed) PIC interrupt (IRQs are remap

Post by xenos »

Are you running this on real hardware or a simulator (Bochs, QEMU etc.)? If this happens in Bochs, it would be helpful to see the logfile, which should tell you more about the reason for the double fault.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
schuirl
Posts: 6
Joined: Sat May 11, 2013 4:19 pm

Re: Double fault on (presumed) PIC interrupt (IRQs are remap

Post by schuirl »

Hello,

Thanks for the quick reply.

I work with qemu. Here is the log entry when I specify that -d int (interrupt logging). I removed everything that is logged if I don't call sti, ergo the interrupt does not occur.

0: v=08 e=0000 i=0 cpl=0 IP=0008:0010158c pc=0010158c SP=0010:00104ff0 EAX=00000000
EAX=00000000 EBX=00000000 ECX=0000002f EDX=00106000
ESI=00000000 EDI=001051a0 EBP=001051b8 ESP=00104ff0
EIP=0010158c EFL=00000202 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 001059f8 00000017
IDT= 00105200 000007f7
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000001 CCD=00000000 CCO=LOGICB
EFER=0000000000000000

The instruction pointer points somewhere in my kernel code. (Wich is loaded at 1MB and 6 pages big.) If I retry the adress changes!
I'm setting up bochs right now to see if its log gets more information.

Lasse
User avatar
Jezze
Member
Member
Posts: 395
Joined: Thu Jul 26, 2007 1:53 am
Libera.chat IRC: jfu
Contact:

Re: Double fault on (presumed) PIC interrupt (IRQs are remap

Post by Jezze »

Hi,

I would mask all the IRQs first and see if that works (outb 0x21, 0xff and outb 0xa1, 0xff). Then I would unmask them one by one until I find what IRQ is causing trouble starting with the timer which is most likely the problematic one. Since you are getting a GPF it could mean that there is no entry in the IDT for that interrupt vector so I would make sure there is by writing some code inside the intended interrupt stub function (probably for vector 0x20 if you remap according to tutorials), something that just prints to screen, just to make sure it works.
Fudge - Simplicity, clarity and speed.
http://github.com/Jezze/fudge/
schuirl
Posts: 6
Joined: Sat May 11, 2013 4:19 pm

Re: Double fault on (presumed) PIC interrupt (IRQs are remap

Post by schuirl »

If I mask the IRQs the double fault does occur.
I just tested calling the software interrupts 0x20 and 0x08. They both seem to cause a double fault while I can call e.g. software interrupt 0x03 or 0x13. I will look at the machine code interrupt handler and the idt installer again. Hope I find something.

Thanks for helping with the diagnosis!

--- Edited ---
This is quite interesting. The double fault and GPF seems to be independent from my software interrupt calls. The fault occurs accidentally and independent from my software interrupts.

Since I masked the PIC interrupts, it is not the PIC. And I think the interrupt routines are right too since I can call any interrupt and IRQ I want and it doesn't seem to influence the fault in any way.

So I assume that its generated by a piece of hardware I didn't initialize yet. (Since I have not really nondeterministic code in the kernel yet. Basically just install the GDT, install the IDT, print to screen and hlt...)
Post Reply