切换到用户空间

时间:2015-05-30 15:26:10

标签: assembly x86 operating-system kernel

这是演示os内核基本功能的代码的一部分。 在刷新GTD并设置IDT后,我想切换到ring 3运行一些int和context switch。 但是我无法跳转到用户模式。我想用iret指令来使用技巧。据我所知,iret将弹出 从堆栈跟随值:SS ESP EFLAGS CS EIP所以想法是将适当的值推送到堆栈(使用新的段选择器), 并让iret在寄存器中设置值。这是我正在使用的代码:

    .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

问题在于iret开始执行此指令后检查选择器的权限级别并且代码是perforem,因此结果CPU故障和重置。 这是日志形式BOCHS:check_cs(0x0008): non-conforming code seg descriptor dpl != cpl, dpl=3, cpl=0。我将非常感谢您对此问题的任何帮助

1 个答案:

答案 0 :(得分:2)

正如bochs告诉你的那样,你的选择器0x08CPL=0但描述符条目有DPL=3。请记住,选择器的两个最低有效位是CPL。因此,要切换到ring3,您应该使用0x0b

相关问题