- 论坛徽章:
- 0
|
今天跟哥们说起Linux的高端内存(high memory)的问题,我解释为什么FreeBSD在i386下没有这个问题,一时没有想清楚,也不记得哪里有文档了,就在这里解释一下吧 
首先看接口,关于映射,抽象出了三个数组,在sys/i386/include/pmap.h
- extern pt_entry_t PTmap[];
- extern pd_entry_t PTD[];
- extern pd_entry_t PTDpde[];
复制代码
pt_entry_t 简单的说就是 page table entry, pd_entry_t 就是page directory entry
PTmap的含义是一个数组,这个数组中包含了映射任意虚拟地址的page table entry.
PTD的含义是一个数组,它包含了映射任意虚拟地址的page directory entry
PTDpde的含义是
看两个物理地址与虚拟地址转换的宏,同一个文件
- #define vtopte(va) (PTmap + i386_btop(va))
- #define vtophys(va) pmap_kextract((vm_offset_t)(va))
- static __inline vm_paddr_t
- pmap_kextract(vm_offset_t va)
- {
- vm_paddr_t pa;
-
- /*
- * 首先找到映射这个虚拟地址的page directory 看看是否起用了PSE(超级页, 4M大小的页)
- */
-
- if ((pa = PTD[va >> PDRSHIFT]) & PG_PS) {
- pa = (pa & PG_PS_FRAME) | (va & PDRMASK);
- } else {
- /*
- * 没有启用PSE那么找到映射这个虚拟地址的page table entry读出其内容,就是映射
- * 这个虚拟地址的物理地址
- */
- pa = *vtopte(va);
- pa = (pa & PG_FRAME) | (va & PAGE_MASK);
- }
- return pa;
- }
-
复制代码
i386_btop 就是 byte to page把字节数转换为页数。
现在我们看这些数组的实现, i386/i386/locore.s
- .globl PTmap,PTD,PTDpde
- .set PTmap,(PTDPTDI << PDRSHIFT)
- .set PTD,PTmap + (PTDPTDI * PAGE_SIZE)
- .set PTDpde,PTD + (PTDPTDI * PDESIZE)
- /* .................................... */
- /*
- * fillkpt
- * eax = page frame address
- * ebx = index into page table
- * ecx = how many pages to map
- * base = base address of page dir/table
- * prot = protection bits
- */
- /* install a pde recursively mapping page directory as a page table */
- movl R(IdlePTD), %eax
- movl $PTDPTDI, %ebx
- movl $NPGPTD,%ecx
- fillkpt(R(IdlePTD), $PG_RW)
复制代码
set 就是给一些符号赋值,跟define的感觉差不多,具体可以看info as
PTDPTDI 一个小于1024的正整数,可以忽略具体数值, PDRSHIFT是page directory shift 就是22
我们看一下这个页表的结构,假设这个页表的物理地址是A,那么
0 1 2...PTDPTDI.......
[-][-][-]...[A]............[-]
‘-‘是我们不关心的内容
OK,事实只有这些,剩下的是我们的理解了 这里每个page table entry的大小是4,每个page directory entry的大小是4
先看看vtopte是怎么回事, 根据上面的一系列的set,我们知道PTmap事实上是 (PTDPTDI << 22),
假设va的最高十位得值是v1, 第二个十位的值是v2,最后的12位对寻找pte没有影响,我们忽略,那么实际的page directory
entry是在第v1项(假设内容是B),实际的page table entry是在B所指向的page table的v2项, 也就是说实际page table
entry的物理地址是 (B & PAGEMASK) + v2 * 4
i386_btop(va) = va >> 12
PTmap + i386_btop(va) = (void*)(PTmap + (va >> 12) * x) = (void*)((PTDPTDI << 22) + (va >> 12) * 4)
现在这个地址的结构, 最高十位是PTDPTDI,第二个十位是v1,最后的12位是v2 * 4
处理器要访问这个地址,那么首先要通过mmu找到其物理地址,怎么转换呢,首先用这个地址的高10位在页表找page directory entry
而这个高十位就是PTDPTDI,而在PTDPTDI这个位置找到page directory entry指向了A(也就是页表自身)然后用第二个十位也就是v1
检索page table entry,这时候得到的值是B然后处理器知道这个虚拟地址最终所对应的物理地址是 (B & PAGEMASK) + v2 * 4
PTD是同样的道理,我就不啰嗦了。 |
评分
-
查看全部评分
|