Long Mode IDT

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.
Post Reply
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Long Mode IDT

Post 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
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Re: Long Mode IDT

Post 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?
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: Long Mode IDT

Post 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.
Image
Image
Solar wrote:It keeps stunning me how friendly we - as a community - are towards people who start programming "their first OS" who don't even have a solid understanding of pointers, their compiler, or how a OS is structured.
I wish I could add more tex
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Re: Long Mode IDT

Post 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...
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Long Mode IDT

Post 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.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Re: Long Mode IDT

Post 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).
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Re: Long Mode IDT

Post 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.
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Re: Long Mode IDT

Post 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...
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Re: Long Mode IDT

Post 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..
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Re: Long Mode IDT

Post 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?
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: Long Mode IDT

Post 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 :P
Image
Image
Solar wrote:It keeps stunning me how friendly we - as a community - are towards people who start programming "their first OS" who don't even have a solid understanding of pointers, their compiler, or how a OS is structured.
I wish I could add more tex
Post Reply