页表结构详细说明

news2024/11/18 15:35:40

一、页表

1. 内存地址的分解

我们知道linux采用了分页机制,通常采用四级页表,页全局目录(PGD),页上级目录(PUD),页中间目录(PMD),页表(PTE)。如下:
在这里插入图片描述

其含义定义在arch/arm64/include/asm/pgtable-hwdef.h文件中:

CONFIG_PGTABLE_LEVELS				//页表级数

//offset
#define PAGE_SHIFT		CONFIG_ARM64_PAGE_SHIFT			//页offset,为12
#define PAGE_SIZE		(_AC(1, UL) << PAGE_SHIFT)		//页大小,为4k

//PTE
#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - 3))		//PTE位数,为9

#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	((PAGE_SHIFT - 3) * (4 - (n)) + 3)

//PMD
#if CONFIG_PGTABLE_LEVELS > 2
#define PMD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(2)
#define PMD_SIZE		(_AC(1, UL) << PMD_SHIFT)		//2M
#define PMD_MASK		(~(PMD_SIZE-1))
#define PTRS_PER_PMD		PTRS_PER_PTE				//PMD位数,为9
#endif

//PUD
#if CONFIG_PGTABLE_LEVELS > 3
#define PUD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(1)
#define PUD_SIZE		(_AC(1, UL) << PUD_SHIFT)		//1G
#define PUD_MASK		(~(PUD_SIZE-1))
#define PTRS_PER_PUD		PTRS_PER_PTE				//PUD位数,为9
#endif

//PGD
#define PGD_SIZE	(PTRS_PER_PGD * sizeof(pgd_t))  //4096 
#define VA_BITS			(CONFIG_ARM64_VA_BITS)		//4级页表为48,3级页表为39
#define PGDIR_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - CONFIG_PGTABLE_LEVELS)
#define PGDIR_SIZE		(_AC(1, UL) << PGDIR_SHIFT)		
#define PGDIR_MASK		(~(PGDIR_SIZE-1))
#define PTRS_PER_PGD		(1 << (VA_BITS - PGDIR_SHIFT))

看到这里我们知道4级页表虚拟地址为48位,页全局目录(PGD),页上级目录(PUD),页中间目录(PMD),页表(PTE)都是9位,offset是12位。但是有些系统是使用3级页表的,那么他的虚拟地址为39位,页全局目录(PGD),页中间目录(PMD),页表(PTE)都是9位,offset是12位,也就是说,少了页上级目录(PUD)。其实我们使用3级页表就够了,39为的虚拟地址可以操作512g的内存,是完全够用的。我们国产操作系统就是使用3级页表的。最后说明一下。无论是3级页表还是4级页表,我们的物理地址都是48位的。

1.2 页表的数据结构

我们已经确立了页表项的数目,但没有定义其结构。内核提供了4个数据结构(定义在 arch/arm64/include/asm/pgtable-types.h中)来表示页表项的结构。

typedef struct { pteval_t pte; } pte_t;
#define pte_val(x)	((x).pte)
#define __pte(x)	((pte_t) { (x) } )

#if CONFIG_PGTABLE_LEVELS > 2
typedef struct { pmdval_t pmd; } pmd_t;
#define pmd_val(x)	((x).pmd)
#define __pmd(x)	((pmd_t) { (x) } )
#endif

#if CONFIG_PGTABLE_LEVELS > 3
typedef struct { pudval_t pud; } pud_t;
#define pud_val(x)	((x).pud)
#define __pud(x)	((pud_t) { (x) } )
#endif

typedef struct { pgdval_t pgd; } pgd_t;
#define pgd_val(x)	((x).pgd)
#define __pgd(x)	((pgd_t) { (x) } )

typedef struct { pteval_t pgprot; } pgprot_t;
#define pgprot_val(x)	((x).pgprot)
#define __pgprot(x)	((pgprot_t) { (x) } )

typedef u64 pteval_t;
typedef u64 pmdval_t;
typedef u64 pudval_t;
typedef u64 pgdval_t;

从代码中我们看到了以下东西:

  1. 页表项的结构
    pgd_t 用于全局页目录项。
    pud_t 用于上层页目录项。
    pmd_t 用于中间页目录项。
    pte_t 用于直接页表项。
页表项的结构pgd_t 用于全局页目录项。pud_t 用于上层页目录项。pmd_t 用于中间页目录项。pte_t 用于直接页表项。

1.3 特定于页表的信息

arch/arm64/include/asm/pgtable-hwdef.h

/*
 * Level 3 descriptor (PTE).
 */
