微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Arm Linux 内核页表的段式映射

Arm Linux 内核页表的段式映射

时间: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 5000 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

由于字节序的原因,上面的每一个表项应该颠倒一下顺序来看,以第一项为例,应该是:

50000c0e

高12位地址是0x500,因为s3c6410的内存物理地址就是从0x50000000开始。

启动到C函数start_kernel()之后,在arch_setup()中会重写映射表,映射所有内存。这时的页表会如下所示:

c0007000:0e 04 00 500e 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 5031 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表里面可以同时使用,映射方式不必全表统一。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top