Motivation:当内核被解压到线性地址0x100000后,为了继续启动内核,即启动内核的第一个swapper进程,内核需要建立一张临时页表供其使用。
当内核从16位的实模式进入保护模式(通过在汇编代码中的setup函数中设置linux的cr0寄存器的PE位),内核要创建一个有限的地址空间,容纳内核的代码段、数据段、初始页表和用于存放动态数据结构的128KB大小的空间。程序设计者假定,内核使用的代码段、数据段、临时页表和128KB的内存范围可以全部存放到RAM的前8MB的空间内。于是我们需要做的工作就是建立一个页表映射使得可以对内存的前8MB的物理地址进行寻址。
进程的线性地址空间可分为两部分:
0x00000000~0xbfffffff (0~3G),无论进程运行于用户态还是内核态都可以访问的地址空间
0xc0000000~0xffffffff (3G~4G),只有处于内核态的进程才能访问该地址空间。
为了保证在实模式和保护模式下,进程都可以对这8MB的空间进行寻址,内核必须建立两个映射。将0x00000000~0x007fffff的线性地址和0xc0000000~0xc07fffff的线性地址都映射到0x00000000~的物理地址空间中。此时便可以通过与物理地址相同的线性地址或是通过从0xc0000000开始的8MB线性地址对RAM的前8MB进行寻址。
建立内核临时页表
采用二级页表的形式建立临时映射。由于要映射8MB的内核空间,一个页表有1024项,每一项页表对应一个4KB的页,8MB=2*1024*4KB,故需要两个全局页目录项和两张页表。
建立页全局目录项
一张页全局目录表有1024项,但我们只需要寻址8MB的地址空间,所以只需要2个页全局目录项即可。由于我们要同时保证进程处于用户空间和内核空间下都能对这8MB的内存空间进行寻址,所有我们需要4个页全局目录项分别寻址8MB的用户空间和8MB的内核空间。
要建立页全局目录表,首先要知道页全局目录表存放的物理地址,其中变量