继续回到KPTphys(0x1000000)之后的页表区域。再分配一个页表条目给cpu0pp指向的
1个页面的区域(0x1025000),属性为读写。
0x1000000 : 0x00000003 0x00001003 0x00002003 0x00003003
0x1000010 : 0x00004003 0x00005003 0x00006003 0x00007003
......
0x1003fe0 : 0x00ff8003 0x00ff9003 0x00ffa003 0x00ffb003
0x1003ff0 : 0x00ffc003 0x00ffd003 0x00ffe003 0x00fff003
0x1004000 : 0x00000000 0x00000000 0x00000000 0x00000000
0x1004010 : 0x00000000 0x00000000 0x00000000 0x00000000
0x1004020 : 0x00000000 0x00000000 0x00000000 0x00000000
0x1004030 : 0x00000000 0x00000000 0x00000000 0x00000000
0x1004040 : 0x00000000 0x00000000 0x00000000 0x00000000
0x1004050 : 0x00000000 0x00000000 0x00000000 0x00000000
0x1004060 : 0x00000000 0x00000000 0x00000000 0x00000000
0x1004070 : 0x00000000 0x00000000 0x0101e003 0x0101f003
0x1004080 : 0x01020003 0x01021003 0x01022003 0x01023003
0x1004090 : 0x01024003 0x01025003
863 /* Map SMP page table page into global kmem FWIW */
864 movl R(SMPptpa), %eax
865 movl $1, %ecx
866 fillkptphys($PG_RW)
再分配一个页表条目给SMPptpa指向的1个页面的区域(0x1026000),属性为读写。
0x1000000 : 0x00000003 0x00001003 0x00002003 0x00003003
0x1000010 : 0x00004003 0x00005003 0x00006003 0x00007003
......
0x1003fe0 : 0x00ff8003 0x00ff9003 0x00ffa003 0x00ffb003
0x1003ff0 : 0x00ffc003 0x00ffd003 0x00ffe003 0x00fff003
0x1004000 : 0x00000000 0x00000000 0x00000000 0x00000000
0x1004010 : 0x00000000 0x00000000 0x00000000 0x00000000
0x1004020 : 0x00000000 0x00000000 0x00000000 0x00000000
0x1004030 : 0x00000000 0x00000000 0x00000000 0x00000000
0x1004040 : 0x00000000 0x00000000 0x00000000 0x00000000
0x1004050 : 0x00000000 0x00000000 0x00000000 0x00000000
0x1004060 : 0x00000000 0x00000000 0x00000000 0x00000000
0x1004070 : 0x00000000 0x00000000 0x0101e003 0x0101f003
0x1004080 : 0x01020003 0x01021003 0x01022003 0x01023003
0x1004090 : 0x01024003 0x01025003 0x01026003
868 /* Map the private page into the SMP page table */
869 movl R(cpu0pp), %eax
870 movl $0, %ebx /* pte offset = 0 */
871 movl $1, %ecx /* one private page coming right up */
872 fillkpt(R(SMPptpa), $PG_RW)
在SMPptpa(0x1026000)页面中分配一个页表条目来映射cpu0pp(0x1025000)指向的页面,
属性为读写。
0x1026000 : 0x01025003 0x00000000 0x00000000 0x00000000
874 /* ... and put the page table table in the pde. */
875 movl R(SMPptpa), %eax
876 movl $MPPTDI, %ebx
877 movl $1, %ecx
878 fillkpt(R(IdlePTD), $PG_RW)
在IdlePTD指向的页表页面目录中创建一条页表目录项来指向SMPptpa指向的SMP页表页面。
MPPTDI定义为1023,表示最后一个页表目录项。属性为读写。我们可以看到,页表目录页面
的其它页表目录项的内容到此时仍然为空。
0x101e000 : 0x00000000 0x00000000 0x00000000 0x00000000
0x101e010 : 0x00000000 0x00000000 0x00000000 0x00000000
......
0x101efe0 : 0x00000000 0x00000000 0x00000000 0x00000000
0x101eff0 : 0x00000000 0x00000000 0x00000000 0x01026003
880 /* Fakeup VA for the local apic to allow early traps. */
881 ALLOCPAGES(1)
882 movl %esi, %eax
883 movl $(NPTEPG-1), %ebx /* pte offset = NTEPG-1 */
884 movl $1, %ecx /* one private pt coming right up */
885 fillkpt(R(SMPptpa), $PG_RW)
再分配一个页面,此时physfree指向0x1028000。将SMPptpa(0x1026000)页面中的最后
一个条目用来映射这个新分配的页面,属性为读写。
0x1026000 : 0x01025003 0x00000000 0x00000000 0x00000000
0x1026010 : 0x00000000 0x00000000 0x00000000 0x00000000
......
0x1026fe0 : 0x00000000 0x00000000 0x00000000 0x00000000
0x1026ff0 : 0x00000000 0x00000000 0x00000000 0x01027003
888 /*
889 * Create an identity mapping for low physical memory, including the kernel.
890 * The part of this mapping that covers the first 1 MB of physical memory
891 * becomes a permanent part of the kernel's address space. The rest of this
892 * mapping is destroyed in pmap_bootstrap(). Ordinarily, the same page table
893 * pages are shared by the identity mapping and the kernel's native mapping.
894 * However, the permanent identity mapping cannot contain PG_G mappings.
895 * Thus, if the kernel is loaded within the permanent identity mapping, that
896 * page table page must be duplicated and not shared.
897 *
898 * N.B. Due to errata concerning large pages and physical address zero,
899 * a PG_PS mapping is not used.
900 */
901 movl R(KPTphys), %eax
902 xorl %ebx, %ebx
903 movl $NKPT, %ecx
904 fillkpt(R(IdlePTD), $PG_RW)
将IdlePTD(0x101e000)页面中的前NKPT(30)个条目用来映射KPTphys(0x1000000)
指向的30个页面的空间,属性为读写。
0x101e000 : 0x01000003 0x01001003 0x01002003 0x01003003
0x101e010 : 0x01004003 0x01005003 0x01006003 0x01007003
0x101e020 : 0x01008003 0x01009003 0x0100a003 0x0100b003
0x101e030 : 0x0100c003 0x0100d003 0x0100e003 0x0100f003
0x101e040 : 0x01010003 0x01011003 0x01012003 0x01013003
0x101e050 : 0x01014003 0x01015003 0x01016003 0x01017003
0x101e060 : 0x01018003 0x01019003 0x0101a003 0x0101b003
0x101e070 : 0x0101c003 0x0101d003 0x00000000 0x00000000
0x101e080 : 0x00000000 0x00000000 0x00000000 0x00000000
......
0x101efe0 : 0x00000000 0x00000000 0x00000000 0x00000000
0x101eff0 : 0x00000000 0x00000000 0x00000000 0x01026003
920 /*
921 * For the non-PSE case, install PDEs for PTs covering the KVA.
922 * For the PSE case, do the same, but clobber the ones corresponding
923 * to the kernel (from btext to KERNend) with 4M (2M for PAE) ('PS')
924 * PDEs immediately after.
925 */
926 movl R(KPTphys), %eax
927 movl $KPTDI, %ebx
928 movl $NKPT, %ecx
929 fillkpt(R(IdlePTD), $PG_RW)
930 cmpl $0,R(pseflag)
931 je done_pde
KPTDI定义为第一个内核页表目录的索引,即768。926到929行将IdlePTD(0x101e000)
页面中的第768项之后的30个页表目录项用来指向KPTphys(0x1000000)指向的30个
页面空间,属性为读写。
0x101e000 : 0x01000003 0x01001003 0x01002003 0x01003003
0x101e010 : 0x01004003 0x01005003 0x01006003 0x01007003
0x101e020 : 0x01008003 0x01009003 0x0100a003 0x0100b003
0x101e030 : 0x0100c003 0x0100d003 0x0100e003 0x0100f003
0x101e040 : 0x01010003 0x01011003 0x01012003 0x01013003
0x101e050 : 0x01014003 0x01015003 0x01016003 0x01017003
0x101e060 : 0x01018003 0x01019003 0x0101a003 0x0101b003
0x101e070 : 0x0101c003 0x0101d003 0x00000000 0x00000000
0x101e080 : 0x00000000 0x00000000 0x00000000 0x00000000
......
0x101ebf0 : 0x00000000 0x00000000 0x00000000 0x00000000
0x101ec00 : 0x01000003 0x01001003 0x01002003 0x01003003
0x101ec10 : 0x01004003 0x01005003 0x01006003 0x01007003
0x101ec20 : 0x01008003 0x01009003 0x0100a003 0x0100b003
0x101ec30 : 0x0100c003 0x0100d003 0x0100e003 0x0100f003
0x101ec40 : 0x01010003 0x01011003 0x01012003 0x01013003
0x101ec50 : 0x01014003 0x01015003 0x01016003 0x01017003
0x101ec60 : 0x01018003 0x01019003 0x0101a003 0x0101b003
0x101ec70 : 0x0101c003 0x0101d003 0x00000000 0x00000000
0x101ec80 : 0x00000000 0x00000000 0x00000000 0x00000000
......
0x101efe0 : 0x00000000 0x00000000 0x00000000 0x00000000
0x101eff0 : 0x00000000 0x00000000 0x00000000 0x01026003
930 cmpl $0,R(pseflag)
931 je done_pde
若全局变量pseflag为0,则跳转至done_pde,示例中此变量为1。
933 movl R(KERNend), %ecx
934 movl $KERNLOAD, %eax
935 subl %eax, %ecx
936 shrl $PDRSHIFT, %ecx
937 movl $(KPTDI+(KERNLOAD/(1 << PDRSHIFT))), %ebx
938 shll $PDESHIFT, %ebx
939 addl R(IdlePTD), %ebx
940 orl $(PG_V|PG_RW|PG_PS), %eax
941 1: movl %eax, (%ebx)
942 addl $(1 << PDRSHIFT), %eax
943 addl $PDESIZE, %ebx
944 loop 1b
933行将KERNend(0x1000000)写入ecx。934行将KERNLOAD(0x400000)写入eax。
935行从ecx中减去eax,得到0xc00000。936行将ecx右移22比特,得到3。
937行,(KERNLOAD/(1 << PDRSHIFT))表示KRENLOAD中有多少个4M(占用了多少个
页表目录项),因为KERNLOAD就是4M,因此这个计算为1,最终写入ebx的值是769。
938行,PDESHIFT定义为2,将ebx左移2比特之后得到的就是第769个页表目录项在
页表目录页面中的偏移地址。939行将ebx加上页表目录页面的基地址
IdlePTD(0x101e000)之后得到第769个页表目录项的地址0x101ec04。940行,
在eax中构造第769个页表目录项的内容,在已有的KERNLOAD地址的基础上,
再加上属性PG_V|PG_RW|PG_PS(0x83),表示当前在物理内存中、可读写、页面
尺寸为4M。941到944行,将eax中构造好的第769、770、771个页表目录项写入ebx
中的指定位置。
0x101e000 : 0x01000003 0x01001003 0x01002003 0x01003003
0x101e010 : 0x01004003 0x01005003 0x01006003 0x01007003
0x101e020 : 0x01008003 0x01009003 0x0100a003 0x0100b003
0x101e030 : 0x0100c003 0x0100d003 0x0100e003 0x0100f003
0x101e040 : 0x01010003 0x01011003 0x01012003 0x01013003
0x101e050 : 0x01014003 0x01015003 0x01016003 0x01017003
0x101e060 : 0x01018003 0x01019003 0x0101a003 0x0101b003
0x101e070 : 0x0101c003 0x0101d003 0x00000000 0x00000000
0x101e080 : 0x00000000 0x00000000 0x00000000 0x00000000
......
0x101ebf0 : 0x00000000 0x00000000 0x00000000 0x00000000
0x101ec00 : 0x01000003 0x00400083 0x00800083 0x00c00083
0x101ec10 : 0x01004003 0x01005003 0x01006003 0x01007003
0x101ec20 : 0x01008003 0x01009003 0x0100a003 0x0100b003
0x101ec30 : 0x0100c003 0x0100d003 0x0100e003 0x0100f003
0x101ec40 : 0x01010003 0x01011003 0x01012003 0x01013003
0x101ec50 : 0x01014003 0x01015003 0x01016003 0x01017003
0x101ec60 : 0x01018003 0x01019003 0x0101a003 0x0101b003
0x101ec70 : 0x0101c003 0x0101d003 0x00000000 0x00000000
0x101ec80 : 0x00000000 0x00000000 0x00000000 0x00000000
......
0x101efe0 : 0x00000000 0x00000000 0x00000000 0x00000000
0x101eff0 : 0x00000000 0x00000000 0x00000000 0x01026003
946 done_pde:
947 /* install a pde recursively mapping page directory as a page table */
948 movl R(IdlePTD), %eax
949 movl $PTDPTDI, %ebx
950 movl $NPGPTD,%ecx
951 fillkpt(R(IdlePTD), $PG_RW)
将IdlePTD(0x101e000)页面中的第PTDPTDI(767)个页表目录项指向IdelPTD页面,
属性为读写。
0x101e000 : 0x01000003 0x01001003 0x01002003 0x01003003
0x101e010 : 0x01004003 0x01005003 0x01006003 0x01007003
0x101e020 : 0x01008003 0x01009003 0x0100a003 0x0100b003
0x101e030 : 0x0100c003 0x0100d003 0x0100e003 0x0100f003
0x101e040 : 0x01010003 0x01011003 0x01012003 0x01013003
0x101e050 : 0x01014003 0x01015003 0x01016003 0x01017003
0x101e060 : 0x01018003 0x01019003 0x0101a003 0x0101b003
0x101e070 : 0x0101c003 0x0101d003 0x00000000 0x00000000
0x101e080 : 0x00000000 0x00000000 0x00000000 0x00000000
......
0x101ebe0 : 0x00000000 0x00000000 0x00000000 0x00000000
0x101ebf0 : 0x00000000 0x00000000 0x00000000 0x0101e003
0x101ec00 : 0x01000003 0x00400083 0x00800083 0x00c00083
0x101ec10 : 0x01004003 0x01005003 0x01006003 0x01007003
0x101ec20 : 0x01008003 0x01009003 0x0100a003 0x0100b003
0x101ec30 : 0x0100c003 0x0100d003 0x0100e003 0x0100f003
0x101ec40 : 0x01010003 0x01011003 0x01012003 0x01013003
0x101ec50 : 0x01014003 0x01015003 0x01016003 0x01017003
0x101ec60 : 0x01018003 0x01019003 0x0101a003 0x0101b003
0x101ec70 : 0x0101c003 0x0101d003 0x00000000 0x00000000
0x101ec80 : 0x00000000 0x00000000 0x00000000 0x00000000
......
0x101efe0 : 0x00000000 0x00000000 0x00000000 0x00000000
0x101eff0 : 0x00000000 0x00000000 0x00000000 0x01026003
960 ret
返回到btex主流程中。
