《ARM64体系结构编程与实践》学习笔记(四)
MMU内存管理
1.MMU内存管理(armv8.6手册的D5章节),MMU包含快表TLB,TLB是对页表的部分缓存,页表是存放在内存里面的。
AArch64仅仅支持Long Descriptor的页表格式,AArch32支持两种页表格式Armv7-A Short Descriptor format和Armv7-A(LPAE)Long Descriptor format(默认是short)。AArch64支持3种不同的页大小:4KB,16KB,64KB(Linux使用的是4KB的页大小),大粒度的page size可以减少页表的体积。ARMv8的地址总线位宽通常为48位,最大空间支持256TB,对于实现了LVA扩展的ARMv8可以将位宽扩展到52位。ARMv8虚拟地址是64位的,虚拟地址VA被划分为两个空间,每个空间最大支持256TB,低位的虚拟地址空间位于0x0000_0000_0000_0000到0x0000_FFFF_FFFF_FFFF高位的虚拟地址空间位于0xFFFF_0000_0000_0000到0xFFFF_FFFF_FFFF_FFFF,低位地址空间用作App Space,使用页表TTBR0,高位地址空间用作Kernel Space,使用页表TTBR1,如下图所示,中间的FAULT部分的地址CPU是无法访问的,若访问会报错。
AArch64采用的是四级页表索引,如下图所示:
AArch64页表的L0~L2页表的页表项格式如下图所示,共有三种情况,bit0为0表示该页表项无效,bit0为1表示有效;bit1为1表示该页表项指示下一级页表的基地址,bit1为0表示该页表项指向一个大块内存空间。(可参考ARMv8手册第D5.3节)
AArch64页表的L3页表的页表项格式如下图所示,不同粒度的页面大小,会有不同位数的输出地址。
高位属性和低位属性的具体字段可以参考ARMv8手册的D5.3.3节,不涉及虚拟化只需参考stage1的部分,如下图:
各个字段具体含义如下:
通常一个TLB entry只能完成一个page的VA到PA的转换,Armv8上利用TLB进行的一个优化,可以利用一个TLB entry来完成多个连续的page的VA到PA的转换,这通过上图中的Contiguous位标示,使用Contiguous bit的条件:页面对应的VA和PA必须是连续的、对于4KB的页面,可以一次转换16个连续的page、对于16KB的页面,可以一次转换32或者128个连续的page、对于64KB的页面,可以一次转换32个连续的page、连续的页面必须有相同的属性、起始地址必须以页面对齐。对于不同粒度的页面大小,48位地址的划分情况如下图所示:
2.共享性与缓存性:缓存性(cacheability)指的是页面是否使能了高速缓存以及高速缓存的范围。通常只有普通内存可以使能高速缓存,通过页表项AttrIndx[2:0]来设置页面的内存属性。另外,还能指定高速缓存是内部共享属性还是外部共享属性。通常处理器内核集成的高速缓存属于内部共享的高速缓存,而通过系统总线集成的高速缓存属于外部共享的高速缓存。共享性指的是在多核处理器系统中某一个内存区域的高速缓存可以被哪些观察者观察到。没有共享性指的是只有本地CPU能观察到,内部共享性只能被具有内部共享属性的高速缓存的CPU观察到,外部共享性通常能被外部共享的观察者(例如系统中所有的CPU、GPU以及DMA等主接口控制器)观察到。页表项属性中使用SH[1:0]字段来表示页面的共享性与缓存性,对于使能了高速缓存的普通内存,可以通过SH[1:0]字段来设置共享属性。但是,对于设备内存和关闭高速缓存的普通内存,处理器会把它们当成外部共享属性来看待,尽管页表项中为SH[1:0]字段设置了共享属性(此时SH[1:0]字段不起作用)。在多核处理器系统中,内部共享性和外部共享性描述了缓存的访问范围。内部共享性指处理器内部多个核心之间共享的缓存(如L1、L2缓存),这些缓存只在同一处理器内部可见,通常访问速度较快,适用于核心间的缓存一致性。外部共享性指多个不同硬件单元(如多个CPU核心、GPU、DMA等)共享的缓存,通常位于处理器外部(如L3缓存),这些缓存通过系统总线对所有设备可见,保证了不同硬件之间的缓存一致性。内部共享性通常具有较低的延迟,而外部共享性涉及的硬件更多,延迟较高。两者的主要区别在于缓存的可见性和访问范围,分别适用于不同层级的硬件和内存访问需求。
3.AArch64执行状态的MMU支持单一阶段的页表转换,也支持虚拟化扩展中两阶段的页表转换。单一阶段的页表转换指把虚拟地址(VA)翻译成物理地址(PA)。两阶段的页表转换包括两个阶段。在阶段1,把虚拟地址翻译成中间物理地址(Intermediate Physical Address,IPA);在阶段2,把IPA翻译成最终PA。
4.在SMP(Symmetric Multi-Processor,对称多处理器)系统中,每个处理器内核内置了MMU和TLB硬件单元。如图110所示,CPU0和CPU1共享物理内存,而页表存储在物理内存中。CPU0和CPU1中的MMU与TLB硬件单元也共享同一份页表。当一个CPU修改了页表项时,需要使用BBM(Break-Before-Make)机制(该机制用于确保在SMP系统中,当一个CPU修改页表项时,其他CPU不会使用过时的TLB缓存数据,可参考ARMv8手册的第D5.11节和K11.5.3节)来保证其他CPU能访问正确和有效的TLB。
5.和页表相关的寄存器:
-
TCR_EL1(Translation Control Register):用来配置地址空间大小和页面粒度,其常用字段如下:IPS[34:32]:用来配置物理地址的大小,对于48位地址(物理空间256TB),可将该位设置为0b101。如果IPS字段定义的输出地址大于实际物理内存地址,那么CPU会使用实际物理内存,因为MMU输出地址不能大于实际物理地址。如果页表里的输出地址超过了物理内存地址,会触发地址大小缺页异常(address size fault)或者页表转换缺页异常(translation fault);TG0[15:14]和TG1[31:30]:分别用来配置TTBR0_EL1和TTBR1_EL1的页面粒度,可设置为4KB、16KB或64KB,例如将该位置为0b00表示4KB;T0SZ[5:0]和T1SZ[21:16]:分别用来配置TTBR0_EL1和TTBR1_EL1对应页表所能管辖的地址空间的大小,计算公式为2^(64-TxSZ),如果想将其设为48位寻址空间,则将该位的值设置为16即可;SH0、SH1、IRGN0、IRGN1、ORGN0、ORGN1:用来设置TTBR0_EL1和TTBR1_EL1对应内存的相关属性,如共享属性、高速缓存属性(具体参考ARM64体系结构编程与实践P203),上文提及的每个页表项中的SH[1:0]比当前的SH字段优先级更高,当两个字段都设置时,以页表项中的SH[1:0]位对应的共享属性为准,一般情况下两者需保证一致,否则可能出错
-
SCTLR_EL1(System Control Register):M[0]位用来设置MMU的打开与关闭,即控制第一阶段地址翻译的开关,C[2]位用来设置data cache的打开与关闭,I[12]位用来设置instruction cache的打开与关闭
-
TTBR0_EL1和TTBR1_EL1:分别指向TTBR0和页表TTBR1的基地址,通常用于EL1/EL0的页表映射
6.ARMv8架构处理器主要提供两种类型的内存属性:普通内存(Normal)和设备内存(Device),普通内存是弱一致性的(weakly ordered),没有其他额外的约束,提供最高的内存访问性能。处理器访问设备内存有很多限制,如不能使用高速缓存等。设备内存是严格按照指令顺序来执行的,是强一致性的。ARMv8架构定义了多种设备内存的属性:
- Device-nGnRnE:不支持聚合操作,不支持指令重排,不支持提前写应答;
- Device-nGnRE:不支持聚合操作,不支持指令重排,支持提前写应答;
- Device-nGRE:不支持聚合操作,支持指令重排,支持提前写应答;
- Device-GRE:支持聚合操作,支持指令重排,支持提前写应答。
设备内存相关操作:G表示支持聚合操作(聚合是指可以在同一个内存属性的区域里面把多次访问内存的操作合并成一次总线传输,如果一个设备内存标记为nG,那么就会严格按照访问的次数和大小来进行访问而不会进行合并优化);R表示支持指令重排,可以乱序执行;E表示支持提前写应答(即数据到达写缓存就可以进行写应答,如果一个设备内存标记为nG则数据到达外设才能进行写应答)。内存属性并没有存放在页表的页表项中,而是存放在MAIR_ELn寄存器(Memory Attribute Indirection Register)。MAIR_ELn寄存器结构如下,最多可以存储八类不同属性的内存:
页表项中有一个3位的索引值AttrIdx[0:2]来查找MAIR_ELn寄存器。
7.在操作系统启动过程中,从BootLoader/BIOS跳转到操作系统时,MMU(内存管理单元)通常是关闭的,因此处理器直接使用物理地址进行内存访问。关闭MMU意味着不能使用高速缓存优化性能,因为当MMU关闭时,系统无法使用虚拟地址进行内存访问,因此无法进行虚拟地址到物理地址的转换,也就无法正确维护缓存的内容。在系统初始化时,打开MMU并启用数据高速缓存是提高性能的关键,但这需要谨慎操作。因为当MMU打开后,处理器会开始使用虚拟地址进行内存访问,因此必须确保虚拟地址到物理地址的正确映射(如使用恒等映射,即VA=PA,一般映射前后2M空间就可以了),否则可能会导致访问错误或数据不一致,在关闭MMU情况下,处理器访问的地址都是物理地址。当MMU打开时,处理器访问的地址变成了虚拟地址。现代处理器都是多级流水线架构,处理器会提前预取多条指令到流水线中。当打开MMU时,处理器已经提前预取了多条指令,并且这些指令是以物理地址来进行预取的。当打开MMU指令执行完成,处理器的MMU功能生效,那么之前提前预取的指令以虚拟地址来访问,到MMU单元去查找对应的物理地址。因此在打开MMU前后应用isb()指令刷新处理器的指令流水线让CPU重新取指。页表的创建和填充是由操作系统来完成的,但是处理器遍历页表是由处理器的 MMU来完成的。第14章的实验一通过恒等映射创建了四级页表,主要创建过程如下:
-
在链接脚本中的数据段直接分配4KB大小作为L0级页表的缓存空间,剩下的L1级、L2级、L3级页表在初始化时动态创建,实验中所设计的页表只有第L2级页表(三级页表)可以分配2M的大块内存,所以在创建页表时用了一个小技巧,即在创建L2级页表项时如果虚拟区间的开始地址(addr)、结束地址(next)和物理地址(phys)都与SECTION_SIZE大小(2MB)对齐并且没有设置NO_BLOCK_MAPPINGS标志位,那么直接设置段映射(section mapping)的页表项,不需要映射下一级页表,因为这几个地址都与SECTION_SIZE对齐就说明所需要的内存大于SECTION,直接按照SECTION分配即可,不用再往下细分到4KB,如下图(具体参考ARM64体系结构编程与实践P215):
-
页表创建完之后设置所要用到的几种内存的内存属性,写入MAIR_EL1寄存器中,并设置页面粒度为4KB,ID_AA64MMFR0_EL1寄存器中含有当前支持的页面粒度信息
-
而后将L0页表基地址写入TTBR0_EL1中,打开MMU,注意在打开MMU前后使用isb()指令冲刷流水线
建立完页表并打开MMU后,可以正常访问已经建立了VA到PA映射的地址,但如果访问没有建立页表映射的地址则会导致同步异常。
8.ldxr和stxr可以进行原子访问,但是使用时有很多限制,参考ARM®Cortex®-A Series(Programmer’s Guide for ARMv8-A)手册的14.1.4节,如下图所示:
只有在所访问的存储器满足:可内部或外部共享、内部回写、外部回写、读写分配命中、非暂态等条件时才能确保这两个指令可正常使用。当没有打开MMU时,访问normal内存会被当成是访问device 内存,这两个指令无法使用。如果仅仅enable了MMU,而没有设置上述属性(具体设置为:通过SCTLR_EL1寄存器的C位打开data cache、通过TCR_EL1寄存器的SH0、SH1、IRGN0、IRGN1、ORGN0、ORGN1位打开外部共享、内部回写、外部回写等属性),这两个指令也无法正常使用。
9.除了通过MMU自动进行虚拟地址到物理地址的转换外,还可以通过AT指令实现两个地址间的转换。AT指令用法如下图所示:
语法格式为AT <operation>, <Xt>,例如上图中s1e1r表示第一阶段地址转换、EL1、读取操作,X0存放了待转换的虚拟地址值,具体可参考ARMv8手册第D5.2.11节,如果转换成功读取的物理地址和内存相关属性信息会被存放在PAR_EL1寄存器中,该寄存器结构如下图所示:
相关文章:

