0

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?

MindW1n
  • 11
  • 4
  • Two bits in the end of the segment selector represent the cpl, I guess – MindW1n May 25 '23 at 19:57
  • No, they represent the rpl, I've just read. – MindW1n May 25 '23 at 20:04
  • 1
    After successfully switching to a new CS, the low bits are the current privilege level (CPL). While executing a far jump, the low bits are the requested (new) privilege level. (@SepRoland). Bit 2 (`1<<2`) selects GDT vs. LDT. https://wiki.osdev.org/Segment_Selector . So the CPU can just mask off the low 3 bits and use the rest as a byte offset into the appropriate table. – Peter Cordes May 25 '23 at 20:49
  • Does the printed RIP point to the `iretq`? – Jester May 25 '23 at 22:29
  • The DPL of your data descriptor seems to be `00` instead of `11`. You did not provide a [mcve] but fixing that it apparently works fine here. – Jester May 25 '23 at 22:50
  • No, it still does not work. The dpl is 11b. I changed the pushf to pushfq because it is x86-64. The first error is gone, but the rest of them are still there. – MindW1n May 28 '23 at 18:02
  • Solved! It was the page fault. When the processor is switched to user mode it tries to execute the first instruction of user mode code. But when it does that the page privilege check occurs, so the third bit of the page table entry needs to be 1 in order to make the page accessible to user. – MindW1n Jun 08 '23 at 17:11

0 Answers0