新闻中心

EEPW首页>嵌入式系统>设计应用> Arm Linux 内核页表的段式映射

Arm Linux 内核页表的段式映射

作者: 时间:2016-11-09 来源:网络 收藏
Linux启动之初,内核为自己建立的是段式内存映射,而不是页式映射。
映射表(PGD)从虚拟地址0xc0004000开始,每项4字节,每项对应1M内存空间,每项的高12位就是这1M内存的高12位地址。
一开始,内核不会为所有内存建立映射,只会映射必要的一部分,这部分代码在arch/ arm/kernel/head.S中由汇编代码完成。
以S3C6410为例,下面是在刚刚进入start_kernel()后打印出来的一段内核映射表。注意内核自身的映射表项是从0xc0007000地址开始。因为从0xc0004000开始的是整个4G空间的表,内核内存只占最高的那1G,所以要加一个偏移量:3G/1M * 4bytes = 0x3000。
c0007000: 0e 0c 00 50 0e 0c 10 50 0e 0c 20 50 00 00 00 00
c0007010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
c0007020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
c0007030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
由于字节序的原因,上面的每一个表项应该颠倒一下顺序来看,以第一项为例,应该是:
50 00 0c 0e
高12位地址是0x500,因为s3c6410的内存物理地址就是从0x50000000开始。
启动到C函数start_kernel()之后,在arch_setup()中会重写映射表,映射所有内存。这时的页表会如下所示:
c0007000: 0e 04 00 50 0e 04 10 50 0e 04 20 50 0e 04 30 50
c0007010: 0e 04 40 50 0e 04 50 50 0e 04 60 50 0e 04 70 50
c0007020: 0e 04 80 50 0e 04 90 50 0e 04 a0 50 0e 04 b0 50
c0007030: 0e 04 c0 50 0e 04 d0 50 0e 04 e0 50 0e 04 f0 50
......
注意,每一个表项的最后两个bit指明了映射方式,00表示 段式映射。在内存重新映射之后,这一映射方式并没有变化。
再来看一段应该程序的pgd表内容,这段内容是从其pgd表开始位置打印的,所以是为用户程序虚拟进程空间建立的映射:
c0d98000: 31 c8 d8 50 31 cc d8 50 00 00 00 00 00 00 00 00
c0d98010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
c0d98020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
c0d98030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
可以看到,表项最后两位是01,这已经是二级页式映射了。
这说明,尽管内核为应用程序建立的是二级粗粒度页式映射,但Linux内核自身一直是运行在段映射模式下。两种映射在同一张pgd表里面可以同时使用,映射方式不必全表统一。


评论


技术专区

关闭