#define PTE_TYPE_MASK		(_AT(pteval_t, 3) << 0)
#define PTE_TYPE_FAULT		(_AT(pteval_t, 0) << 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 */

/*
 * Level 2 descriptor (PMD).
 */
#define PMD_TYPE_MASK		(_AT(pmdval_t, 3) << 0)
#define PMD_TYPE_FAULT		(_AT(pmdval_t, 0) << 0)
#define PMD_TYPE_TABLE		(_AT(pmdval_t, 3) << 0)
#define PMD_TYPE_SECT		(_AT(pmdval_t, 1) << 0)
#define PMD_TABLE_BIT		(_AT(pmdval_t, 1) << 1)

#define PUD_TYPE_TABLE		(_AT(pudval_t, 3) << 0)
#define PUD_TABLE_BIT		(_AT(pudval_t, 1) << 1)
#define PUD_TYPE_MASK		(_AT(pudval_t, 3) << 0)
#define PUD_TYPE_SECT		(_AT(pudval_t, 1) << 0)

还有一些用于处理内存页的体系结构相关状态的函数:

函数描述
pte_present页在内存中吗
pte_read从用户空间可以读取该页吗
pte_write可以写入到该页吗
pte_exec该页中的数据可以作为二进制代码执行吗
pte_dirty页是脏的吗?其内容是否修改过
pte_file该页表项属于非线性映射吗
pte_young访问位(通常是_ PAGE_ACCESS )设置了吗
pte_rdprotect清除该页的读权限
pte_wrprotect清除该页的写权限
pte_exprotect清除执行该页中二进制数据的权限
pte_mkread设置读权限
pte_mkwrite设置写权限
pte_mkexec允许执行页的内容
pte_mkdirty将页标记为脏
pte_mkclean“清除”页,通常是指清除 _PAGE_DIRTY 位
pte_mkyoung设置访问位,在大多数体系结构上是 _PAGE_ACCESSED
pte_mkold清除访问位
以上函数一般是用于设置、删除、查询某个特定的属性(例如,页的写权限)。

1.4 页表的格式、

ARM64 处理器把页表称为转换表( translation table ),最多 4 级。分别是页全局目录(PGD),页上级目录(PUD),页中间目录(PMD),页表(PTE)。ARM64 处理器把表项称为描述符( descriptor ),使用 64 位的长描述符格式。描述符的第 0 位指示描述符是不是有效的: 0 表示无效, 1 表示有效;第 1 位指定描述符类型。

  1. 页目录项,就是在页全局目录(PGD),页上级目录(PUD),页中间目录(PMD)中, 0 表示块( block )描述符, 1 表示表( table )描述符。块描述符存放一个内存块(即巨型页)的起始地址,表描述符存放下一级转换表的地址。
  2. 页目表项,就是页表(PTE), 0 表示保留描述符, 1 表示页描述符。

1.4.1 页目录项

  1. 无效描述符:无效描述符的第 0 位是 0 。
    在这里插入图片描述

  2. 块描述符:块描述符的最低两位是 01。
    在这里插入图片描述

  3. 表描述符:表描述符的最低两位是 11。
    在这里插入图片描述

1.4.2 页目表项

  1. 无效描述符:无效描述符的第 0 位是 0。
    在这里插入图片描述

  2. 保留描述符:保留描述符的最低两位是 01。
    在这里插入图片描述

  3. 页描述符:页描述符的最低两位是 11
    在这里插入图片描述

无论是页目录项的块描述符还是页表项的页描述符,都是表示一个整体的内存;块描述符一般用于巨型页,而页描述符用于普通页。
他们的内存属性被拆分成一个高属性块和一个低属性块,具体可以看下面的图和表:
在这里插入图片描述

