[SOLVED] Weird PIT/PIC interrupt behaivor

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
HugeCode
Member
Member
Posts: 112
Joined: Mon Dec 17, 2012 9:12 am

[SOLVED] Weird PIT/PIC interrupt behaivor

Post by HugeCode »

Hi all. I have very interisting and weird problem.
I've mapped my IRQs to 0x20 using PIC. Then I set up an interrupt for IRQ(0) timer and also set up counter0 of PIT (+pit command word). When I run my OS, messages before and after interrupt setting are printed, but there is no IRQ0 handler message.
Because of this I decided to test if my IDT is correct by causing division by zero error. Division by zero exception works. Then I tried to print ISR and IRR of pit. In ISR output I can see that IRQ0 is acknowledged but it hasn't received EOI. Therefore I tried to debug handler, but I can see no handler call when debugging. I also tried to call interrupt manually (int 0x20) and it works. It works until it comes to iret instruction - when iret is executed, VM jumps to 0xfffffff0 (reboots?). And here the problem probably is. I found that SP(before_call) - SP(in_handler) = 4. Shouldn't it be 8 or 10 bytes? How can EFLAGS and EIP fit in four bytes?

So questions I have: is it only problem of manual interrupt (using int), or it's problem of my handler (it has Interrupt Trap Gate 32(0xE) flag set)?
Does anybody have any idea why the timer sets IRQ, but my interrupt is not called?
I'm posting here part of my PIT code:

Code: Select all

void pit_default_handler();

unsigned long long int _default_pit_ticks = 0;
void pit_init() {
	idt_register(IRQ0, (void*)&pit_default_handler, INTFLAG_MINRING_0+INTFLAG_TYPE_INTGATE32);
	pit_setcounter(0, 1000, PIT_MODE_RATEGEN+PIT_BINARY);
}
void pit_setcounter(unsigned char counter, unsigned int hzFreq, unsigned char flags) {
	unsigned short port = 0;

	if(counter > 2)
		return;

	hzFreq = 1193181 / hzFreq;
	if(counter==0)
		port = PIT_REG_COUNT0;
	else if(counter==1)
		port = PIT_REG_COUNT1;
	else port = PIT_REG_COUNT2;

	//writing OCW to 0x43
	outb(PIT_REG_CONTROL, flags | (counter << 6) | PIT_LOAD_LSBMSB);

	//writing COUNT to port
	outb(port, (unsigned char)hzFreq);
	outb(port, (unsigned char)(hzFreq >> 8));
}
void __declspec(naked) pit_default_handler() {
	cli();

	_default_pit_ticks++;
	if(_default_pit_ticks == 1000) {
		println("Second...");
		_default_pit_ticks = 0;
	}

	sti();
	hw_eoi(0);
	iret();
}
PS: I have also tested value of _default_pit_ticks, it's zero when performing manual call.
Last edited by HugeCode on Tue Apr 16, 2013 9:50 am, edited 1 time in total.
HugeCode
Member
Member
Posts: 112
Joined: Mon Dec 17, 2012 9:12 am

Re: Weird PIT/PIC interrupt behaivor

Post by HugeCode »

Any ideas?
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: Weird PIT/PIC interrupt behaivor

Post by Combuster »

Read the FAQ, use bochs, and keep debugging?

Oh and, never ever use naked functions.
"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 ]
HugeCode
Member
Member
Posts: 112
Joined: Mon Dec 17, 2012 9:12 am

Re: Weird PIT/PIC interrupt behaivor

Post by HugeCode »

I finally solved the problem. There were two problems and first one was hiding the second. I've set up the exceptions. Then I found out that iret instruction was causing GPF, but not because stack was corrupted. It was in iret instruction. Visual Studio compiler takes it as 16bit so it loads segment:offset instead of loading selector:address from GDT. I had to use iretd.
The second problem was more interesting. I could see ISR with IRQ0 set, so processor knew that there's some interrupt which has to be called. I tried to send EOI to PIC, but it also didn't work. Then I found out that in my bootloader, interrupts are cleared before jumping to C code. So there wasn't error in C which I was checking and debugging several times. So "sti" solved the problem.
User avatar
Kazinsal
Member
Member
Posts: 559
Joined: Wed Jul 13, 2011 7:38 pm
Libera.chat IRC: Kazinsal
Location: Vancouver
Contact:

Re: Weird PIT/PIC interrupt behaivor

Post by Kazinsal »

HugeCode wrote:Visual Studio compiler takes it as 16bit so it loads segment:offset instead of loading selector:address from GDT. I had to use iretd.
Odd. I use Visual Studio 2010 and don't have that issue. What version are you using?

EDIT: Actually, this issue doesn't make sense. iretd and iret are the same opcode in both modes.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Weird PIT/PIC interrupt behaivor

Post by Owen »

Blacklight wrote:EDIT: Actually, this issue doesn't make sense. iretd and iret are the same opcode in both modes.
Your x86-fu is weak...

iret word is CF in real mode/16-bit protected mode and 66 CF in 32-bit protected mode
iret dword is 66 CF in real mode/16-bit protected mode and 66 in 32-bit protected mode
HugeCode
Member
Member
Posts: 112
Joined: Mon Dec 17, 2012 9:12 am

Re: Weird PIT/PIC interrupt behaivor

Post by HugeCode »

I have Visual Studio 2010. BTW why shouldn't I use naked functions?
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: Weird PIT/PIC interrupt behaivor

Post by Combuster »

HugeCode wrote:I have Visual Studio 2010. BTW why shouldn't I use naked functions?
Because
a) You apparently have no idea how they work.
b) When you do know how they work you can't possibly construct an implementation that works forever.

That interrupt handler is broken like hell. Rewrite it in assembly, and use a sane reference on what it should actually be doing.
"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
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Weird PIT/PIC interrupt behaivor

Post by xenos »

Owen wrote:iret dword is 66 CF in real mode/16-bit protected mode and 66 in 32-bit protected mode
I guess you mean CF in 32 bit pmode ;)
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
Post Reply