2010-11-02 80 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)真正的硬件非常好。