位数含义
59 ~ 62基于页的硬件属性( Page-Based Hardware Attributes ),如果没有实现 ARMv8.2-TTPBHA ,忽略。
55 ~ 58保留给软件使用。
54在异常级别 0 ,表示 UXN ( Unprivileged execute-Never ),即不允许异常级别0 执行内核代码;在其他异常级别,表示 XN ( execute-Never ),不允许执行。
53PXN ( Privileged execute-Never ),不允许在特权级别(即异常级别 1/2/3 )执行。
52连续( Contiguous ),指示这条转换表项属于一个连续表项集合,一个连续表项集合可以被缓存在一条 TLB 表项里面
51脏位修饰符( Dirty Bit Modifier , DBM ),指示页或内存块是否被修改过。
11非全局( not global , nG )。 nG 位是 1 ,表示转换不是全局的,是进程私有的,有一个关联的地址空间标识符( Address Space Identifier , ASID ); nG 位是 0 ,表示转换是全局的,是所有进程共享的,内核的页或内存块是所有进程共享的。
10访问标志( Access Flag , AF ),指示页或内存块自从相应的转换表描述符中的访问标志被设置为 0 以后是否被访问过。
8 ~ 9可共享性( SHareability , SH ), 00 表示不共享, 01 是保留值, 10 表示外部共享, 11 表示内部共享。
6 ~ 7AP[2:1] ( Data Access Permissions ,数据访问权限)。AP[2] 用来选择只读或读写, 1 表示只读, 0 表示读写; AP[1] 用来选择是否允许异常级别 0 访问, 1 表示允许异常级别 0 访问, 0 表示不允许异常级别 0 访问。
5非安全( Non-Secure , NS )。对于安全状态的内存访问,指定输出地址在安全地址映射还是在非安全地址映射。
2 ~ 4内存属性索引( memory attributes index , AttrIndx ),指定寄存器 MAIR_ELx中内存属性字段的索引,内存属性间接寄存器( Memory Attribute Indirection Register ,MAIR_ELx )有 8 个 8 位内存属性字段: Attr , n 等于 0 ~ 7 。

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

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

相关文章

应急响应 - Windows启动项分析,Windows计划任务分析,Windows服务分析

「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 Windows应急响应 一、启动项分析1、msconfig2、gpedit.msc3、注册表4、msinfo325、启动菜…

【数据结构实验】哈希表设计

【数据结构实验】哈希表设计 简介 针对本班同学中的人名设计一个哈希表&#xff0c;使得平均查找长度不超过R&#xff0c;完成相应的建表和查表程序。文末贴出了源代码。 需求分析 假设人名为中国人姓名的汉语拼音形式&#xff0c;待填入哈希表的人名共有三十个左右&#x…

汇编指令角度掌握函数调用堆栈详细过程

函数参数从右向左依次压栈push&#xff0c;call 要先把下一行指令 压栈&#xff0c; 根据如下代码思考两个问题&#xff1a; 问题一&#xff1a;main函数调用sum&#xff0c;sum执行完以后&#xff0c;怎么知道回到哪个函数中&#xff1f; 问题二&#xff1a;sum函数执行完&…

使用树状图可视化聚类

一般情况下&#xff0c;我们都是使用散点图进行聚类可视化&#xff0c;但是某些的聚类算法可视化时散点图并不理想&#xff0c;所以在这篇文章中&#xff0c;我们介绍如何使用树状图&#xff08;Dendrograms&#xff09;对我们的聚类结果进行可视化。 树状图 树状图是显示对象…

vue 项目中 向数组 添加元素 的方式

学习目标&#xff1a; 提示&#xff1a;了解 vue 向数组 添加元素 的三种方式 学习内容&#xff1a; 提示&#xff1a; vue 向数组 添加元素 的三种方式 方法&#xff1a; push()unshift()splice() 总结&#xff1a; 提示&#xff1a;这里总结相关的知识 1、push() 含义&a…

网络编程之 Socket 套接字(使用数据报套接字和流套接字分别实现一个小程序(附源码))

文章目录 1. 什么是网络编程2. 网络编程中的基本概念1&#xff09;发送端和接收端2&#xff09;请求和响应3&#xff09;客户端和服务端4&#xff09;常见的客户端服务端模型 3. Socket 套接字1&#xff09;Socket 的分类2&#xff09;Java 数据报套接字通信模型3&#xff09;J…

【Redis7】Redis7 集群(重点:哈希槽分区)

【大家好&#xff0c;我是爱干饭的猿&#xff0c;本文重点介绍Redis7 集群概述、作用、集群算法-分片-槽位slot、集群环境案例步骤、集群常用操作命令和CRC16算法。 后续会继续分享Redis7和其他重要知识点总结&#xff0c;如果喜欢这篇文章&#xff0c;点个赞&#x1f44d;&am…

ChatGPT 的数据保护盲点以及安全团队如何解决这些盲点

自成立以来的短时间内&#xff0c;ChatGPT 和其他生成式 AI 平台理所当然地赢得了终极生产力助推器的声誉。 然而&#xff0c;能够按需快速生成高质量文本的技术&#xff0c;可能同时暴露敏感的公司数据。 最近发生的一起事件&#xff0c;三星软件工程师将专有代码粘贴到 ChatG…

SpringBoot集成MyBatis-yml方式详解

SpringBoot集成MyBatis-yml方式详解 简介&#xff1a;spring boot整合mybatis开发web系统目前来说是市面上主流的框架&#xff0c;每个Java程序和springboot mybatis相处的时间可谓是比和自己女朋友相处的时间都多&#xff0c;但是springboot mybatis并没有得到你的真爱&#x…

