Linux arm64 pte相关宏

文章目录

  • 一、pte 和 pfn
    • 1.1 pte_pfn
    • 1.2 pfn_pte
  • 二、其他宏
  • 参考资料

一、pte 和 pfn

// linux-5.4.18/arch/arm64/include/asm/pgtable.h#define pte_pfn(pte)		(__pte_to_phys(pte) >> PAGE_SHIFT)
#define pfn_pte(pfn,prot)	\__pte(__phys_to_pte_val((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))

1.1 pte_pfn

/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT		CONFIG_ARM64_PAGE_SHIFT
CONFIG_ARM64_PAGE_SHIFT=12

通常arm64架构 PAGE_SHIFT = 12

#define pte_pfn(pte)		(__pte_to_phys(pte) >> PAGE_SHIFT)

用于从页表项(Page Table Entry,PTE)中提取页帧号(Page Frame Number,PFN)。通过将PTE转换为物理地址,然后右移位来获得页帧号。页帧号表示物理页在内存中的位置,用于访问和管理物理内存。

#define PTE_ADDR_LOW		(((_AT(pteval_t, 1) << (48 - PAGE_SHIFT)) - 1) << PAGE_SHIFT)#define PTE_ADDR_MASK		PTE_ADDR_LOW
#define __pte_to_phys(pte)	(pte_val(pte) & PTE_ADDR_MASK)

__pte_to_phys宏根据pte来获取对应的物理地址,用于从页表项(Page Table Entry,PTE)中提取低位的物理地址。

PTE_ADDR_LOW这个宏定义的步骤如下:
(1)_AT(pteval_t, 1):这是一个类型转换宏,将常量1强制转换为pteval_t类型。pteval_t是一个代表页表项的数据类型,在这里假设它是一个无符号整数类型。

(2)48 - PAGE_SHIFT:PAGE_SHIFT是一个常量,表示页的大小的位移量。这个表达式计算了48减去页的大小的位移量,得到了用于掩码操作的位数。

(3)(_AT(pteval_t, 1) << (48 - PAGE_SHIFT)):将1左移上一步计算得到的位数,得到一个掩码,只有最低的一些位被设置为1。

(4)(((_AT(pteval_t, 1) << (48 - PAGE_SHIFT)) - 1) << PAGE_SHIFT):将上一步得到的掩码减去1,得到一个更低位全为1的掩码。然后将这个掩码左移PAGE_SHIFT位,相当于将物理地址的低位清零,得到一个基地址。

这个宏定义的作用是根据页表项的位宽和页的大小,计算出页表项中低位的物理地址。这个物理地址是页表项中存储的物理页的基地址,用于访问对应的物理内存。

让我们通过一个示例来分解宏的工作原理:

(1)假设PAGE_SHIFT的值是12,表示页面大小为4KB(2^12 = 4KB)。

(2)_AT(pteval_t, 1) << (48 - PAGE_SHIFT)表达式计算出一个掩码,低位被设置为1。例如,如果pteval_t是一个无符号64位整数,_AT(pteval_t, 1)的结果为1ULL(无符号长整型),那么掩码的值将是0xFFFFFFFFFFFFF000。

(3)从掩码中减去1,得到0xFFFFFFFFFFFFEFFF。

(4)将掩码左移PAGE_SHIFT位(在这个示例中为12位),有效地将低12位清零,结果为0xFFFFFFFFFFFFF000。这代表了物理页的基地址。

(5)执行位与操作pte & PTE_ADDR_LOW,保留了PTE中物理地址的低位,丢弃了高位。

通过这种方式应用宏,你可以从页表项中提取物理地址的低位。得到的值表示与PTE相关联的物理页的基地址。

1.2 pfn_pte

typedef struct { pteval_t pgprot; } pgprot_t;
#define pgprot_val(x)	((x).pgprot)
#define __phys_to_pte_val(phys)	(phys)#define pfn_pte(pfn,prot)	\__pte(__phys_to_pte_val((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))

用于将页帧号(Page Frame Number,PFN)和页面保护属性(Page Protection,prot)转换为页表项(Page Table Entry,PTE)。

