2010-11-02 30 views
9

我正在嘗試編寫一個內核,主要用於娛樂目的,而且我遇到了一個問題,我認爲它是三重故障。在我嘗試啓用分頁之前一切正常。被打破的代碼是這樣的:自家內核中的三重故障

void switch_page_directory(page_directory_t *dir){ 

current_directory = dir; 
asm volatile("mov %0, %%cr3":: "r"(&dir->tablesPhysical)); 

u32int cr0; 
asm volatile("mov %%cr0, %0": "=r"(cr0)); 

cr0 |= 0x80000000;//enable paging 
asm volatile("mov %0, %%cr0":: "r"(cr0)); //this line breaks 


}//switch page directory 

我一直在關注這個各種教程/文檔,但我使用尋呼的一個是這樣http://www.jamesmolloy.co.uk/tutorial_html/6.-Paging.html。我不確定其他代碼對於解決這個問題是有用的,但是如果有更多的我應該提供,我會非常樂意這樣做。

編輯=====

相信CS,DS和SS在這裏選擇正確的項是用來設置它們

global gdt_flush  
extern gp    
gdt_flush: 

    lgdt [gp]  ; Load the GDT with our 'gp' which is a special pointer 
    mov ax, 0x10  ; 0x10 is the offset in the GDT to our data segment 

    mov ds, ax 
    mov es, ax 
    mov fs, ax 
    mov gs, ax 
    mov ss, ax 

    jmp 0x08:flush2 ; 0x08 is the offset to our code segment: Far jump! 

flush2: 
    ret    ; Returns back to the C code! 

代碼和這裏的GDT結構本身

struct gdt_entry{ 
    unsigned short limit_low; 
    unsigned short base_low; 
    unsigned char base_middle; 
    unsigned char access; 
    unsigned char granularity; 
    unsigned char base_high; 
} __attribute__((packed)); 

struct gdt_ptr{ 
    unsigned short limit; 
    unsigned int base; 
} __attribute__((packed)); 

struct gdt_entry gdt[5]; 
struct gdt_ptr gp; 

IDT與此非常相似。

+0

那麼當你執行有問題的行時究竟發生了什麼? – sth 2010-11-02 19:31:11

+0

虛擬機重新啓動自己,並將im帶回引導裝載程序 – bschaffer13 2010-11-02 19:40:26

+0

我不認爲這裏有足夠的信息:許多事情可能出錯了,特別是如果你是從各種教程中混合的東西。你如何設置GDT? CS,DS和SS(至少)是否都選擇了合適的GDT條目?那麼IDT呢?是否正確設置了頁面表以進行標識映射?你在運行什麼虛擬機環境? – 2010-11-03 01:00:03

回答

6

GDT:你不說什麼內容的GDT項是的,但你已經證明的東西顯得頗爲相似earlier part of the tutorial you linked to,如果你以同樣的方式設置的條目,那麼所有的都應該是很好的(也就是說,對於CS來說,用0環代碼段進行平坦段映射,對於其他所有環0數據段,都以0爲基礎並且限制爲4GB)。

IDT:如果中斷被禁用並且您還沒有(尚)期望導致頁面錯誤,反正可能無所謂。

頁表:不正確的頁表似乎是最可能的嫌疑犯。確保您的身份映射覆蓋了您至少使用的代碼,數據和堆棧內存的全部

http://www.jamesmolloy.co.uk/tutorial_html/6.-Paging.html底部鏈接到源代碼肯定是建立東西正確地做工作既QEMU和Bochs的,所以希望你可以比較你與什麼在做什麼做什麼,並且找出什麼是錯的。

QEMU總體來說不錯,但我會推薦Bochs開發真正的低級別的東西 - 它包括(或可以配置爲包括)非常方便的internal debugger。例如設置reset_on_triple_fault=0cpu:線的配置文件,設置在switch_page_directory()代碼中設置斷點,運行到斷點,然後單步說明,看看會發生什麼......

+0

謝謝我將設置bochs我只使用qemu,因爲這是我的大學實驗室安裝的。 – bschaffer13 2010-11-03 22:06:17

+0

還有一個問題,如果你知道你的頭頂如何獲得boch讀取floppy.img我不能做sudo losetup/dev/loop0 floppy.img因爲我不在機器上我有sudo訪問 – bschaffer13 2010-11-03 23:18:19

+0

你可以將它指向一個文件而不是一個環回設備。例如'floppya:1_44 = floppy.img,status =插入'。 – 2010-11-03 23:20:28

2

您可以通過鏈接QEMU的gdb調試會話gdb中的遠程調試器工具。這可以通過發出以下命令來完成:

qemu -s [optional arguments] 

然後你的GDB會話中,打開你的內核可執行文件,並在您switch_page_directory()功能設置一個破發點後,輸入在gdb提示以下命令:

target remote localhost:1234 

然後,您可以在斷點處單步執行內核,並查看發生三重故障的位置。

另一個需要考慮的步驟是在IDT中實際安裝一些默認的異常處理程序......您發生三重故障的原因是CPU引發了異常,但是沒有適當的異常處理程序可以處理它。因此,在安裝了一些默認處理程序的情況下,尤其是雙錯誤處理程序,您可以有效地停止內核,而不會進入自動重置PC的三重故障。

最後,確保您在進入保護模式之前重新編程了PIC,否則默認硬件會中斷編程爲在實模式下從BIOS觸發,現在將觸發保護模式下的異常中斷。

1

我也面臨着尋呼tutorial.But同樣的問題,經過一番搜索,我發現它發生,因爲儘快啓用分頁的解決方案,所有的地址都成爲虛擬,解決它,我們必須映射虛擬地址到相同的物理地址,所以它們指的是相同的事物,這稱爲身份映射。

你可以按照這個link進一步幫助實施身份映射。

還有一件事你memset新分配的空間歸零,因爲它可能包含垃圾值和memset沒有在教程中完成它將工作bochs,因爲它爲你設置空間爲零,但其他模擬器(qemu)真正的硬件非常好。