Stumped on long mode triple fault
Posted: Mon Mar 04, 2024 1:06 pm
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:
And here is a log of the triple fault in QEMU:
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
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