(Solved...mostly) Divide by Zero Exception during hlt loop
Posted: Wed Jun 22, 2016 9:17 pm
I have been working on my OS using resources from osdev and bran's kernel tutorial and I was trying to enable the PIT interrupt for a simple timer. In my kernel I added
so the main method didn't exit.
This all works fine except that it throws a divide by zero exception, as well as the timer handler not firing. The exception is thrown after the EOI is sent to the master (and slave if the irq was not irq 0-7)I have spent hours rereading the code and even ended up trying to flat out copy code to see if replacing a certain methods would fix everything. I have also been using inline asm instead of external methods if that makes too much of a difference.
Here's the code for the IRQ stub:
Basically the code for all the irqs (and isrs but very very slight difference just with what gets called)
fault&irq handlers code I just ended up copying over to see if it made any difference
If you need to see any other parts of the source just ask and I'll add them, thank you for your time.
Code: Select all
for(;;)
{
__asm__ ("hlt");
}
This all works fine except that it throws a divide by zero exception, as well as the timer handler not firing. The exception is thrown after the EOI is sent to the master (and slave if the irq was not irq 0-7)I have spent hours rereading the code and even ended up trying to flat out copy code to see if replacing a certain methods would fix everything. I have also been using inline asm instead of external methods if that makes too much of a difference.
Here's the code for the IRQ stub:
Code: Select all
void irq_common_stub()
{
printf("An IRQ Somewhere just executed the stub.");
__asm__ __volatile__ (
"pusha;"
"pushw %%ds;"
"pushw %%es;"
"pushw %%fs;"
"pushw %%gs;"
"movw $0x10, %%ax;"
"movw %%ax, %%ds;"
"movw %%ax, %%es;"
"movw %%ax, %%fs;"
"movw %%ax, %%gs;"
"movl %%esp, %%eax;"
"pushl %%eax;"
"call irq_handler;"
"popl %%eax;"
"popw %%gs;"
"popw %%fs;"
"popw %%es;"
"popw %%ds;"
"popa;"
"addl $8, %%esp;"
"iret;"
:
:
:"memory"
);
}
Code: Select all
void irq0()
{
printf("irq0 activated\n"); //temporary debug text
__asm__ __volatile__ (
"cli;"
"pushl $0;"
"pushl $32;"
"call irq_common_stub"
: : :"memory"
);
}
Code: Select all
void fault_handler(struct regs *r)
{
//printf("fault handler activated");
/* Is this a fault whose number is from 0 to 31? */
if (r->int_no < 32)
{
/* Display the description for the Exception that occurred.
* In this tutorial, we will simply halt the system using an
* infinite loop */
printf(exception_messages[r->int_no]);
printf(" Exception. System halted.");
for (;;);
}
else
{
irq_handler(r);
}
}
void irq_handler(struct regs *r)
{
int i = r->int_no;
if(i > 31)
{
printf("An IRQ Somewhere just activated the handler.\n");
/* This is a blank function pointer */
puts(" - handler: created blank pointer");
void (*handler)(struct regs *r);
puts(" - done");
/* Find out if we have a custom handler to run for this
* IRQ, and then finally, run it */
puts(" - handler: get IRQ routine.");
handler = irq_routines[i + 32];
puts(" - done");
if (handler)
{
puts(" - handler: activating the handler...");
handler(r);
puts(" - done");
}
/* If the IDT entry that was invoked was greater than 40
* (meaning IRQ8 - 15), then we need to send an EOI to
* the slave controller */
if (i >= 40)
{
puts(" - handler: sending to slave...");
outportb(0xA0, 0x20);
puts(" - done");
}
/* In either case, we need to send an EOI to the master
* interrupt controller too */
puts(" - handler: sending to master...");
outportb(0x20, 0x20);
puts(" - done");
}
}