Problem with calling ISRs
Posted: Mon Sep 05, 2016 6:57 am
Hi everyone,
I've got a newbie problem - I cannot seem to get my ISRs to be called.
What's happening:
My code to test my ISRs (a simple divide by zero) does not appear to call the appropriate ISR to handle the exception, causing the machine to triple fault and reboot.
How I got here:
I followed the Meaty Skeleton template on the Wiki, and then built on that using Bran's Kernel Development. Up to now I have used this tutorial to load a new GDT, and have then gone on to use its pages on the IDT and ISRs to attempt to implement interrupt handling. I have not done too much yet: aside from all of the stuff covered in Meaty Skeleton, I have only written screen scrolling code and GDT-loading code.
My code:
I'll explain my interpretation of how this works, so any misconceptions I may have can be identified:
1) The kernel calls the function loadidt(), which is located in idt.c. This function creates a new, empty IDT and then calls idt_init(), which is in boot.S, to actually do the lidt. Now we should have an unpopulated IDT table. This function returns to the kernel.
2) The kernel then calls another function, loadisr(), which is located in isr.c. This function calls idt_setgate() (located in idt.c) for each interrupt, to populate the idt.
3) If an interrupt occurs, the processor looks up the correct ISR in the IDT and executes it as follows:
ISRs are defined in assembly. They push a dummy error code (if one is not already pushed) and a number identifying the isr. Then they jump to an assembly label - isr_common_stub - which takes care of
pushing the registers, resetting them to the data segment, and then calling a function defined in isr.c to print the relevant error message (working this out using the pushed registers and a structure defined in a header file) and halt the system.
4) In the main kernel function, I've done this to test my interrupts:
The code can be seen here:
idt.c
Section of boot.S that deals with interrupts.
isr.c
From my attempts at debugging (inserting infinite loops at places in the code), the problem seems to be occurring before the ISRs are called; that is to say that they are not being called at all. This leads me to suspect that there is something wrong with the implementation of the IDT.
What's interesting is that everything appears to work fine before any interrupts are called: both loadidt() and loadisr() return back to the kernel without any crashing.
How I've tried to resolve this:
I have checked the Bran's Known Bugs page on the Wiki, and searched the Wiki, the forums and the rest of the Internet for any possible resolution. I have also tried starting the OS from scratch and recoding everything, to no avail - I think this should rule out any mistyped code.
Does anyone know if I may have made a common mistake in my code? I feel that maybe I'm either missing something pretty fundamental about interrupts.
I hate to ask such a question on here, but I'm at my wits' end: I have been trying to solve this for weeks.
Thanks very much.
I've got a newbie problem - I cannot seem to get my ISRs to be called.
What's happening:
My code to test my ISRs (a simple divide by zero) does not appear to call the appropriate ISR to handle the exception, causing the machine to triple fault and reboot.
How I got here:
I followed the Meaty Skeleton template on the Wiki, and then built on that using Bran's Kernel Development. Up to now I have used this tutorial to load a new GDT, and have then gone on to use its pages on the IDT and ISRs to attempt to implement interrupt handling. I have not done too much yet: aside from all of the stuff covered in Meaty Skeleton, I have only written screen scrolling code and GDT-loading code.
My code:
I'll explain my interpretation of how this works, so any misconceptions I may have can be identified:
1) The kernel calls the function loadidt(), which is located in idt.c. This function creates a new, empty IDT and then calls idt_init(), which is in boot.S, to actually do the lidt. Now we should have an unpopulated IDT table. This function returns to the kernel.
2) The kernel then calls another function, loadisr(), which is located in isr.c. This function calls idt_setgate() (located in idt.c) for each interrupt, to populate the idt.
3) If an interrupt occurs, the processor looks up the correct ISR in the IDT and executes it as follows:
ISRs are defined in assembly. They push a dummy error code (if one is not already pushed) and a number identifying the isr. Then they jump to an assembly label - isr_common_stub - which takes care of
pushing the registers, resetting them to the data segment, and then calling a function defined in isr.c to print the relevant error message (working this out using the pushed registers and a structure defined in a header file) and halt the system.
4) In the main kernel function, I've done this to test my interrupts:
Code: Select all
char c = 10 / 0;
printf("%c\n", c);
The code can be seen here:
idt.c
Section of boot.S that deals with interrupts.
isr.c
From my attempts at debugging (inserting infinite loops at places in the code), the problem seems to be occurring before the ISRs are called; that is to say that they are not being called at all. This leads me to suspect that there is something wrong with the implementation of the IDT.
What's interesting is that everything appears to work fine before any interrupts are called: both loadidt() and loadisr() return back to the kernel without any crashing.
How I've tried to resolve this:
I have checked the Bran's Known Bugs page on the Wiki, and searched the Wiki, the forums and the rest of the Internet for any possible resolution. I have also tried starting the OS from scratch and recoding everything, to no avail - I think this should rule out any mistyped code.
Does anyone know if I may have made a common mistake in my code? I feel that maybe I'm either missing something pretty fundamental about interrupts.
I hate to ask such a question on here, but I'm at my wits' end: I have been trying to solve this for weeks.
Thanks very much.