《ARM64体系结构编程与实践》学习笔记(四)
MMU内存管理 1.MMU内存管理(armv8.6手册的D5章节),MMU包含快表TLB,TLB是对页表的部分缓存,页表是存放在内存里面的。 AArch64仅仅支持Long Descriptor的页表格式,AArch32支持两种页表格式Armv7-A Short De…...

01-SDRAM控制器的设计——案例总概述
本教程重点▷▷▷ 存储器简介。 介绍 SDRAM 的工作原理。 详细讲解SDRAM 控制的Verilog 实现方法。 PLL IP和FIFO IP 的调用,计数器设计,按键边沿捕获,数码管控制。 完成SDRAM控制器应用的完整案例。 Signal Tap 调试方法。 准备工作▷…...

京准:NTP卫星时钟服务器对于DeepSeek安全的重要性
京准:NTP卫星时钟服务器对于DeepSeek安全的重要性 京准:NTP卫星时钟服务器对于DeepSeek安全的重要性 在网络安全领域,分布式拒绝服务(DDoS)攻击一直是企业和网络服务商面临的重大威胁之一。随着攻击技术的不断演化…...

uniapp访问django目录中的图片和视频,2025[最新]中间件访问方式
新建中间件, middleware.py 匹配,以/cover_image/ 开头的图片 匹配以/episode_video/ 开头的视频 imageSrc: http://192.168.110.148:8000/cover_image/12345/1738760890657_mmexport1738154397386.jpg, videoSrc: http://192.168.110.148:8000/episode_video/12345/compres…...

