Ufo
Ufo

Reputation: 225

Switch to user space

this is part of code which demonstrates basic functions of os kernel. After flushing GTD and setting up IDT I want to switch to ring 3 run some int and context switch. However I cannot jump to user mode. I want to use trick with iret instruction. As far I know iret will pop from stack following values: SS ESP EFLAGS CS EIP so the idea is push proper values to the stack(with new segment selectors), and let iret set values in registers. Here is the code I am using:

    .equ NULL_DESCRIPTOR,  0x0000000000000000

    .equ CODE_P3,          0x40C3FA000000D090 
    .equ DATA_P3,          0x40C3F2000000D090 
    .equ CODE_KERNEL,      0x00CF9A000000FFFF 
    .equ DATA_KERNEL,      0x00CF92000000FFFF 
         GDT:
            .quad NULL_DESCRIPTOR
            .quad CODE_P3       #0x08
            .quad DATA_P3       #0x10
            .quad CODE_KERNEL   #0x18
            .quad DATA_KERNEL   #0x20
        _GDT:
            .word 39
            .long GDT


    .global flushGDT
    .type flushGDT, @function
    flushGDT:
        cli
        lgdt _GDT

        xor %eax, %eax

        #Data segment setup
        mov $0x10, %ax
        mov %ax, %ds
        mov %ax, %gs
        mov %ax, %fs
        mov %ax, %es

        #Stack save
        mov %esp, %eax

        #stack setup for iret and user space return

        pushl $0x10
        pushl %eax

        pushf
        #enable ints after switch to ring 3
        pop %eax
        or $0x200, %eax
        push %eax

        #CS selector
        pushl $0x08
        pushl $0x60 #Address of .leave (I have written proper ld script and checked with objdump)
        iret

    .section .upper_code, "ax", @progbits
    .leave:
        hlt
        call upperKernelCode

The problem is with iret after starting to execute this instruction check on privilege level of selector and a code is perforem, so in result CPU faults and reset. Here is log form BOCHS: check_cs(0x0008): non-conforming code seg descriptor dpl != cpl, dpl=3, cpl=0. I will much appreciate any help with this issue

Upvotes: 0

Views: 907

Answers (1)

Jester
Jester

Reputation: 58762

As bochs told you, your selector 0x08 has CPL=0 but the descriptor entry has DPL=3. Remember that the two least significant bits of the selector are the CPL. Thus, to switch to ring3, you should use 0x0b.

Upvotes: 2

Related Questions