2014-11-01 49 views
1

我正嘗試使用lret指令從ring0切換到ring3。因此,我爲ss,esp,cs,ip推送正確的值,並使用lret。在x86中從ring0切換到ring3時出錯

我用QEMU和gdb調試代碼,並發現一件奇怪的事情:

LRET instrunction後,處理器成功地切換到環3(我用「信息登記」的QEMU來檢查),值ss,cs,esp都是正確的,並且eip指向ring3代碼的第一條指令。

但是,不管是什麼環3代碼的第一個指令是(甚至NOP指令),QEMU將重新啓動(可能是一般保護性錯誤?)

下面是代碼,頭文件是從this repo。自舉程序將CPU切換到保護模式,並將內核加載到0x100000,內核的虛擬地址從0x80100000開始。

#include "memlayout.h" 
#include "mmu.h" 
#include "asm.h" 

.text 

.globl _start 
_start = V2P_WO(entry) 

.globl entry 
entry: 
    mov %cr4, %eax 
    or $(CR4_PSE), %eax 
    mov %eax, %cr4 
    mov $(V2P_WO(pgdir)), %eax 
    mov %eax, %cr3 
    mov %cr0, %eax 
    or $(CR0_PG|CR0_WP), %eax 
    mov %eax, %cr0 

    lgdt gdtdesc 

    mov $0x28, %ax 
    ltr %ax 
    mov $kernel_stack, %esp 
    push $0x23 
    push $user_stack 
    push $0x1b 
    push $user_task 

    lret 

user_task: 
    nop 
die: 
    jmp die 

.data 

.align 4096 
tss: 
    .long 0 
    .long kernel_stack 
    .word 0x10, 0 
    .long 0, 0, 0, 0 
    .long pgdir 
    .long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
    .long 0, 0, 0, 0, 0, 0, 0, 0 

gdt:  
    SEG_NULLASM 
    SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg 
    SEG_ASM(STA_W, 0x0, 0xffffffff)   # data seg 
    SEG_ASM_USER(STA_X|STA_R, 0x0, 0xffffffff) 
    SEG_ASM_USER(STA_W, 0x0, 0xffffffff) 

    .word 0, 0x1000 
    .byte 0x10, 0x89, 0x80, 0x80 

gdtdesc: 
    .word (gdtdesc - gdt - 1) 
    .long gdt 

.align 4096 
pgdir: .long PTE_P|PTE_W|PTE_PS 
    .fill 511, 4 
    .long PTE_P|PTE_W|PTE_PS 
    .fill 511, 4 

    .fill 4096 
kernel_stack: 

    .fill 4096 
user_stack: 
+2

向我們展示您的代碼和全局描述符錶轉儲。我不知道如何使用/打開Qemu中的功能,但在[Bochs emulator](http://bochs.sourceforge.net/)中,調試界面有**指令跟蹤**(http:///bochs.sourceforge.net/doc/docbook/user/internal-debugger.html).. – xmojmr 2014-11-01 08:34:04

回答

0

哦,我發現問題在哪裏。訪問衝突發生在分頁。

+1

您可以添加更多的細節,您是如何找到錯誤的,對未來的讀者可能有用嗎? – xmojmr 2014-11-03 08:52:02

+1

我重新組織我的代碼並放在這裏。在我放置代碼之後,我突然發現我啓用了分頁,並沒有考慮分頁中的特權問題。 – delphifirst 2014-11-03 08:59:33

相關問題