RuoYi-Vue-Oracle的oracle driver驱动配置问题ojdbc8-12.2.0.1.jar的解决
RuoYi-Vue-Oracle的oracle driver驱动配置问题ojdbc8-12.2.0.1.jar的解决 1、报错情况 下载:https://gitcode.com/yangzongzhuan/RuoYi-Vue-Oracle 用idea打开,启动: 日志有报错: 点右侧m图标,maven有以下报误 &…...

python脚本实现windows电脑内存监控内存清理(类似rammap清空工作集功能)
import ctypes import psutil import time import sys import os from datetime import datetime import pyautogui# 检查管理员权限 def is_admin():try:return ctypes.windll.shell32.IsUserAnAdmin()except:return False# 内存清理核心功能 def cleanup_memory(aggressivene…...

【狂热算法篇】并查集:探秘图论中的 “连通神器”,解锁动态连通性的神秘力量
嘿,朋友们!喜欢这个并查集的讲解吗 记得点个关注哦,让我们一起探索算法的奥秘,别忘了一键三连,你的支持是我最大的动力! 欢迎拜访:羑悻的小杀马特.-CSDN博客 本篇主题:深度剖析并查…...

SpringBoot中实现动态数据源切换
SpringBoot中实现动态数据源切换 文章目录 SpringBoot中实现动态数据源切换SpringBoot中实现动态数据源切换基础知识1. 什么是数据源?2. 动态数据源切换的概念3. Spring Boot 中的默认数据源配置4. 动态数据源的挑战5. Spring 中的数据源切换方式 设计思路1. 明确应…...

