1.带你了解Linux内核页表
2.ARMä¸bufferable cacheableç解
3.linux内核基础知识
4.ARM A64架构 memory model 学习(一)
5.一文让你搞懂 | ARM MMU纯干货建议收藏
6.ARM Cortex-A53的页页表存储层次结构
带你了解Linux内核页表
Linux内核页表是操作系统内核管理内存资源的核心组件,涉及内存空间的表建划分和地址映射。本文将带您深入了解Linux内核页表的立源构造、分配及作用。页页表
在ARM的表建位系统中,内存空间被划分为0-3G的立源通达信关注公式源码用户空间和3G-4G的内核空间,其中位地址空间分为PGD(页全局描述符)、页页表PTE(页表项)以及页内地址三部分。表建在内核代码中,立源PGD通常使用位表示,页页表PTE使用9位,表建页内地址为位。立源然而,页页表在MMU(存储器管理单元)系统中,表建ARM的立源二级页表则采用位的PGD和8位的PTE。
Linux内核页表分为用户空间页表和内核空间页表,不同的进程拥有不同的用户空间页表,但它们共享同一内核空间页表。在创建进程时,系统会分配一个页表指针(mm_struct数据结构中的pgd_t * pgd),通常初始值为swapper_pg_dir,为进程分配k空间,包括用户空间页表和内核空间页表。
用户空间页表映射了从地址0x 到0xC 的区域,大小为TASK_SIZE,而内核空间页表则从0xC 映射到0Xffff ffff,为1G。考虑到硬件地址映射,实际的页表项数为项,通过将页表指针的值右移位来实现。
Linux内核页表在系统启动时进行分配,如Linux-2.6版本的S3C系统中,内核页表的godaddyapiphp源码地址是0x ,最大空间为0x,即K。在init_mm()结构中初始化空闲进程页表,系统在引导代码的汇编中实现页表创建。
在进程创建时,页表分为用户空间页表和内核空间页表,用户空间页表占用前个页表项,其余部分用于内核空间页表。
在Linux内核页表中,页表项的位表示与硬件的位存在细微差异,这可以通过在软件上将位页表项的值补上0或1来实现硬件兼容性。这样,页表项的数量可以达到项,每个项大小为4字节,总大小为K,对应每个进程分配的页表空间。
内核空间页表的分配涉及永久内核映射、临时内核映射和非连续内存分配等。在系统初始化时,内核会为内核空间分配页表,确保内核代码、内核内存地址等的正确映射。通过更新页表项,当访问特定内核地址时,系统可以将相应的内核映射复制到进程页表中。
当内核访问无效地址时,会触发取值异常,导致中断并进入处理函数。通过这些机制,Linux内核能够有效地管理内存资源,确保程序的稳定运行。
ARMä¸bufferable cacheableç解
注é说çå¾æ¸ æ¥ï¼åå§å页表ï¼æå¼cacheableåbufferableä½ ã对ç©çRAM空é´å»ºç«cacheåbufferãç¶åéè¿å°r0ï¼r3ï¼ä¸çå°åå¼å³ç§»ä½å左移ä½ï¼å³æ¸ é¶r3ä¸å°åçä½ä½ï¼
linux内核基础知识
Linux内核基础知识涵盖了Linux内核的源码 文件版本、标准内核概念、Linux操作系统的分类、内核的选择以及Linux内核的启动过程。标准内核,即基础内核,主要在kernel.org维护和获取,通常针对Intel X体系结构。ARM架构使用的是RISC指令集,指令长度固定,而X架构使用CISC指令集,指令长度不固定。Linux内核的分类包括基于主要功能差异和发行组织、应用不同嵌入式平台的两种方式。标准内核与嵌入式Linux系统相比,后者通过安装补丁实现对特定硬件平台的支持。选择Linux内核时,ARM Linux建议使用2.4.x或2.6.x版本。
Linux内核的启动过程涉及到引导加载程序(Bootloader)、Linux内核、文件系统和应用程序。Bootloader作为系统启动后的第一段代码,负责初始化处理器及外设,并将内核从非易失性存储器(如Flash)加载至RAM,然后跳转到内核执行。Bootloader在执行过程中需要初始化RAM、串口、检测处理器类型、设置内核启动参数并最终调用Linux内核。
Bootloader在不同处理器上电或复位后的执行地址不同,对于ARM处理器,地址为0x。Bootloader需要根据存储器类型(Nor Flash或Nand Flash)来决定执行过程,dcl 源码Nor Flash支持代码直接执行,而Nand Flash则需要先拷贝代码至RAM再执行。Bootloader功能包括RAM初始化、串口初始化、处理器类型检测、内核启动参数设置、最终调用Linux内核。
Linux内核启动通常通过call_linux(0, machine_type, kernel_params_base)调用,其中machine_type是处理器类型,kernel_params_base是启动参数在RAM的地址。内核入口程序包括arch/arm/boot/compressed/head.S和arch/arm/kernel/head-armv.S。head.armv.S程序完成开启MMU和Cache,解压内核,并通过调用call_kernel()进入内核启动。
Linux内核的启动从非压缩内核Image的stext段开始,通过查找处理器类型调用初始化函数,建立页表,最后跳转到start_kernel()函数开始内核初始化。start_kernel函数进行剩余的硬件平台相关初始化,调用init进程并等待用户进程执行,完成内核启动。该过程包括硬件初始化、根文件系统挂载、执行init进程及其后续工作,最终使系统处于闲置状态等待用户程序执行。
ARM A架构 memory model 学习(一)
Memory model在计算机架构中起着核心作用,它定义了如何组织和描述内存行为,为程序提供了一套准则来控制内存的访问与使用。它还定义了内存中地址的属性以及是否允许乱序访问。地址映射是将内存区域分配到地址空间中,这在系统设计中至关重要,以确保不同组件之间的bitspirit源码数据隔离和权限控制。例如,外设通常不能缓存,且只能顺序访问,而用户数据和代码的权限较低,不能访问内核资源和执行。
AArch架构中的内存模型涉及虚拟地址空间与物理地址空间的映射,通过一系列转换列表(通常是页表)实现这一过程。每个页表描述器包含对应物理地址和访问属性,如可共享性、访问权限、执行权限等。内存属性可以跨层级垂直覆盖,即更高层级的属性设置可以影响更低层级的设置,这有助于实现内存访问的灵活性和安全性。
内存访问顺序与SSE(顺序执行概念)相关,但二者并非完全相同。SSE描述了处理器执行指令的顺序,而内存访问顺序则关注数据在内存中的访问顺序。现代处理器通过乱序执行和并行处理提高性能,但内存访问仍需遵循一定的顺序规则,以确保数据一致性。正常内存(Normal memory)用于描述任何行为像内存的存储器,如RAM、FLASH、ROM等,而设备内存(Device memory)则用于描述外设,允许在访问时发生可能的副作用,如改变数据状态。
AArch架构中的内存模型提供了对内存访问的精细控制,以支持高效、安全的多任务和多线程环境。通过页表、转换列表等机制,它确保了内存访问的隔离性和一致性,同时允许硬件在不违反数据依赖性的前提下进行优化,如合并存储指令、预测内存访问等。这使得AArch架构在嵌入式和移动设备上广泛使用,为开发者提供了强大而灵活的内存管理工具。
一文让你搞懂 | ARM MMU纯干货建议收藏
MMU主要负责地址翻译,将CPU发出的虚拟地址自动转换为物理地址,进行内存或设备的读写操作。在Linux内核中,地址转换涉及TTBRx_EL1寄存器的页表基地址,支持特权模式与非特权模式下的地址空间转换。软件需管理页表,按照ARM技术要求创建页表,将其基地址写入指定寄存器。地址翻译过程涉及一级或二级页表的使用,具体取决于虚拟地址范围。Linux后台/内核技术交流群提供学习资源,包括书籍、视频等。
在ARMV8-aarch架构下,不同异常等级使用不同的页表基地址寄存器进行地址转换,EL0/EL1系统使用TTBR0_EL1和TTBR1_EL1,EL2使用TTBR2_EL1,EL3使用TTBR3_EL1。每个entry的memory attributes条目定义了执行权限、访问权限、共享属性等。当启用memory tagging时,虚拟地址的高8位用于传输签名数据,处理器内部对这些位进行特殊处理。
启用hypervisor后,虚拟地址转换经过VA—>PA和VA—>IPA—>PA两次转换,guestos中的假物理地址通过VTTBR0_EL2转换为真实物理地址。MMU和cache维护相关的寄存器共有多个,包括用于地址翻译和TLB维护的寄存器。系统寄存器如TTBR0_ELx、TTBR1_ELx、TCR_ELx以及MAIR_ELx等,用于控制和管理MMU和cache操作。TCR_ELx寄存器中的Shareable属性表明地址的使用权限。Inner和Outer Shareable属性在多处理器系统中确保一致性。
设置inner/outer cache属性包括模式选择(只写模式、回写模式、write allocate、No-write allocate),属性设置1表示回写模式和write allocate模式。通过理解这些寄存器和设置,可以实现高效和安全的内存管理和访问。
ARM Cortex-A的存储层次结构
Cortex-A设计了两个全相联微TLB,每个表项,借助于共享的个表项四路组相联的主TLB,以及一个位虚拟地址空间和一个位物理地址空间的支持。处理器的位寄存器支持更大的虚拟地址空间,但软件并未需求此空间,因此位虚拟地址空间能够有效减小页表内存占用,简化TLB硬件。Cortex-A的地址尺寸和TLB总结如下。
Cortex-A提供了1至4个处理器或核心,每个核心配备至KiB二路组相联的L1指令缓存,L1缓存块大小为字节。数据缓存的关联度增加至四路,而其他变量保持不变。Cortex-A提供了一个在1至4个核心之间共享的L2缓存,该缓存为十六路组相联,块大小为字节,大小在KiB至2MiB之间。以下是Cortex-A的缓存概览。
设计人员在缓存支持多时钟周期执行访存指令的处理器时面临挑战。通常做法是将缓存分割为多个bank,并在不同bank下允许多个独立并行访问,类似于DRAM bank交错式访问。Cortex-A采用额外优化技术减少缺失代价,包括在缺失时先返回关键字,以及在缓存缺失期间继续执行访问数据缓存指令。使用非阻塞cache技术隐藏缺失延迟,通过其他工作来隐藏缺失,以及重叠不同缺失的延迟。
为支持多未完成缺失,需要一个高带宽存储系统,以平行处理多个缺失。个人移动设备通常可以流水化、合并、重排或优先化请求,而大型服务器和多处理器则常具备能并行处理多个未完成缺失的存储器系统。
Cortex-A采用数据访问预取机制,预测下一个数据访问地址,在缺失前获取数据。此技术在循环访问数组时表现良好。芯片的复杂存储系统,以及大部分专用于缓存和TLB的模块,体现了为缩小处理器时钟周期与存储器延迟差距所付出的努力。
为了评估存储器层次结构的性能,使用了KiB二路组相联的L1指令缓存、KiB四路组相联的L1数据缓存和1MiB十六路组相联的L2缓存,进行SPEC整数基准测试。Cortex-A在这些基准测试上的指令缓存缺失率极低。数据缓存结果中,L1缓存缺失率在0.5%至.3%之间,平均6.4%,中位数2.4%;全局L2缓存缺失率在0.1%至9.0%之间,平均1.3%,中位数0.3%。1GHz下,L1缺失代价为个时钟周期,L2缺失代价为个时钟周期。每次数据访问的平均缺失代价,显示了低缺失率乘以高缺失代价对性能的影响。对于内存占用率较大的应用,L1和L2中的缺失率较高,值得注意的是,L2中的缺失率为全局缺失率,包含L1中命中的访问。尽管L1缺失率相对较高,但L2缺失代价高出了5倍以上,这意味着L2缺失对性能的影响巨大。
ARM BTI特性学习
ARM的BTI特性,全称branch target identification,是v8.5架构引入的一项关键安全增强,旨在对抗JOP攻击,这种攻击利用程序中的小代码片段(gadgets)进行间接跳转,可能让攻击者执行任意代码。BTI的引入改变了这一规则,通过在处理器编译时为间接跳转指令(如BLR、BR或ret)设置特定的着陆点(landing pads),限制了其可跳转目标,从而大大减少了攻击者利用gadgets的能力。
其工作原理在于,处理器在编译时为间接跳转指令配置BTI指令,只允许它们跳转到预先指定的着陆点。如果目标地址不符合设定,将引发跳转目标异常。这种机制通过细化间接跳转指令类型(BTYPE字段)进一步增强安全性,使得攻击者不仅需要知道指令类型,还要理解其特定用途,否则无法顺利执行。
启用BTI特性的方法是通过在页表转换表中设置guarded page(GP)位。对于启用BTI的页表,GP位为1,否则为0。BTI和PAC指令都是向下兼容的,旧处理器会忽略BTI,但当GP为0时,也会忽略指令。在实践中,如RET等间接跳转指令的使用需谨慎,因为可能带来代码膨胀。然而,PAC特性已经在一定程度上覆盖了这些指令,因此在函数调用时,通常仅使用PACIxSP和PACIxZ作为保护,以避免额外的代码负担。
更多详细信息可参考ARM开发者文档:developer.arm.com/docum...