本文主要是介绍初始化页表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
之前我们已经在内存中为页目录表预留了空间,现在我们将
初始化页目录表,页目录表一共有1024个表项。前768个表项为用户空间预留,
后面256个表项为内核空间预留,暂时只考虑映射4G空间。在内核空间中,在main函数中,
不能通过用户空间的页表访问内核,所以,之前在head.s中设置的映射内核空间的页目录表项
作废,重新设置。
end = (unsigned long)__va(max_low_pfn*PAGE_SIZE);
pgd_base = swapper_pg_dir;
i = __pgd_offset(PAGE_OFFSET);
设置内核起始虚拟地址
pgd = pgd_base + i;
从内核空间开始遍历页目录数组
for (; i < PTRS_PER_PGD; pgd++, i++) {
取虚拟地址
vaddr = i*PGDIR_SIZE;
if (end && (vaddr >= end))
break;
掠过中间页目录地址转换过程,我们只需要映射4G内存
pmd = (pmd_t *)pgd;
if (pmd != pmd_offset(pgd, 0))
BUG();
设置中间页目录表,我们只需要映射4G内存,因此,PTRS_PER_PMD为1,只有一个表项
for (j = 0; j < PTRS_PER_PMD; pmd++, j++) {
因为每张页表需要1页来存储,共1024项。为页表分配一页
pte_base = pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
for (k = 0; k < PTRS_PER_PTE; pte++, k++) {
为页表的首地址计算虚拟地址
vaddr = i*PGDIR_SIZE + j*PMD_SIZE + k*PAGE_SIZE;
if (end && (vaddr >= end))
break;
设置页表项,该页的属性:(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
*pte = mk_pte_phys(__pa(vaddr), PAGE_KERNEL);
}
set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte_base)));
if (pte_base != pte_offset(pmd, 0))
BUG();
}
这篇关于初始化页表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!