数据结构及排序算法
数据结构 线性结构 ◆线性结构:每个元素最多只有一个出度和一个入度,表现为一条线状。线性表按存储方式分为顺序表和链表。 存储结构: ◆顺序存储:用一组地址连续的存储单元依次存储线性表中的数据元素,使得逻辑上相邻的元素物理上也相邻。 ◆链式存储:存储各数据元素的结点…...

Python基础-元组tuple的学习
在 Python 中,元组(tuple)是一种不可变的序列类型,允许存储不同类型的元素。元组非常类似于列表(list),但与列表不同的是,元组一旦创建,就不能修改其内容。 1 元组的创建…...

【手写公式识别】MEMix: Improving HMER with Diverse Formula Structure Augmentation 论文阅读
发表于:ICME 2024 原文链接:https://ieeexplore.ieee.org/document/10687521 源码:无 Abstract 手写数学表达式识别(HMER)旨在将数学表达式(MEs)的图像转换为相应的LaTeX序列。然而࿰…...
使用deepseek写一个飞机大战游戏
说明: 安装pygame:在运行代码之前,需要先安装 pygame 库。可以通过以下命令安装: pip install pygame图像文件:需要将玩家、敌人和子弹的图像文件(player.png, enemy.png, bullet.png)放在与脚本…...
用Kibana实现Elasticsearch索引的增删改查:实战指南
在大数据时代,Elasticsearch(简称 ES)和 Kibana 作为强大的数据搜索与可视化工具,受到了众多开发者的青睐。Kibana 提供了一个直观的界面,可以方便地对 Elasticsearch 中的数据进行操作。本文将详细介绍如何使用 Kiban…...
C# 封送和远程编程介绍
.NET学习资料 .NET学习资料 .NET学习资料 在 C# 编程领域中,封送(Marshaling)和远程编程(Remote Programming)是两个极为重要的概念,它们为开发者提供了与不同环境、不同进程或不同机器上的代码进行交互的…...
MybatisPlus较全常用复杂查询引例(limit、orderby、groupby、having、like...)
MyBatis-Plus 是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。以下是 MyBatis-Plus 中常用复杂查询(如 LIMIT、ORDER BY、GROUP BY、HAVING、LIKE 等)的引例: 1. 环境准备…...

