一、64位虚拟地址划分
假设页的大小是16K,即PAGE_SHIFT = 14
PGD 含有2K项,每一项占8个字节,总共16K(一页)
VA[46:36] 索引PGD,低3位置0,意在以8字节为单位索引PGD。用于索引PGD的VA 的位数
正好为11位,与每页容纳的PGD 项相对应。
PMD 含有2K项,每一项占8个字节,总共16K(一页)
PMD 类似,使用 VA[35:25],11位索引 PMD。
PTE 含有2K项,每一项占8个字节,总共16K(一页)
PTE 则要注意,其使用 VA[24:15],10位索引 PTE,只因为每次要取2项共16个字节,因此要忽略
VA[14],故而其低4位要为0。虽然使用10位索引,但其以16字节为单位,则实际的索引项数仍然为
2^11。
余下的 VA[13:0] 正好是页内位移
二、tlbrefill 代码分析
汇编代码: C代码:
build_get_pmde64函数中有如下代码:
0:00403a40 dmfc0 k0,$8 #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
____long pgdc = (long)pgd_current;
#endif
4:17004007 bltz k0,0x64
8:4e801b3c lui k1,0x804e ____UASM_i_LA_mostly(p, ptr, pgdc);
c:00407bdf ld k1,16384(k1) ____uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
10:7ed01a00 dsrl32 k0,k0,0x1 ____uasm_i_dsrl_safe(p, tmp, tmp, PGDIR_SHIFT - 3);
14:f83f5a33 andi k0,k0,0x3ff8 ____uasm_i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3);
18:2dd87a03 daddu k1,k1,k0 ____uasm_i_daddu(p, ptr, ptr, tmp);
#ifndef __PAGETABLE_PMD_FOLDED
1c:00403a40 dmfc0 k0,$8 ____uasm_i_dmfc0(p, tmp, C0_BADVADDR);
20:00007bdf ld k1,0(k1) ____uasm_i_ld(p, ptr, 0, ptr);
24:bad51a00 dsrl k0,k0,0x16 ____uasm_i_dsrl_safe(p, tmp, tmp, PMD_SHIFT-3);
28:f83f5a33 andi k0,k0,0x3ff8 ____uasm_i_andi(p, tmp, tmp, (PTRS_PER_PMD - 1)<<3);
2c: 2dd87a03 daddu k1,k1,k0 ____uasm_i_daddu(p, ptr, ptr, tmp);
#endif
在build_get_ptep函数中
30: 00a03a40 dmfc0 k0,$20 GET_CONTEXT(p, tmp);
34: 00007bdf ld k1,0(k1) UASM_i_LW(p, ptr, 0, ptr);
38: bad01a00 dsrl k0,k0,0x2 build_adjust_context(p, tmp);
3c: f03f5a33 andi k0,k0,0x3ff0
40: 2dd87a03 daddu k1,k1,k0 UASM_i_ADDU(p, ptr, ptr, tmp);
在函数build_update_entries中
44:00007adf ld k0,0(k1) uasm_i_ld(p, tmp, 0, ptep);
48:08007bdf ld k1,8(k1) uasm_i_ld(p, ptep, sizeof(pte_t), ptep);
4c:bad11a00 dsrl k0,k0,0x6 uasm_i_dsrl_safe(p, tmp, tmp, ilog2(_PAGE_GLOBAL));
50:00109a40 mtc0 k0,$2 UASM_i_MTC0(p, tmp, C0_ENTRYLO0);
54:bad91b00 dsrl k1,k1,0x6 uasm_i_dsrl_safe(p, ptep, ptep, ilog2(_PAGE_GLOBAL));
58:00189b40 mtc0 k1,$3 UASM_i_MTC0(p, ptep, C0_ENTRYLO1);
5c:06000042 tlbwr
60:18000042 eret
64: b8d81a00 dsll k1,k0,0x2
68: 04006107 bgez k1,0x7c
6c: 00c01b3c lui k1,0xc000
70: 2fd05b03 dsubu k0,k0,k1
74: e6ff0010 b 0x10
78: 4d801b3c lui k1,0x804d
7c: 3cd81b00 dsll32 k1,k1,0x0
80: 2fd05b03 dsubu k0,k0,k1
84: e2ff0010 b 0x10
88: 4e801b3c lui k1,0x804e
三、几点说明
1、以上代码可以看错是页表应用的最好的例子,即读页表来填充tlb,此时页表已经被填充好了,填充的内容是虚拟地址。
2、pgd_current是一个保存页全局目录变量地址的全局数组,数组的个数是cpu数,在per_cpu_trap_init函数在调用TLBMISS_HANDLER_SETUP将swapper_pg_dir赋值给pgd_current[i]
阅读(3297) | 评论(0) | 转发(0) |