Page 1 of 1
Long Mode IDT
Posted: Mon Apr 06, 2009 7:36 am
by johnsa
Having issues getting the IDT working in 64bit mode...
Below is the setup code that gets called, fills the idt table with not-present interrupt gates, configures int 0 only to a handler (div by 0).. nothing goes wrong here.. second we're back in the main code and we do an STI or force an IDIV by zero we triple fault.
Anyone see anything wrong that I'm missing?
PS NMI and IRQS are still disabled at this point (until this table is working and I've fully populated all the handlers with a base generic handler chainable etc etc).
Code: Select all
struct interrupt_gate
rsrvd dd ?
ofs63_32 dd ?
ofs31_16 dw ?
flags dw ?
selector dw ?
ofs15_0 dw ?
ends
idt_init64:
mov rsi,offset kernel_idt
mov ecx,256
fillidt:
mov ax,0e00h
mov [rsi+interrupt_gate.flags],ax
add rsi,16
dec ecx
jnz short fillidt
mov rsi,offset kernel_idt
mov ax,8e00h
mov [rsi+interrupt_gate.flags],ax
mov rax,offset exception0_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,08h
mov [rsi+interrupt_gate.selector],ax
mov rax,offset kernel_idt
mov rsi,offset IDTReg
mov [rsi+2],rax
lidt [rsi]
ret
align 16
kernel_idt:
repeat 256
dq 0,0
end repeat
idt_size equ ($-kernel_idt)-1
align 16
IDTReg:
dw idt_size
dq 0
align 16
exception0_handler:
jmp short $
iretq
Re: Long Mode IDT
Posted: Mon Apr 06, 2009 2:28 pm
by johnsa
i think the struct layout was back 2 front, so i swapped it.. I also pointed ALL idt entries to the dummy handler the same way.. still no joy.. on sti.. reboot.
I had a look thru the bochs debug output and the only thing i can find was:
interrupt(long mode): not accesable or not code segment
CPU is in long mode (active)
CS.d_b = 16bit
SS.d_b = 16bit
.. all the other register values look fine, and RIP is on the STI instruction..
One other thing i have noticed as well
Once I'm in long mode, I set all the seg regs to the data64 descriptor (ds,es,fs,gs) ... I'm not sure if this is necessary, but If i don't do it then the CPU dump from bochs etc still show funny values for the base/limit on these regs.
However, if I try to set SS to the same selector QEMU resets completely while bochs doesn't complain.. I'm not sure if I should set SS to seomthing, and if not that same selector i use for the other seg regs, then what?
Re: Long Mode IDT
Posted: Mon Apr 06, 2009 3:55 pm
by Troy Martin
STI is your problem. It allows external maskable interrupts to be called from the PIC (IRQs.) NMIs can still fire.
Research first, then ask.
Re: Long Mode IDT
Posted: Tue Apr 07, 2009 1:43 am
by johnsa
thanks for the sarcasm, i'm fully aware of what sti does and when the nmi's would be able to fire
the reply I posted maybe needed more detail, it's not JUST sti. if I don't do an STI but manually cause a div.by.zero, the sample triple fault happens.
I tried connecting ALL the idt entries up to dummy handlers and putting IRQ handler stubs on the ones linked as such (32-48). Still the second an an STI or div.by.zero occurs, triple fault...
Re: Long Mode IDT
Posted: Tue Apr 07, 2009 1:50 am
by xenos
johnsa wrote:interrupt(long mode): not accesable or not code segment
It looks like your CS register contains something wrong. I once had a similar problem... Make sure that CS contains a valid code segment before enabling interrupts.
Re: Long Mode IDT
Posted: Tue Apr 07, 2009 2:08 am
by johnsa
As a side note to Troy's post.. the STI isn't going to magically enable IRQs while the PIC is fully masked too.. as I mentioned in my first post.
Xen, that's what it looked like to me as well.. so to test I put a 0 into the IDT descriptiors, then the bochs log shows the error as being NULL descriptor, then I put it back to 8 (which is what the whole kernel cs runs under).. so its definately a valid 64bit code selector.. unless under 64bit mode the selector index numbers should change to be *16 not *8 ? I currently setup the GDT before switching to long mode, maybe I should reset the GDT once in long mode so it too has 64bit entries/10byte GDTR ? .. perhaps thats also why any load to SS breaks in QEMU (works in bochs tho).
Re: Long Mode IDT
Posted: Tue Apr 07, 2009 2:37 am
by johnsa
Found the problem... all fixed now.. I took some info from the long mode wiki tutorial and there is a mistake in it... the data GDT entry in the tutorial is:
Code: Select all
.data equ $ - gdt
dq 0x0000900000000000
it should be:
Code: Select all
.data equ $ - gdt
dq 0x0000920000000000
... as it's marked as read-only... perhaps that was intentional just to get into long mode, but once in a data selector that isn't read/write... isn't much use
the CS selector was indeed correct at 08h, the *16 isn't an option as selectors remain 8 bytes unless its a system type.
Re: Long Mode IDT
Posted: Tue Apr 07, 2009 7:22 am
by johnsa
OK so now the machine doesn't fault, full IDT is setup with stub handlers and NMI/IRQs are re-enabled, STI is done.. all working.
If I run some code that causes an exception, the correct handler is triggered (ie div.by.zero).. however an INT n doesn't seem to trigger anything...
Re: Long Mode IDT
Posted: Tue Apr 07, 2009 7:27 am
by johnsa
its odd, it seems that the initial handler stub put in for all the ints, 48-255 does fire but ONLY if the int no. is > 90 ... like INT 100 works, but INT 80 doesn't.. also then if you try to update the IDT with a new handler after that LIDT for those int's it's not taking affect.. but the exception ones are..
Re: Long Mode IDT
Posted: Tue Apr 07, 2009 8:32 am
by johnsa
Ok found the problem.. its odd.. in Bochs if the PIC irqs are all masked, when you STI the timer (IRQ0) fires once... under qemu it doesn't... not sure if this is a bochs bug?
Re: Long Mode IDT
Posted: Tue Apr 07, 2009 8:49 am
by Troy Martin
I had issues when writing my pmode IDT and IRQs. I'm not sure what happened to the IRQs, but for some reason the timer never fired. I did some code re-arranging and added in a few debugging statements and it was fixed, as almost if by itself.
I still have no idea what was causing the issue though. There were no TFs, no GPFs, no nothing, just no timer ticks.
Ah well, it's all said and done now. Time to write a normal (read: not polling) keyboard driver