这个宏定义的作用是将PFN和页面保护属性转换为PTE。它通过将PFN左移位得到物理地址,然后将物理地址转换为PTE的值。接着,将页面保护属性的值与PTE的值进行按位或操作,得到最终的PTE。这个PTE可以用于更新或设置页表中的条目,以实现对应PFN的映射和页面的保护。

二、其他宏

(1)

#define pte_none(pte)		(!pte_val(pte))
#define pte_clear(mm,addr,ptep)	set_pte(ptep, __pte(0))
#define pte_page(pte)		(pfn_to_page(pte_pfn(pte)))

pte_none(pte): 这个宏判断给定的PTE是否为空。它使用了pte_val(pte)宏,将PTE转换为数值,然后判断该数值是否为0。如果数值为0,表示该PTE为空,返回值为真(非零);否则返回假(0)。

pte_clear(mm, addr, ptep): 这个宏用于将给定的PTE清空,即将其设置为0。它使用了set_pte(ptep, __pte(0)),将给定的PTE指针(ptep)设置为值为0的新的PTE。这样就清除了该PTE所指向的页表项。

pte_page(pte): 这个宏用于从PTE中获取对应的页结构(Page)指针。它使用了pte_pfn(pte)宏获取PTE的页帧号(PFN),并将其传递给pfn_to_page()函数,以获取与该PFN对应的页结构指针。

(2)

// linux-5.4.18/arch/arm64/include/asm/pgtable-hwdef.h/** Level 3 descriptor (PTE).*/
#define PTE_VALID		(_AT(pteval_t, 1) << 0)
#define PTE_TYPE_MASK		(_AT(pteval_t, 3) << 0)
#define PTE_TYPE_PAGE		(_AT(pteval_t, 3) << 0)
#define PTE_TABLE_BIT		(_AT(pteval_t, 1) << 1)
#define PTE_USER		(_AT(pteval_t, 1) << 6)		/* AP[1] */
#define PTE_RDONLY		(_AT(pteval_t, 1) << 7)		/* AP[2] */
#define PTE_SHARED		(_AT(pteval_t, 3) << 8)		/* SH[1:0], inner shareable */
#define PTE_AF			(_AT(pteval_t, 1) << 10)	/* Access Flag */
#define PTE_NG			(_AT(pteval_t, 1) << 11)	/* nG */
#define PTE_DBM			(_AT(pteval_t, 1) << 51)	/* Dirty Bit Management */
#define PTE_CONT		(_AT(pteval_t, 1) << 52)	/* Contiguous range */
#define PTE_PXN			(_AT(pteval_t, 1) << 53)	/* Privileged XN */
#define PTE_UXN			(_AT(pteval_t, 1) << 54)	/* User XN */
#define PTE_HYP_XN		(_AT(pteval_t, 1) << 54)	/* HYP XN */
/** The following only work if pte_present(). Undefined behaviour otherwise.*/
#define pte_present(pte)	(!!(pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)))
#define pte_young(pte)		(!!(pte_val(pte) & PTE_AF))
#define pte_special(pte)	(!!(pte_val(pte) & PTE_SPECIAL))
#define pte_write(pte)		(!!(pte_val(pte) & PTE_WRITE))
#define pte_user_exec(pte)	(!(pte_val(pte) & PTE_UXN))
#define pte_cont(pte)		(!!(pte_val(pte) & PTE_CONT))
#define pte_devmap(pte)		(!!(pte_val(pte) & PTE_DEVMAP))

这些宏定义用于处理页表项(Page Table Entry,PTE),但前提是PTE必须处于有效状态。否则,行为未定义。

pte_present(pte): 这个宏用于判断给定的PTE是否为有效状态(即存在于内存中)。它使用了pte_val(pte)宏将PTE转换为数值,然后通过位掩码检查PTE_VALID和PTE_PROT_NONE是否同时存在于该数值中。如果两个位都存在,表示PTE为有效状态,返回值为真(非零);否则返回假(0)。

pte_young(pte): 这个宏用于判断给定的PTE是否为"young"状态,即表示该页最近被访问过。它使用了pte_val(pte)宏将PTE转换为数值,然后通过位掩码检查PTE_AF是否存在于该数值中。如果存在,表示PTE为"young"状态,返回值为真(非零);否则返回假(0)。

