初始化内核地址空间
Exercise 5
Fill in the missing code in mem_init() after the call to check_page().
Your code should now pass the check_kern_pgdir() and check_page_installed_pgdir() checks.
错误
kernel panic at kern/pmap.c:787: assertion failed: check_va2pa(pgdir, KERNBASE + i) == i
实际卡在以下语句下,
// check phys mem
for (i = 0; i < npages * PGSIZE; i += PGSIZE)
assert(check_va2pa(pgdir, KERNBASE + i) == i);
发现其以npages * PGSIZE为检查边界,修改KERNBASE以上内存的映射代码为
boot_map_region(kern_pgdir,
KERNBASE,
npages * PGSIZE,
0,
PTE_W );
又出现了以下错误:
kernel panic at kern/pmap.c:804: assertion failed: pgdir[i] & PTE_P
.
调试发现,页目录表中的页目录项,960-991索引项都通过assert
,错误发生在992项处,即992项无效。(991-960+1)*2^10 = 2^15 = 32768. 刚好等于npages的值。
感觉是npages
与 0xFFFFFFFF-KERNBASE
不一致导致的。打印npages =32768
, (0xFFFFFFFF-KERNBASE)/PGSIZE
向上取整= 65536页。很明显用npages映射的内存远远没有后一种方法多,所以出现第二种错误很正常,但是第一种错误为什么会出现呢?
继续改为出现第一种错误的写法,通过调试发现,在 i=0时就出错了,证明KERNBASE根本就没有映射到物理地址0处。
根本没有道理啊,第二种能映射成功,证明是没有问题的呀。而且之前的两次boot_map_region
都没有问题, 应该是第三次的size= 268435456
过大导致boot_map_region()
出现了Bug。
最初写法,发现用va+size
会出现溢出的情况,比如当前情况,size=268435456=0x10000000
, va=0xF0000000
, 两者相加直接等于0了。 所以当我们用第二种npage*PGSIZE
时能成功初始化一部分映射。
并且,当我们直接给size
传入0xFFFFFFFF-KERNBASE
即等于0xFFF_FFFF
,其与va相加为0xFFFF_FFFF
, 就会出现死循环。因为pva从0xF000_0000
开始增长,最大只能为0xFFFF_F000
,永远不会有大于等于va+size
的时候。
static void
boot_map_region(pde_