02.07 TCP服务器与客户端的搭建
一.思维导图 二.使用动态协议包实现服务器与客户端 1. 协议包的结构定义 首先,是协议包的结构定义。在两段代码中,pack_t结构体都被用来表示协议包: typedef struct Pack {int size; // 记录整个协议包的实际大小enum Type type; …...
Jenkins数据备份到windows FTP服务器
文章目录 背景1. 安装配置 FileZilla Server(Windows)1.1 下载并安装 FileZilla Server1.2 配置 FTP 用户和共享目录 2. 安装并配置 FTP 客户端(CentOS)2.1 在 CentOS 安装 lftp 3. 编写 Jenkins 备份脚本3.1 赋予执行权限3.2 测试…...

【R语言】卡方检验
一、定义 卡方检验是用来检验样本观测次数与理论或总体次数之间差异性的推断性统计方法,其原理是比较观测值与理论值之间的差异。两者之间的差异越小,检验的结果越不容易达到显著水平;反之,检验结果越可能达到显著水平。 二、用…...
ASP.NET Core托管服务
目录 托管服务的异常问题 托管服务中使用DI 托管服务案例:数据的定时导出 场景,代码运行在后台。比如服务器启动的时候在后台预先加载数据到缓存,每天凌晨3点把数据导出到备份数据库,每隔5秒钟在两张表之间同步一次数据。托管服…...

HarmonyOS 5.0应用开发——全局自定义弹出框openCustomDialog
【高心星出品】 文章目录 全局自定义弹出框openCustomDialog案例开发步骤完整代码 全局自定义弹出框openCustomDialog CustomDialog是自定义弹出框,可用于广告、中奖、警告、软件更新等与用户交互响应操作。开发者可以通过CustomDialogController类显示自定义弹出框…...

【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...