Content #
//代码路径:boot/head.s
.align 2
setup_paging:
movl $1024*5,%ecx /* 5 pages - pg_dir + 4 page tables */
xorl %eax,%eax
xorl %edi,%edi /* pg_dir is at 0x000 */
cld;rep;stosl
/*下面几行中的7应看成二进制的111,是页属性,代表u/s、r/w、present,
111代表:用户u、读写rw、存在p,000代表:内核s、只读r、不存在 */
movl $pg0 + 7,_pg_dir /* set present bit/user r/w */
movl $pg1 + 7,_pg_dir + 4 /* --------- " " --------- */
movl $pg2 + 7,_pg_dir + 8 /* --------- " " --------- */
movl $pg3 + 7,_pg_dir + 12 /* --------- " " --------- */
movl $pg3 + 4092,%edi
movl $0xfff007,%eax /* 16Mb -4096 + 7 (r/w user,p) */
std
1: stosl /* fill pages backwards-more efficient :-) */
subl $0x1000,%eax
jge 1b
…
这些工作完成后,内存中的布局如 内存结构图(head.s执行后)所示。可以看出,只有184字节的剩余代码。
PG(Paging)标志:CR0寄存器的第31位,分页机制控制位。当CPU的控制寄存器 CR0第0位PE(保护模式)置为1时,可设置PG位为开启。当开启后,地址映射模式采取分页机制。当CPU的控制寄存器CR0第0位PE(保护模式)置为0时,设置PG 位将引起CPU发生异常。
CR3寄存器:3号32位控制寄存器,其高20位存放页目录表的基地址。当CR0中的 PG标志置位时,CPU使用CR3指向的页目录表和页表进行虚拟地址到物理地址的映射。
执行代码如下:
//代码路径:boot/head.s
…
xorl %eax,%eax /* pg_dir is at 0x0000 */
movl %eax,%cr3 /* cr3-page directory start */
movl %cr0,%eax
orl $0x80000000,%eax
movl %eax,%cr0 /* set paging (PG) bit */
…
前两行代码的动作是将CR3指向页目录表,意味着操作系统认定0x0000这个位置就是页目录表的起始位置;后3行代码的动作是启动分页机制开关PG标志置位,以启用分页寻址模式。两个动作一气呵成。
From #
Linux内核设计的艺术