pte_special(pte): 这个宏用于判断给定的PTE是否为特殊标记状态。它使用了pte_val(pte)宏将PTE转换为数值,然后通过位掩码检查PTE_SPECIAL是否存在于该数值中。如果存在,表示PTE为特殊标记状态,返回值为真(非零);否则返回假(0)。

pte_write(pte): 这个宏用于判断给定的PTE是否为可写状态。它使用了pte_val(pte)宏将PTE转换为数值,然后通过位掩码检查PTE_WRITE是否存在于该数值中。如果存在,表示PTE为可写状态,返回值为真(非零);否则返回假(0)。

pte_user_exec(pte): 这个宏用于判断给定的PTE是否允许用户态执行。它使用了pte_val(pte)宏将PTE转换为数值,然后通过位掩码检查PTE_UXN是否不存在于该数值中。如果不存在,表示PTE允许用户态执行,返回值为真(非零);否则返回假(0)。

pte_cont(pte): 这个宏用于判断给定的PTE是否为连续标记状态。它使用了pte_val(pte)宏将PTE转换为数值,然后通过位掩码检查PTE_CONT是否存在于该数值中。如果存在,表示PTE为连续标记状态,返回值为真(非零);否则返回假(0)。

pte_devmap(pte): 这个宏用于判断给定的PTE是否为设备映射标记状态。它使用了pte_val(pte)宏将PTE转换为数值,然后通过位掩码检查PTE_DEVMAP是否存在于该数值中。如果存在,表示PTE为设备映射标记状态,返回值为真(非零);否则返回假(0)。

#define pte_hw_dirty(pte)	(pte_write(pte) && !(pte_val(pte) & PTE_RDONLY))
#define pte_sw_dirty(pte)	(!!(pte_val(pte) & PTE_DIRTY))
#define pte_dirty(pte)		(pte_sw_dirty(pte) || pte_hw_dirty(pte))#define pte_valid(pte)		(!!(pte_val(pte) & PTE_VALID))
#define pte_valid_not_user(pte) \((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID)
#define pte_valid_young(pte) \((pte_val(pte) & (PTE_VALID | PTE_AF)) == (PTE_VALID | PTE_AF))
#define pte_valid_user(pte) \((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))

这些宏定义用于进一步处理页表项(Page Table Entry,PTE),提供了更多的状态判断和标记位操作。

下面是每个宏定义的说明:
pte_hw_dirty(pte): 这个宏用于判断给定的PTE是否为硬件脏页状态。它使用了pte_write(pte)宏判断PTE是否可写,然后通过位掩码检查PTE_RDONLY是否不存在于PTE的数值中。如果PTE可写且不是只读状态,表示PTE为硬件脏页状态,返回值为真(非零);否则返回假(0)。

pte_sw_dirty(pte): 这个宏用于判断给定的PTE是否为软件脏页状态。它使用了pte_val(pte)宏将PTE转换为数值,然后通过位掩码检查PTE_DIRTY是否存在于该数值中。如果存在,表示PTE为软件脏页状态,返回值为真(非零);否则返回假(0)。

pte_dirty(pte): 这个宏用于判断给定的PTE是否为脏页状态(硬件脏页或软件脏页)。它使用了pte_sw_dirty(pte)宏判断PTE是否为软件脏页,以及pte_hw_dirty(pte)宏判断PTE是否为硬件脏页。如果PTE为软件脏页或硬件脏页状态,返回值为真(非零);否则返回假(0)。

pte_valid(pte): 这个宏用于判断给定的PTE是否为有效状态。它使用了pte_val(pte)宏将PTE转换为数值,然后通过位掩码检查PTE_VALID是否存在于该数值中。如果存在,表示PTE为有效状态,返回值为真(非零);否则返回假(0)。

pte_valid_not_user(pte): 这个宏用于判断给定的PTE是否为有效状态且不是用户态的。它使用了位掩码检查PTE_VALID和PTE_USER是否同时存在于PTE的数值中。如果同时存在,表示PTE为有效状态且不是用户态的,返回值为真(非零);否则返回假(0)。

