I've had my long mode IDT setup for a while now, and I've been using IRQs quite extensively and they all work perfectly. The second I try to use an INT instruction .. triple fault.
I've double checked the idt entries and descriptor format and it seems fine to me, just can't figure why a direct INT won't work.
Here is what I've got setup as an entry in the IDT say for INT 80h:
Code: Select all
struct interrupt_gate
ofs15_0 dw ?
selector dw ?
flags dw ?
ofs31_16 dw ?
ofs63_32 dd ?
rsrvd dd ?
ends
;the flags are set to 0x8e00 ... which in 64bit mode should be correct for int gate / using modified legacy stack / ring 0 (so no tss or switch) ...
;The IDT is initially setup with dummy handlers for all 256 ints, then various things replace them as needed.. like the base IRQ manager / setup using the install_int64 function:
macro INSTALL_INT_HANDLER int_num,handler_addr,int_type
{
mov ecx,int_num
mov rax,handler_addr
mov dx,int_type
call install_int64
}
idt_init64:
mov rsi,offset kernel_idt
mov ecx,256
fillidt:
mov ax,8e00h
mov [rsi+interrupt_gate.flags],ax
mov rax,offset dummy_handler
mov rbx,rax
shr rbx,32
mov [rsi+interrupt_gate.ofs15_0],ax
shr rax,16
mov [rsi+interrupt_gate.ofs31_16],ax
mov [rsi+interrupt_gate.ofs63_32],ebx
mov ax,8
mov [rsi+interrupt_gate.selector],ax
xor eax,eax
mov [rsi+interrupt_gate.rsrvd],eax
add rsi,16
dec ecx
jnz short fillidt
lea rax,[kernel_idt]
lea rsi,[IDTReg]
lea rdi,[IDTBase]
mov [rdi],rax
lidt [rsi]
ret
; ECX = interrupt vector number.
; RAX = address of new handler.
; DX = (8e00h=int/8f00h=trap).
install_int64:
mov rsi,offset kernel_idt
xor rbx,rbx
mov ebx,ecx
shl ebx,4
add rsi,rbx
mov [rsi+interrupt_gate.flags],dx
mov rbx,rax
shr rbx,32
mov [rsi+interrupt_gate.ofs15_0],ax
shr rax,16
mov [rsi+interrupt_gate.ofs31_16],ax
mov [rsi+interrupt_gate.ofs63_32],ebx
mov ax,8
mov [rsi+interrupt_gate.selector],ax
xor eax,eax
mov [rsi+interrupt_gate.rsrvd],eax
ret
align 4
dummy_handler:
iretq
align 16
kernel_idt:
entries dq 512 DUP (0)
align 16
IDTReg:
dw 4095
IDTBase:
dq 0
; so in the kernel somewhere i setup an int...
INSTALL_INT_HANDLER 80h,offset int_handler,0x8e00
; and call it..
int 80h..
it never makes it into the handler code at all.
anyone have any ideas as it seems the IDT is fine to me as it works from the IRQ handlers, just when trying to call one via INT it dies.