最近做lazy lab做的有点头大,突然发现是自己遗漏了一些内容,即lec5,6,因为刚开始看的时候很多看不懂,就跑去看书了,后来就一直没有回来看lecture
所以为了提高效率,应该快速的把书看一遍,然后回来看lecture,再带着问题去看书看代码
code walk through
kvminit
void kvminit()
{
// 确定64bit的一级目录地址
kernel_pagetable = (pagetable_t) kalloc();
memset(kernel_pagetable, 0, PGSIZE);
// 一对一的IO映射 1 page
kvmmap(UART0, UART0, PGSIZE, PTE_R | PTE_W);
kvmmap(VIRTION(0), VIRTION(0), PGSIZE, PTE_R | PTE_W);
kvmmap(VIRTION(1), VIRTION(1), PGSIZE, PTE_R | PTE_W);
// CLINT 16 pages
kvmmap(CLINT, CLINT, 0x10000, PTE_R | PTE_W);
// PLIC 1024 pages
kvmmap(PLIC, PLIC, 0x400000, PTE_R | PTE_W);
// memlayout.h
// #define KERNBASE 0x80000000L
// #define PHYSTOP (KERNBASE + 128*1024*1024) 所以内核共映射了128M的内存
// #define TRAMPOLINE (MAXVA - PGSIZE)
// etext 在kernel.ld中,编译器根据代码量确定的对齐地址,ALGIN(0x1000),不懂意思
kvmmap(KERNBASE, KERNBASE, (uint64)etext-KERNBASE, PTE_R | PTE_X);
// 映射数据段和空闲内存
kvmmap((uint64)etext, (uint64)etext, PHYSTOP-(uint64)etext, PTE_R | PTE_W);
// 只有trampoline不是直接映射,实际的位置已经出现在代码段了,KERNBASE~etext。该段代码二次映射
kvmmap(TRAMPOLINE, (uint64)trampoline, PGSIZE, PTE_R | PTE_X);
}
kvmmap
直接调用了mappages(pagetable,va,size,pa,permission) , 而mappages是建立va~va+sz的pte:通过kalloc得到物理地址,然后设置pte
int
mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm)
{
uint64 a, last;
pte_t *pte;
a = PGROUNDDOWN(va);
last = PGROUNDDOWN(va + size - 1);
for(;;){
if((pte = walk(pagetable, a, 1)) == 0)
return -1;
if(*pte & PTE_V)
panic("remap");
*pte = PA2PTE(pa) | perm | PTE_V;
if(a == last)
break;
a += PGSIZE;
pa += PGSIZE;
}
return 0;
}
walk
其中walk通过虚拟地址,找到对应pte&