Linux页表机制分析Word文档格式.docx
- 文档编号:17804067
- 上传时间:2022-12-10
- 格式:DOCX
- 页数:30
- 大小:261.74KB
Linux页表机制分析Word文档格式.docx
《Linux页表机制分析Word文档格式.docx》由会员分享,可在线阅读,更多相关《Linux页表机制分析Word文档格式.docx(30页珍藏版)》请在冰豆网上搜索。
但是由于每一个用户进程都有自己的独立空间,所以每一个进程都需要一个1M的内存来存储页表信息,这依然是对系统内存的浪费,采用两级甚至多级分页是一种不错的解决方案。
另外有些处理器采用64位体系架构,此时两级也不合适了,所以Linux使用三级页表。
∙页全局目录(PageGlobalDirectory),即pgd,是多级页表的抽象最高层。
每一级的页表都处理不同大小的内存。
每项都指向一个更小目录的低级表,因此pgd就是一个页表目录。
当代码遍历这个结构时(有些驱动程序就要这样做),就称为是在遍历页表。
∙页中间目录(PageMiddleDirectory),即pmd,是页表的中间层。
在x86架构上,pmd在硬件中并不存在,但是在内核代码中它是与pgd合并在一起的。
∙页表条目(PageTableEntry),即pte,是页表的最低层,它直接处理页,该值包含某页的物理地址,还包含了说明该条目是否有效及相关页是否在物理内存中的位。
12.2.
一级页表
三级页表由不同的的数据结构表示,它们分别是pgd_t,pmd_t和pte_t。
注意到它们均被定义为unsignedlong类型,也即大小为4bytes,32bits。
arch/arm/include/asm/page.h
typedefunsignedlongpte_t;
typedefunsignedlongpmd_t;
typedefunsignedlongpgd_t[2];
typedefunsignedlongpgprot_t;
以下是页表操作相关的宏定义。
#definepte_val(x)(x)
#definepmd_val(x)(x)
#definepgd_val(x)((x)[0])
#definepgprot_val(x)(x)
#define__pte(x)(x)
#define__pmd(x)(x)
#define__pgprot(x)(x)
任何一个用户进程都有自己的页表,与此同时,内核本身就是一个名为init_task的0号进程,每一个进程都有一个mm_struct结构管理进程的内存空间,init_mm是内核的mm_struct。
在系统引导阶段,首先通过__create_page_tables在内核代码的起始处_stext向低地址方向预留16K,用于一级页表(主内存页表)的存放,每个进程的页表都通过mm_struct中的pgd描述符进行引用。
内核页表被定义在swapper_pg_dir。
arch/arm/kernel/init_task.c
#defineINIT_MM(name)\
{\
.mm_rb=RB_ROOT,\
.pgd=swapper_pg_dir,\
.mm_users=ATOMIC_INIT
(2),\
.mm_count=ATOMIC_INIT
(1),\
.mmap_sem=__RWSEM_INITIALIZER(name.mmap_sem),\
.page_table_lock=__SPIN_LOCK_UNLOCKED(name.page_table_lock),\
.mmlist=LIST_HEAD_INIT(name.mmlist),\
.cpu_vm_mask=CPU_MASK_ALL,\
}
structmm_structinit_mm=INIT_MM(init_mm);
swapper_pg_dir在head.S中被定义为PAGE_OFFSET向上偏移TEXT_OFFSET。
TEXT_OFFSET代表内核代码段的相对于PAGE_OFFSET的偏移。
KERNEL_RAM_VADDR的值与_stext的值相同,代表了内核代码的起始地址。
swapper_pg_dir为KERNEL_RAM_VADDR-0x4000,也即向低地址方向偏移了16K。
arch/arm/Makefile
textofs-y:
=0x00008000
......
TEXT_OFFSET:
=$(textofs-y)
特定系统架构的Makefile中通过textofs-y定义了内核起始代码相对于PAGE_OFFSET的偏移。
arch/arm/kernel/head.S
#defineKERNEL_RAM_VADDR(PAGE_OFFSET+TEXT_OFFSET)
.globlswapper_pg_dir
.equswapper_pg_dir,KERNEL_RAM_VADDR-0x4000
ARMLinux中的主内存页表,使用段表。
每个页表映射1M的内存大小,由于16K/4*1M=4G,这16K的主页表空间正好映射4G的虚拟空间。
内核页表机制在系统启动过程中的paging_init函数中使能,其中对内核主页表的初始化等操作均是通过init_mm.pgd的引用来进行的。
在系统执行paging_init之前,系统的地址空间如下图所示:
61.
内核RAM布局
图中的黄色部分就是内核0号进程的主页表。
arch/arm/mm/mmu.c
void__initpaging_init(structmeminfo*mi,structmachine_desc*mdesc)
{
void*zero_page;
build_mem_type_table();
sanity_check_meminfo(mi);
prepare_page_table(mi);
bootmem_init(mi);
devicemaps_init(mdesc);
top_pmd=pmd_off_k(0xffff0000);
zero_page=alloc_bootmem_low_pages(PAGE_SIZE);
memzero(zero_page,PAGE_SIZE);
empty_zero_page=virt_to_page(zero_page);
flush_dcache_page(empty_zero_page);
62.
ARM内存主页表初始化
paging_init依次完成了以下工作:
∙调用prepare_page_table初始化虚拟地址[0,PAGE_OFFSET]和[mi->
bank[0].start+mi->
bank[0].size,VMALLOC_END]所对应的主页表项,所有表项均初始化为0。
这里保留了内核代码区,主页表区以及Bootmem机制中的位图映射区对应的主页表。
这是为了保证内核代码的执行以及对主页表区和位图区的访问。
如果只有一个内存bank,那么mi->
bank[0].size的值和high_memory保持一致,它是当前bank进行物理内存一一映射后的虚拟地址。
对于一个内存为256M的系统来说,它只有一个bank,经过prepare_page_table处理后的内存如上图所示。
∙接着在bootmem_init函数将通过bootmem_init_node对每一个内存bank的页表进行值的填充。
bootmem_init_node将通过map_memory_bank间接调用create_mapping,最终由该函数创建页表。
∙通过devicemaps_init初始化设备I/O对应的相关页表。
∙最后创建0页表,并在Dcache中清空0页表的缓存信息。
63.
页表创建函数调用
12.3.
ARM内存访问
当ARM要访问内存RAM时,MMU首先查找TLB中的虚拟地址表,如果ARM的结构支持分开的地址TLB和指令TLB,那么它用:
∙取指令使用指令TLB
∙其它的所有访问类别用数据TLB
指令TLB和数据TLB在ARMv6架构的MMU中被分别称为指令MicroTLB和数据MicroTLB。
如果没有命中MicroTLB,那么将查询主TLB,此时不区分指令和数据TLB。
如果TLB中没有虚拟地址的入口,则转换表遍历硬件从存在主存储器中的转换表中获取转换页表项,它包含了物理地址或者二级页表地址和访问权限,一旦取到,这些信息将被放在TLB中,它会放在一个没有使用的入口处或覆盖一个已有的入口。
一旦为存储器访问的TLB的入口被拿到,这些信息将被用于:
∙C(高速缓存)和B(缓冲)位被用来控制高速缓存和写缓冲,并决定是否高速缓存。
∙首先检查域位,然后检查访问权限位用来控制访问是否被允许。
如果不允许,则MMU将向ARM处理器发送一个存储器异常;
否则访问将被允许进行。
∙对没有或者禁止高速缓存的系统(包括在没有高速缓存系统中的所有存储器访问),物理地址将被用作主存储器访问的地址。
64.
高速缓存的MMU存储器系统
12.4.
ARMMMU页表
在ARMv6的MMU机制中,提供了两种格式的页表描述符:
∙兼容ARMv4和ARMv5MMU机制的页表描述符。
这种描述符可以对64K大页面和4K小页面再进一步细分为子页面。
∙ARMv6特有的MMU页表描述符,这种页表描述符内增加了额外的特定比特位:
Not-Global(nG),Shared(S),Execute-Never(XN)和扩展的访问控制位APX。
65.
向前兼容的一级页表描述符格式
66.
向前兼容的二级页表描述符格式
Linux使用ARMv6特有的MMU页表描述符格式,它们的标志位描述如下:
67.
ARMv6一级页表描述符格式
表
20.
ARMv6一级页表描述符比特位含义
位
标志
含义
b[1:
0]
类型
指示页表类型:
b00错误项;
b11保留;
b01粗页表,它指向二级页表基址。
b10:
1MB大小段页表(b[18]置0)或16M大小超级段页表(b[18]置1)
b[2]
B[a]
写缓冲使能[b]
b[4]
Execute-Never(XN)
禁止执行标志:
1,禁止执行;
0:
可执行
b[5:
8]
域(domain)
指明所属16个域的哪个域,访问权限由CP15的c3寄存器据定
b[9]
P(ECCEnable)
ECC使能标志,1:
该页表映射区使能ECC校验[c]
b[10:
11]
AP(AccessPermissions)
访问权限位,具体见访问权限列表
b[12:
14]
TEX(TypeExtensionField)
扩展类型,与B,C标志协同控制内存访问类型
bit[15]
APX(AccessPermissionsExtensionBit)
扩展访问权限位
bit[16]
S(Shared)
共享访问
bit[17]
nG(Not-Global)
全局访问
bit[18]
0/1
段页表和超级段页表开关
bit[19]
NS
[a]高速缓存和写缓存的引入是基于如下事实,即处理器速度远远高于存储器访问速度;
如果存储器访问成为系统性能的瓶颈,则处理器再快也是浪费,因为处理器需要耗费大量的时间在等待存储器上面。
高速缓存正是用来解决这个问题,它可以存储最近常用的代码和数据,以最快的速度提供给CPU处理(CPU访问Cache不需要等待)。
[b]SBZ意味置0,该位在粗页表中置0。
[c]ARM1176JZF-S处理器不支持该标志位。
Linux在ARM体系架构的Hardwarepagetable头文件中通过宏定义了这些位。
arch/arm/include/asm/pgtable-hwdef.h
/*
*Hardwarepagetabledefinitions.
*
*+Level1descriptor(PMD)
*-common
*/
#definePMD_TYPE_MASK(3<
<
0)//获取一级页表类型的掩码,它取bit[0:
1]
#definePMD_TYPE_FAULT(0<
0)//置bit[0:
1]为b00,错误项
#definePMD_TYPE_TABLE(1<
1]为b01,粗页表
#definePMD_TYPE_SECT(2<
1]为b10,段页表
#definePMD_BIT4(1<
4)//定义bit[4],禁止执行标志位
#definePMD_DOMAIN(x)((x)<
5)//获取域标志位b[5:
#definePMD_PROTECTION(1<
9)//b[9]ECC使能标志
以上定义了一级页表的相关标志位。
Linux使用段页表作为一级页表,粗页表作为二级页表的基址页表。
段页表的标志位定义如下:
#definePMD_SECT_BUFFERABLE(1<
2)
#definePMD_SECT_CACHEABLE(1<
3)
#definePMD_SECT_XN(1<
4)/*v6*/
#definePMD_SECT_AP_WRITE(1<
10)
#definePMD_SECT_AP_READ(1<
11)
#definePMD_SECT_TEX(x)((x)<
12)/*v5*/
#definePMD_SECT_APX(1<
15)/*v6*/
#definePMD_SECT_S(1<
16)/*v6*/
#definePMD_SECT_nG(1<
17)/*v6*/
#definePMD_SECT_SUPER(1<
18)/*v6*/
68.
ARMv6二级页表基址格式
二级页表相同标志位的含义与一级页表相同,这里不再单独列出。
注意它的b[1]为1时,b[0]表示禁止执行标志。
Linux对二级页表中的标志位定义如下:
*+Level2descriptor(PTE)
#definePTE_TYPE_MASK(3<
0)//获取二级页表类型的掩码,它取bit[0:
#definePTE_TYPE_FAULT(0<
#definePTE_TYPE_LARGE(1<
1]为b01,大页表(64K)
#definePTE_TYPE_SMALL(2<
1]为b10,扩展小页表(4K)
#definePTE_TYPE_EXT(3<
0)//使能禁止执行标志的扩展小页表(4K)
#definePTE_BUFFERABLE(1<
2)//B标志
#definePTE_CACHEABLE(1<
3)//C标志
Linux二级页表使用扩展小页表,这样每个二级页表可以表示通常的1个页面大小(4K)。
Linux对二级页表标志位的定义如下:
*-extendedsmallpage/tinypage
#definePTE_EXT_XN(1<
0)/*v6*/
#definePTE_EXT_AP_MASK(3<
4)
#definePTE_EXT_AP0(1<
#definePTE_EXT_AP1(2<
#definePTE_EXT_AP_UNO_SRO(0<
#definePTE_EXT_AP_UNO_SRW(PTE_EXT_AP0)
#definePTE_EXT_AP_URO_SRW(PTE_EXT_AP1)
#definePTE_EXT_AP_URW_SRW(PTE_EXT_AP1|PTE_EXT_AP0)
#definePTE_EXT_TEX(x)((x)<
6)/*v5*/
#definePTE_EXT_APX(1<
9)/*v6*/
#definePTE_EXT_COHERENT(1<
9)/*XScale3*/
#definePTE_EXT_SHARED(1<
10)/*v6*/
#definePTE_EXT_NG(1<
11)/*v6*/
以上两种页表转换机制由CP15协处理器的控制寄存器c1中的bit23来选择。
bit23为0时为第一种机制,否则为第二种。
在CPU初始化后该位的默认值为0。
Linux在系统引导时会设置MMU的控制寄存器的相关位,其中把bit23设置为1,所以Linux在ARMv6体系架构上采用的是ARMv6MMU页表转换机制。
arch/arm/mm/proc-v6.S
__v6_setup:
adrr5,v6_crval
ldmiar5,{r5,r6}
mrcp15,0,r0,c1,c0,0@readcontrolregister
bicr0,r0,r5@clearbitsthem
orrr0,r0,r6@setthem
movpc,lr@returntohead.S:
__ret
/*
*VXFIDLR
*.......EPUI..T.T4RVIZFRSBLDPWCAM
*rrrrrrrxxxx00101xxxxxxxxx111xxxx<
forced
*011000111.00.1111101<
wewant
.typev6_crval,#object
v6_crval:
crvalclear=0x01e0fb7f,mmuset=0x00c0387d,ucset=0x00c0187c
注意到v6_crval定义了三个常量,首先mrc指令读取c1到r0,然后清除clear常量指定的比特位,然后设置mmuset指定的比特位,其中bit23为1。
在movpc,lr跳转后将执行定义在head.S中的__enable_mmu函数,在进一步调节其它的比特位后最终将把r0中的值写回c1寄存器。
12.5.
页面访问控制
在谈到create_mapping之前,必须说明一下Linux是如何实现对页面的访问控制的。
它定义了一个类型为structmem_type的局部静态数组。
根据不同的映射类型,它定义了不同的访问权限,它通过md参数中的type成员传递给create_mapping。
arch/arm/include/asm/io.h
*Architectureioremapimplementation.
#defineMT_DEVICE0
#defineMT_DEVICE_NONSHARED1
#defineMT_DEVICE_CACHED2
#defineMT_DEVICE_WC3
arch/arm/include/asm/mach/map.h
/*types0-3aredefinedinasm/io.h*/
#defineMT_UNCACHED4
#defineMT_CACHECLEAN5
#defineMT_MINICLEAN6
#defineMT_LOW_VECTORS7
#defineMT_HIGH_VECTORS8
#defineMT_MEMORY9
#defineMT_ROM10
系统中定义了多个映射类型,最常用的是MT_MEMORY,它对应RAM;
MT_DEVICE则对应了其他I/O设备,应用于ioremap;
MT_ROM对应于ROM;
MT_LOW_VECTORS对应0地址开始的向量;
MT_HIGH_VECTORS对应高地址开始的向量,它有vector_base宏决定。
arch/arm/mm/mm.h
structmem_type{
unsignedintprot_pte;
unsignedintprot_l1;
unsignedintprot_sect;
unsignedintdomain;
};
尽管Linux在多数系统上实现或者模拟了3级页表,但是在ARMLinux上它只实现了主页表和两级页表。
主页表通过ARMCPU的段表实现,段表中的每个页表项管理1M的内存,虚拟地址只需要一次转换既可以得到物
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux 机制 分析