首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >启用分页后的页面错误?OSDEV

启用分页后的页面错误?OSDEV
EN

Stack Overflow用户
提问于 2021-04-08 09:29:21
回答 1查看 757关注 0票数 1

我正在努力制作我自己的操作系统。我得到了中断工作,一些键盘和鼠标驱动,基本的视频和打印功能。现在,我想进入内存管理和任务,我意识到的第一件事是我需要分页,而我还没有正确地设置分页。

我遵循了有关它的一些指南和教程,其中最主要的是osdev wiki (https://wiki.osdev.org/Setting_Up_Paging)中的分页教程。我“写”(基本上是复制和粘贴)下面的代码来初始化分页。

代码语言:javascript
复制
void initPaging()
{
    
    unsigned int i;
    for(i = 0; i < 1024; i++)
    {
        // This sets the following flags to the pages:
        //   Supervisor: Only kernel-mode can access them
        //   Write Enabled: It can be both read from and written to
        //   Not Present: The page table is not present
        page_directory[i] = 0x00000002;
    }       
    
    //we will fill all 1024 entries in the table, mapping 4 megabytes
    for(i = 0; i < 1024; i++)
    {
        // As the address is page aligned, it will always leave 12 bits zeroed.
        // Those bits are used by the attributes ;)
        first_page_table[i] = (i * 0x1000) | 3; // attributes: supervisor level, read/write, present.
    }
    
    page_directory[0] = ((unsigned int)first_page_table) | 3;
    
    enablePaging(page_directory);
    
}

enablePaging函数将页面目录加载到cr3,然后通过在cr0中设置PG位来启用分页。

问题是在调用这个之后,如果我调用任何类似printk的东西,就会导致页面错误。我认为这是因为我没有身份页面内核或其他什么。在我的页面错误处理程序中,我将错误代码移动到eax,并检查qemu监视器中的寄存器。错误代码为0x00000020,即

0 1 0-监控过程试图写入不存在的页面条目。

TL;DR

在启用分页之后,我不能调用其他任何东西,需要映射我的内核吗?我该怎么做?还有什么不对劲的吗?

这是我在github:https://github.com/Danyy427/PagingOsdev上的代码

编辑:异常后的寄存器

我的异常处理程序:

代码语言:javascript
复制
void isr14_handler(interrupt_frame_t *frame)
{
    //panic("Page Fault");
    
    unsigned int err = frame->err_code;
    
    //asm(".intel_syntax noprefix");
    asm("mov %0, %%eax "::"r"(err));
    
    while(1);
}

我把恐慌排除在外,因为它会造成双重错误,导致三重错误。我把错误代码放入eax,代码挂起,这是我想要的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-09 08:47:43

我终于拿到了。我的内核有以下代码:

代码语言:javascript
复制
    initPaging();
    
    printk("Hello %d", 15) ;

启用分页之后,我尝试打印一些东西,并意识到printk抛出了一个页面错误。我转到printk代码,发现我正在访问0xFD000000,这是QEMU的帧缓冲区地址。但我没有绘制地图,所以程序试图访问一个未映射的位置。我编写了以下代码,它在我的initPaging函数中将0xFD000000映射到0x400000:

代码语言:javascript
复制
int from = 0x00000000, size = 0x400000,  zz = 0;
    for(; size>0; from += 4096, size -= 4096, zz++){
       first_page_table[zz] = from | 1;     // mark page present.
    }
    
    from = 0xFD000000;
    size = 0x400000;
    zz = 0;
    for(; size>0; from += 4096, size -= 4096, zz++){
       second_page_table[zz] = from | 1;     // mark page present.
    }
    
    vbemode.framebuffer = 0x400000;
    
    page_directory[0] = ((unsigned int)first_page_table) | 3;
    page_directory[1] = ((unsigned int)second_page_table) | 3;
    
    enablePaging(page_directory);

代码将从0x400000开始的4MB内存映射到0x800000 (希望如此)的物理地址0xFD000000,从而允许访问视频内存。

请随时指出我在代码中的错误。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67001152

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档