I'm facing this very strange behaviour trying to setup an IDT under long IA-32e mode. I followed the Intel manuals instructions and yet something's bugging me desperately for the past 4-5 hours now. Here's the setup, then I'll describe the problem:
Code: Select all
[bits 64]
__setupIDT:
; RBX|RAX = IDT entry (trap-gate, 32 bits), pointing to __interruptProcedure
mov rax, 0x8F00_0000_0000
mov rbx, CODE64_SEL
shl rbx, 16
or rax, rbx
mov rbx, qword __interruptProcedure
and rbx, 0xFFFF0000
shl rbx, 32
or rax, rbx
mov rbx, qword __interruptProcedure
and rbx, 0xFFFF
or rax, rbx
mov rbx, qword __interruptProcedure
shr rbx, 32
mov rdi, qword IDT
mov cx, 256
__setupIDT_NextIDTStore:
mov [rdi], rax
mov [rdi+8], rbx
add rdi, 16
dec cx
jnz __setupIDT_NextIDTStore
mov rax, qword IDTR
lidt [rax]
;sti
lea rbx, [rip]
;int 32
call __interruptProcedure
ret
align 16
__interruptProcedure:
mov rax, [rsp]
hlt
iretq
align 16
IDTR:
idt_limit dw (256 * 16 - 1)
idt_base dq IDT
align 16
IDT:
times 256 ddq 0x00000000_00000000_0000_0000_0000_0000 ; set-up by code
Thank you very much in advance for your suggestions,
John X.
P.S.: Other notes - The assembler I use is YASM (an extension of NASM which uses basically the same syntax), running the code using QEMU. I was able to see the values of the registers by using QEMU's Monitor feature. The execution stops inside __interruptProcedure at the HLT instruction; when that happens, RAX should be loaded with the RIP pushed on the stack (mov rax, [rsp]). In QEMU Monitor I'm running the command "x /1i $eax" to see the instruction pointed by the RIP on the stack; this results in "RET" when STI is commented out and in "IRETQ" when it's uncommented. See details on the bottom of this page http://en.wikibooks.org/wiki/QEMU/Monitor regarding the QEMU Monitor command "x /1i $eax". Also, I've set-up the paging tables for long mode and everything is working properly regarding that. Each IDT entry is set-up to point to __interruptProcedure and to be a trap-gate, running under ring 0, present and to use the 0x08 code selector I've mentioned earlier. The IST for each IDT entry is set to be 0.