涨点技巧: 谷歌强势推出优化器Lion,引入到Yolov8,内存更小、效率更高,秒杀Adam(W)

1.Lion优化器介绍 论文:https://arxiv.org/abs/2302.06675 代码:automl/lion at master google/automl GitHub 1.1 简单、内存高效、运行速度更快 1)与 AdamW 和各种自适应优化器需要同时保存一阶和二阶矩相比,Lion 只需要动量,将额外的内存占用减半; 2)由于 Lion…

企业批量寄件快递教程

了解企业批量寄快递操作流程之前&#xff0c;我们先来解答一下这个问题&#xff1a;什么样的企业需要批量寄快递&#xff1f; 电商行业就不提&#xff0c;本身二者就是相互依存的关系。就商务件来说&#xff0c;具体什么样的企业需要批量寄快递&#xff0c;其实很简单&#xf…

Ansys Zemax | 如何使用坐标返回功能

概述 这篇文章简单介绍了如何使用OpticStudio中的坐标返回(Coordinate Return)功能。坐标返回功能可以非常方便的使系统坐标自动返回到目标表面处。&#xff08;联系我们获取文章附件&#xff09; 介绍 在OpticStudio的序列模式中&#xff0c;我们经常会使用坐标间断(Coordinat…

Netty 源码解析(上)

序 Netty的影响力以及使用场景就不用多说了&#xff0c; 去年10月份后&#xff0c;就着手研究Netty源码&#xff0c;之前研究过Spring源码&#xff0c;MyBatis源码&#xff0c;java.util.concurrent源码&#xff0c;tomcat源码&#xff0c;发现一个特点&#xff0c;之前的源码都…

PHPStudy安装imagick扩展

phpstudy软件管理中没有自带安装imagick扩展&#xff0c;只能自己安装了。 下面将用几个步骤来进行phpstudy imagick安装&#xff1a; 1.下载imagick 下载地址 ImageMagick – Download 下载电脑版本相对的64/32位&#xff0c;最新的版本 2.安装imagick 双击刚刚下载的文件…

三维可视化如何助力智慧城市建设?

在智慧城市建设中&#xff0c;如何将城市各类数据可视化是一大难题&#xff0c;目前市面上可视化的方法很多&#xff0c;如传统的三维建模、地物模型、建筑模型等。 这些方法各有利弊&#xff0c;从其实现方式来看&#xff1a; GIS/BIM是将所有的空间信息全部整合到一起; 从技术…

第三章 法的渊源与法的分类

目录 第一节 法的渊源的分类 一、法的渊源释义二、法的渊源种类 第二节 正式法源 一、正式法源的含义二、当代中国的正式法源三、正式法源的一般效力原则 第三节 非正式法源 一、当代中国的非正式法源 第四节 法的分类 一、法的一般分类二、法的特殊分类 第一节 法的渊源的…

SSH连接本地centerOS系统配置

SSH连接本地linux系统 前提&#xff1a;安装好centerOS系统并能启动 目标&#xff1a;连通外网并设置SSH 1.网卡配置文件路径 打开linux本地终端 快捷键一般是ctrlaltf2(f1~f3) 这里是管理员登录,密码是隐藏式的输入(输入看不见) 这样就显示成功登录了&#xff01; 下面查…

Unity InputSystem (二)

InputActionAssets 是包含输入操作以及其关联的绑定和控制方案的资源&#xff0c;文件以 .inputactions 文件扩展名存储&#xff0c;并且是以纯 json 文件存储的。 创建 InputActionAssets 文件 在 Assets 窗口内选择创建 InputActions 文件 ControlSchemes 控制的解决方案…

上市公司杰创智能携手甄云,启动供应链采购数字化升级

近日&#xff0c;A股上市企业杰创智能科技股份有限公司&#xff08;以下简称“杰创智能”&#xff09;联合甄云科技举办数字化采购管理项目启动会&#xff0c;双方企业高层、相关部门负责人及项目团队成员参加了此次活动。 会上&#xff0c;就杰创智能的数字化采购管理系统建设…

Flink Table API 和 Flink-SQL使用详解

Flink Table API 和 Flink-SQL使用详解 1.Table API & Flink SQL-核心概念 ​ Apache Flink 有两种关系型 API 来做流批统一处理&#xff1a; Table API Table API 是用于 Scala 和 Java 语言的查询API&#xff0c;它可以用一种非常直观的方式来组合使用选取、过滤、join…