pte_valid_young(pte): 这个宏用于判断给定的PTE是否为有效状态且是"young"状态。它使用了位掩码检查PTE_VALID和PTE_AF是否同时存在于PTE的数值中。如果同时存在,表示PTE为有效状态且是"young"状态,返回值为真(非零);否则返回假(0)。

pte_valid_user(pte): 这个宏用于判断给定的PTE是否为有效状态且是用户态的。它使用了位掩码检查PTE_VALID和PTE_USER是否同时存在于PTE的数值中。如果同时存在,表示PTE为有效状态且是用户态的,返回值为真(非零);否则返回假(0)。

参考资料

Linux 5.4.18

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/84156.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nvme_queue_rq函数分析一

nvme I/O请求时&#xff0c;数据交互分析 主要函数为nvme_queue_rq&#xff1a; static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) {struct nvme_ns *ns hctx->queue->queuedata;struct nvme_queue *nvmeq hctx-…

Linux内核顶层Makefile的make过程说明一

一. Linux内核源码的make编译 使用命令“make xxx_defconfig”配置好 Linux 内核以后就可以使用“make”或者“make all” 命令进行编译。 二. Linux内核源码的make过程 使用命令“ make xxx_defconfig ”配置好 Linux 内核以后就可以使用“ make ”或者“ make all ” 命…

js 事件流、事件冒泡、事件捕获、阻止事件的传播

事件流 js 事件的执行过程分为捕获阶段&#xff08;由外层节点传播到内层节点&#xff09;和冒泡阶段&#xff08;由内层节点传播到外层节点&#xff09;&#xff0c;即先执行捕获阶段的代码&#xff0c;后执行冒泡阶段的代码 事件冒泡 js 事件中的代码默认在冒泡阶段执行&…

【计组】计算机系统体系结构

【计组】计算机系统体系结构 文章目录 【计组】计算机系统体系结构1、体系的发展与思维变化1.1 计算机发展1.2 冯诺依曼体系 2、计算机系统2.1 CPU2.2 存储层次2.2.1 寄存器2.2.2 高速缓存&#xff08;Cache&#xff09;2.2.3 动态随机访问存储器&#xff08;DRAM&#xff09;2…

优化Cache机制,提升CPU性能

目录 CPU性能提升方式 CPU和Cache交互流程 Cache机制 优化Cache机制 CPU性能提升方式 CPU性能提升可以通过多种方式实现&#xff0c;以下是一些常见的方式&#xff1a; 增加CPU核心数&#xff1a;多核心处理器可以同时处理多个任务&#xff0c;从而提高CPU的处理能力。 提…

自动化发布npm包小记

1.注册npm账号 打开npm官网&#xff0c;并注册自己的npm账号 2.申请AccessToken 1.登录npm官网&#xff0c;登录成功后&#xff0c;点开右上角头像&#xff0c;并点击Access Tokens选项 2.点开Generate New Token下拉框&#xff0c;点击Classic Token(和Granular Access To…

CCF会议期刊(软件工程/系统软件/程序设计语言)

中国计算机学会推荐国际学术会议 1PLDIACM SIGPLAN Conference on Programming Language Design & ImplementationA会议软件工程/系统软件/程序设计语言2POPLACM SIGPLAN-SIGACT Symposium on Principles of Programming LanguagesA会议软件工程/系统软件/程序设计语言3FS…

VS2019创建GIt仓库时剔除文件或目录

假设本地有解决方案“SomeSolution” 1、首先”团队资源管理器“-“创建Git存储库”&#xff0c;选择“仅限本地”、“创建” VS会在解决方案目录下自动生成.gitattributes、.gitignore 2、编辑gitignore&#xff0c;直接拖到VS里或者用记事本打开。添加要剔除的文件或文件夹…

轻松自定义文件,悦享文件管理与格式转换!

大家好&#xff01;厌倦了繁琐的文件命名和格式转换过程吗&#xff1f;现在&#xff0c;我们为您推出一款智能文件管理工具&#xff0c;让您能够轻松自定义文件改名&#xff0c;并将视频文件格式转换为MP3&#xff0c;让您的文件管理更加高效便捷&#xff01; 首先&#xff0c…

Redis核心数据结构实战与高性能解析

