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.
I have exceptions 0 - 17 tied to one fault handler that will print out the number of exception triggered, and what it is. The problem is I am getting the same number printed out for all exceptions: 8 (Double fault).
idt_selector:
0x8E00 // 1000111000000000 = present,ring0,int_gate
Bochs output: (Same for each exception)
32 bit interrupt gate target = 0x0008:0x00010380, DPL = 0
From Intel manuals
Normally, when the processor detects an exception while trying to invoke the handler for a prior exception, the two exceptions can be handled serially. If, however, the processor cannot handle them serially, it signals the double-fault exception instead. To determine when two faults are to be signalled as a double fault, the 80386 divides the exceptions into three classes: benign exceptions, contributory exceptions, and page faults.
Can you post some code - your interrupt stubs should be fine. If you do not have different stubs, how are you getting the code? The processor does not tell you the exception number when it invokes the handler.
I don't think the double fault is the problem - it could be, though.
The double fault is most likely not actually a double fault, it's probably a hardware interrupt (IRQ0 - PIT), you will need to mask or remap the PIC before you'll be able to tell whether or not it's a CPU exception. Also your Int8 handler is invalid, since you are using the same handler for all exceptions I assume you aren't removing the Error Code from the stack which will cause another exception when you attempt to IRET from the handler.
Can you post some code - your interrupt stubs should be fine. If you do not have different stubs, how are you getting the code? The processor does not tell you the exception number when it invokes the handler.
I should of made myself more clear. I am using different stubs for each exception but having them called through one common fault_handler.
%macro STUB 1
push byte 0 ; "Fake" error code
push byte %1 ; Exception number
push gs ; Push segment registers
push fs
push es
push ds
pusha ; Push EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX
; Put known-good values into segment registers
mov ax, 0x10
mov ds, eax
mov es, eax
mov fs, eax
mov gs, eax
.1:
mov eax, _fault_handler ; Default "handler"
call eax ; Use EAX for absolute call vs. EIP-relative
popa ; Pop EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX
pop ds ; Pop segment registers
pop es
pop fs
pop gs
add esp, 8 ; Drop exception number and error code
iret
%endmacro
; ISR00 (Divide Error)
divide_error:
STUB 0x00
Also your Int8 handler is invalid, since you are using the same handler for all exceptions I assume you aren't removing the Error Code from the stack which will cause another exception when you attempt to IRET from the handler.
push eax
.1: mov eax, _fault_handler ; Default "handler"
call eax ; Use EAX for absolute call vs. EIP-relative
pop eax
You call C functions by pushing their parameters on to the stack. Right now, the top thing on the stack is 0x10 - the data segment. So, I would think it should be printing 0x10 - coproc error. Instead, you need to do push esp right before the function - and get rid of the push/pop eax (but add 4 to esp after the function call to pop the parameters).
Change your regs_t struct to match the layout of the stack, and change fault_handler to take a regs_t* pointer. Then it should work, and you get access to all the other registers as a bonus. See a previous related thread (that I can't find right now) for more information.