之前我们已经在内存中为页目录表预留了空间,现在我们将
初始化页目录表,页目录表一共有1024个表项。前768个表项为用户空间预留,
后面256个表项为内核空间预留,暂时只考虑映射4G空间。在内核空间中,在main函数中,
不能通过用户空间的页表访问内核,所以,之前在head.s中设置的映射内核空间的页目录表项
作废,重新设置。
将物理地址896M转化成虚拟地址
end = (unsigned long)__va(max_low_pfn*PAGE_SIZE);
之前已经设置好了页目录表,在物理地址0x101000处
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();
}
}
初始化页表
最新推荐文章于 2023-10-24 16:06:46 发布