c-无法分页/访问2 MiB以上的内存.奥斯德夫



我正在尝试开发我的ow-os,我正在进行分页,突然决定切换到长模式。由于长模式需要对其他一切进行分页(打印到屏幕、中断、驱动程序等(,我从那里开始,我有一个页面帧分配器,它返回4 KiB的页面帧。在我的引导程序中,当切换到64位时,我标识映射前2个MIB以供内核使用。在我到达内核后,我标识映射相同的2个MiB,并尝试标识映射2个MiB以上的更多内存,但我无法映射,当我尝试写一个应该映射2个MiB以上的页面表时,它会出现三次错误。

这是我试图执行的代码:

long from = 0x00000, size = 0x400000,  zz = 0;

for(; size>0; from += 4096, size -= 4096, zz++)
{
//first_page_table[zz] = from | 1;     // mark page present.
map_page(kernelDirectory, from, from, 0x003);

}

这段代码试图从零开始映射4个MIB,它有三个错误。如果我将大小设置为0x200000或2 MiB,它将停止三次故障,即使我将大小设为0x201000,它也会发生三次故障。

这是映射函数:

void map_page(pml4_t *pml4, void * physaddr, unsigned long virtualaddr, unsigned int flags)
{
// Make sure that both addresses are page-aligned.
unsigned int pdindex;
unsigned int ptindex;
unsigned int pdptindex;
unsigned int pml4index;

virtualaddr >>= 12;
ptindex = virtualaddr & 0x1ff;
virtualaddr >>= 9;
pdindex = virtualaddr & 0x1ff;
virtualaddr >>= 9;
pdptindex = virtualaddr & 0x1ff;
virtualaddr >>= 9;
pml4index = virtualaddr & 0x1ff;


page_directory_pointer_table_t *pdpt;
if(pml4->entries[pml4index].present == 0)
{
pdpt = RequestPage();
memset(pdpt, 0, 4096);
pml4->entries[pml4index].present = 1;
pml4->entries[pml4index].writeable = 1;
pml4->entries[pml4index].address = ((unsigned long)pdpt >> 12);
}   
else
{

pdpt = (pml4->entries[pml4index].address << 12);
}

page_directory_t *directory;
if(pdpt->entries[pdptindex].present == 0)
{
directory = RequestPage();
memset(directory, 0, 4096);
pdpt->entries[pdptindex].present = 1;
pdpt->entries[pdptindex].writeable = 1;
pdpt->entries[pdptindex].address = ((unsigned long)directory >> 12);
}   
else
{

directory = (pdpt->entries[pdindex].address << 12);
}


page_table_t *pt;
if(directory->entries[pdindex].present == 0)
{
pt = RequestPage();
//memset(pt, 0, 4096);
directory->entries[pdindex].present = 1;
directory->entries[pdindex].writeable = 1;
directory->entries[pdindex].address = ((unsigned long)pt >> 12);
}   
else
{

pt = (directory->entries[pdindex].address << 12);
}



pt->entries[ptindex].present = flags & 1;                 
pt->entries[ptindex].writeable = (flags & 2) >> 1;               
pt->entries[ptindex].user_access = (flags & 4) >> 2;         
pt->entries[ptindex].write_through = (flags & 8) >> 3;          
pt->entries[ptindex].cache_disabled = (flags & 16) >> 4;           // 000
pt->entries[ptindex].accessed = (flags & 32) >> 5;               // 0000 0000 0000
pt->entries[ptindex].dirty = (flags & 64) >> 6;                
pt->entries[ptindex].zero = 0;                
pt->entries[ptindex].global = (flags & 256) >> 8;           
pt->entries[ptindex].ignored_2 = 0b000; 
pt->entries[ptindex].address = ((unsigned long)physaddr >> 12);



__native_flush_tlb_single((unsigned long)pt->entries[ptindex].address << 12);

}

以下是整个github回购:https://github.com/Danyy427/OSDEV5

这些功能位于源/内核/内存/分页/分页.c 下

您可能还需要查看source/kernel/bitmap/bitmap.h和bitmap.c

帧分配器位于source/kernel/memory/pmm.c和pmm.h

提前谢谢!

page_directory_t *directory;
if(pdpt->entries[pdptindex].present == 0)
{
/* omit */
}   
else
{

directory = (pdpt->entries[pdindex].address << 12);
}

在这里,您检查的是pdpt->entries[pdptindex]的存在,但随后从pdpt->entries[pdindex]检索地址。看起来您还应该使用pdpt->entries[pdptindex]来检索地址。

最新更新