I have implemented a way to register callback functions to interrupts in my kernel that I am developing from scratch. This means if a program runs int 0x67
it will call a C function in my kernel to handle a system call. It returns like it should and the kernel continues executing code. However, when I map functions to certain interrupts, I cannot return and the processor seems to hang. For example, here's some of my code:
void test(registers_t *r) {
print("Why can't I return from this?\n");
}
void syscall(registers_t *r) {
print("I can always return from this.\n");
}
and in my main function:
register_int_handler(11, &test); //Also happens on 10 and 11 and 13
register_int_handler(103, &syscall); //a.k.a. 0x67 in hex, this one works.
then I can call:
asm("int $0x67"); //Works fine, code continues executing
asm("int $0xB"); //Calls "test" (interrupt 11 )but code execution stops...
asm("int $0x67"); //This never gets called.
Expected output:
I can always return from this.
Why can't I return from this?
I can always return from this.
What I actually see:
I can always return from this.
Why can't I return from this?
Here is the assembly code that actually handles interrupts:
extern isr_handler
isr_common_stub:
pusha
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp
push eax
mov eax, isr_handler
call eax
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8
sti
iret
isr_handler
is a C function that looks in an array of registered handlers and calls the function I assign it.
void isr_handler(registers_t *r) {
if(interrupt_handlers[r->int_no] != 0) {
isr_t handler = interrupt_handlers[r->int_no];
handler(r);
}
}
This part works, but some interrupts (I believe only the 32 reserved exceptions) don't return. I need to return from this, I can't have the computer crash every time something like a page fault happens. Any insight? Thanks in advance.
P.S. I compile and run with a GCC cross-compiler, compiled to target i686-elf. It looks like this:
i686-elf-gcc -m32 -c kernel.c -o ../bin/kernel.o -O3 -ffreestanding -Wall -Wextra -fno-exceptions
EXTREME UPDATE: ONLY the interrupts that pass error codes are not being returned from. Am I doing this part wrong? Heres the macro for the error code interrupt:
%macro ISR_ERRCODE 1
global isr%1
isr%1:
cli
push byte %1
jmp isr_common_stub
%endmacro
I thought the error code got pushed automatically? Here is the macro for a regular, non-errorcode interrupt:
%macro ISR_NOERRCODE 1
global isr%1
isr%1:
cli
push byte 0
push byte %1
jmp isr_common_stub
%endmacro
I push a dummy error code here to keep a uniform stack frame. Why are the error code interrupts not working right?
Ok I figured it out, pretty simple actually. The interrupts that require error codes (8, 10-14) were never getting error codes pushed onto the stack when I call them with asm("int $0xB");
(interrupt 11). This called the function without setting up the stack correctly.
The macro:
%macro ISR_ERRCODE 1
global isr%1
isr%1:
cli
push byte %1
jmp isr_common_stub
%endmacro
As you can see, only the isr number is pushed where as the other macro, the ISR_NOERRCODE
one, a dummy byte was pushed. The error code gets pushed automatically by the processor when the certain interrupt gets called. I was just calling it manually without doing this. Thats why 0-7 and 15 and beyond would still work. Pretty silly mistake actually, but thanks everyone for helping out!