目录 一、安装Redis 二、Redis线程与高性能 2.1 Redis是单线程么&#xff1f; 2.2 Redis读写是单线程为何这么快&#xff1f; 2.3 Redis如何处理并发操作命令&#xff1f; 三、核心数据结构实战 3.1 字符串常用操作实战 SET 存入键值对 SETNX SETEX MSET 批量存入键…

java图片转pdf ,pdf 导出

pom引入jar <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.0-RC2</version></dependency> 转pdf方法 /*** 使用pdfbox将jpg转成pdf** throws IOException IOException*/pu…

.Net IDE智能提示汉化(.Net6、AspNetCore)

先上现成的.net6汉化文件&#xff0c;可以手动下载后参照 如何为 .NET 安装本地化的 IntelliSense 文件 进行安装。或者使用后文的工具进行自动安装。 无对照英文在前中文在前 汉化内容来自 官方在线文档 &#xff0c;某些内容可能存在明显的机翻痕迹。 上一些效果图&#x…

c语言基础知识+OS+数据结构

c语言&#xff1a; memory section&#xff1a; .bss&#xff1a; uninitialized or zero-initialized global and static variables .data: initialized global and static variables .text: Read only, code and const C语言编译流程&#xff1a; pre-compiler: …

快速安装和测试混淆后的IPA文件:使用Ipa Guard的签名和安装功能

​ 目录 转载&#xff1a;怎么保护苹果手机移动应用程序ipa中文件安全&#xff1f; 前言 1. 对敏感文件进行文件名称混淆 ​编辑 2. 更改文件的MD5值 3. 增加不可见水印处理 3. 对html&#xff0c;js&#xff0c;css等资源进行压缩 5. 删除可执行文件中的调试信息 转载&…

kubesphere中间件部署

微服务部署前中间件部署 一、MySQL部署 1.1 使用Docker实现MySQL主从复制 docker run -p 3307:3306 --name mysql-master \ -v /mydata/mysql/master/log:/var/log/mysql \ -v /mydata/mysql/master/data:/var/lib/mysql \ -v /mydata/mysql/master/conf:/etc/mysql \ -e My…

企业架构LNMP学习笔记59

目录介绍&#xff1a; bin&#xff1a;存放的是启动和关闭tomcat的脚本文件&#xff1b; conf&#xff1a;存放tomcat服务器的各种全局配置文件&#xff0c;其中最重要的是server.xml和web.xml lib: 存放的是tomcat服务器所需要的各种jar文件。java打包类库。 logs&#xff…

Vue项目前端代码防止被调试

项目背景 被安全测试针对了&#xff0c;总是调试我这不太安全的代码。前端代码深度混淆转成十六进制还不行&#xff0c;仍然找到加密方法&#xff0c;对后端数据进行解密。这次就修改了思路换种方法: 我承认阁下很强&#xff0c;但假如, 我是说假如打开控制台是空白页面&…

OSCP系列靶场-Esay-Gaara保姆级

OSCP系列靶场-Esay-Gaara 目录 OSCP系列靶场-Esay-Gaara总结准备工作信息收集-端口扫描目标开放端口收集目标端口对应服务探测 信息收集-端口测试22-SSH端口的信息收集22-SSH端口版本信息与MSF利用22-SSH协议支持的登录方式22-SSH弱口令爆破(待定)22-SSH手动登录尝试(无) 80-HT…

“三高”论文完美复现!基于PSO-VMD-MCKD方法的风机轴承微弱故障诊断,实现早期微弱故障诊断,MATLAB代码实现...

声明&#xff1a;对于作者的原创代码&#xff0c;禁止转售倒卖&#xff0c;违者必究&#xff01; 本期文章思路来自振动测试与诊断期刊的一篇三高论文&#xff0c;点击链接可跳转。https://mp.weixin.qq.com/s/hmmDj5IwpaozeL4F0iI-2g 文章摘要如下&#xff1a; 针对风机滚动轴…

在qml中将一个16进制表示的颜色加上透明度

在qml中&#xff0c;我们在指定控件的颜色时&#xff0c;可以直接通过16进制的字符串来表示&#xff0c;比如"#ff0000"; 这种方式也比较符合UI设计人员的使用习惯。 但是假如要在此颜色的基础上&#xff0c;加个透明度的话&#xff0c;就要重新计算一番&#xff0c;比…