I am writing a simple os for x86-64. I made it to the long mode. Now I gotta get to the user mode cause I want my os to run user applications. So here's how my gdt looks like:
GDTLM:
.Null: equ $ - GDTLM
dq 0
.Code: equ $ - GDTLM
dw 0xffff
dw 0
db 0
db 10011010b
db 10101111b
db 0
.Data: equ $ - GDTLM
dw 0xffff
dw 0
db 0
db 10010010b
db 11001111b
db 0
.UserCode: equ $ - GDTLM
dw 0xffff
dw 0
db 0
db 11111010b
db 10101111b
db 0
.UserData: equ $ - GDTLM
dw 0xffff
dw 0
db 0
db 11110010b
db 11001111b
db 0
.Pointer:
dw $ - GDTLM - 1
dq GDTLM
And here's the code that makes the actual switch to user code for me (obviously it must do, but it doesn't):
cli
mov ax, 0x23
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov rax, rsp
push 0x23
push rax
pushf
push 0x1B
push _user
iretq
When I try to run it in bochs it says something like this:
check_cs(0x5054): conforming code seg descriptor dpl > cpl, dpl=3, cpl=0
fetch_raw_descriptor: GDT: index (5547) aa8 > limit (27)
What do I do wrong?