Page 1 of 1

Stumped on long mode triple fault

Posted: Mon Mar 04, 2024 1:06 pm
by orbitaldecay
Hey folks,

I'm in the middle of writing a long mode boot loader. I am running into problems with the IDT. When I manually test interrupts after initializing the IDT, I get a triple fault (on the int 0x80 instruction). I do not currently have a TSS because my understanding is that I do not need one (yet) so long as I am not leaving ring 0 and my ISTs for all of my interrupts are zero (which they should be). Any help would be greatly appreciated. Here is the relevant code:

Code: Select all

	org 0x7c00
	bits 16

%define IDT_ADDR 0x6000
%define KERNEL_ADDR 0x10000
%define STACK_ADDR 0x6000

	; Canonicalize IP
	jmp 0x0000:start
start:
	; Clear the direction flag
	cld

	; Clear data segment
	xor ax, ax
	mov ds, ax

	; Turn on A20 gate (fast A20)
a20:	in al, 0x92
	or al, 2
	out 0x92, al

	; Set up long mode paging (identity map first 2 MB)
	mov edi, 0x1000
	mov cr3, edi
	xor eax, eax
	mov ecx, 4096
	rep stosd
	mov edi, cr3
	mov dword [edi], 0x2003
	add edi, 0x1000
	mov dword [edi], 0x3003
	add edi, 0x1000
	mov dword [edi], 0x4003
	add edi, 0x1000
	mov ebx, 3
	mov ecx, 512
page:	mov dword [edi], ebx
	add ebx, 0x1000
	add edi, 8
	loop page

	; Enable PAE
pae:	mov eax, cr4
	or eax, 1 << 5
	mov cr4, eax

	; Switch to long mode
	cli
	mov ecx, 0xc0000080	; LM-bit
	rdmsr
	or eax, 1 << 8
	wrmsr
	mov eax, cr0		; Enable paging and protected mode
	or eax, 1 << 31 | 1 << 0
	mov cr0, eax
	lgdt [gdtr]
	jmp CODE_SEG:lmode

	bits 64

lmode:	mov ax, DATA_SEG
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax
	mov rsp, STACK_ADDR

	; Create IDT
	mov rdi, IDT_ADDR
	xor rcx, rcx
	dec cl
idt:	mov ax, isr
	stosw
	mov ax, CODE_SEG
	stosw
	mov ax, 0x8e00
	stosw
	xor rax, rax
	stosw
	stosd
	stosd
	loop idt

	; Load IDT and test
	lidt [IDT_ADDR]
	int 0x80

spin:	jmp spin

	; Default isr
isr:
	mov dword [0xb8000], ') : '
	iretq

idtr:
	dw (256 * 16) - 1
	dq IDT_ADDR

gdt:
gdtr: ; null segment also
	dw gdt_end - gdt - 1
	dd gdt
	dw 0

gdt_code:
	dw 0xffff	; limit
	dw 0x0000	; base
	db 0		; base
	db 0x9a		; access byte
	db 10101111b	; flags / limit
	db 0		; base

gdt_data:
	dw 0xffff
	dw 0x0000
	db 0
	db 0x92
	db 11001111b
	db 0
gdt_end:

CODE_SEG equ gdt_code - gdt
DATA_SEG equ gdt_data - gdt

times 510 - ($ - $$) db 0

	dw 0xAA55
And here is a log of the triple fault in QEMU:

Code: Select all

check_exception old: 0x8 new 0xe
Triple fault
CPU Reset (CPU 0)
RAX=0000000000000000 RBX=0000000000200003 RCX=0000000000000000 RDX=0000000000000000
RSI=0000000000000000 RDI=0000000000006ff0 RBP=0000000000000000 RSP=0000000000006000
R8 =0000000000000000 R9 =0000000000000000 R10=0000000000000000 R11=0000000000000000
R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 R15=0000000000000000
RIP=0000000000007ce3 RFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 0000000000000000 ffffffff 00af9a00 DPL=0 CS64 [-R-]
SS =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT=     0000000000007cfe 00000017
IDT=     000000008e000008 00007ce7
CR0=80000011 CR2=000000008e000088 CR3=0000000000001000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000000 CCD=ffffffffffffffff CCO=CLR
EFER=0000000000000500
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=0000000000000000 0000000000000000 XMM01=0000000000000000 0000000000000000
XMM02=0000000000000000 0000000000000000 XMM03=0000000000000000 0000000000000000
XMM04=0000000000000000 0000000000000000 XMM05=0000000000000000 0000000000000000
XMM06=0000000000000000 0000000000000000 XMM07=0000000000000000 0000000000000000
XMM08=0000000000000000 0000000000000000 XMM09=0000000000000000 0000000000000000
XMM10=0000000000000000 0000000000000000 XMM11=0000000000000000 0000000000000000
XMM12=0000000000000000 0000000000000000 XMM13=0000000000000000 0000000000000000
XMM14=0000000000000000 0000000000000000 XMM15=0000000000000000 0000000000000000

Re: Stumped on long mode triple fault

Posted: Mon Mar 04, 2024 1:32 pm
by Octocontrabass
orbitaldecay wrote:

Code: Select all

	lidt [IDT_ADDR]
Shouldn't that be "lidt [idtr]"?

Re: Stumped on long mode triple fault

Posted: Mon Mar 04, 2024 1:39 pm
by orbitaldecay
Octocontrabass wrote:
orbitaldecay wrote:

Code: Select all

	lidt [IDT_ADDR]
Shouldn't that be "lidt [idtr]"?
Well don't I feel silly. Thank you so much!