鸿蒙内核源码分析 (协处理器篇) | CPU 的好帮手

本篇很重要,对CP15协处理所有16个寄存器一一介绍,可能是全网介绍CP15最全面的一篇,鸿蒙内核的汇编部分(尤其开机启动)中会使用,熟练掌握后看汇编代码将如虎添翼。

协处理器

协处理器 (co-processor) 顾名思义是协助主处理器完成工作,例如浮点、图像、音频处理这一类外围工作。角色相当于老板的助理/秘书,咱皇上身边的人,专干些咱皇上又不好出面的脏活累活,您可别小看了这个角色,权利不大但能力大,是能通天的人,而且老板越大,身边这样的人还不止一个。

在 arm 的协处理器设计中,最多可以支持 16 个协处理器,通常被命名为 cp0cp15,本篇主要说第16号协处理器 cp15

CP15

关于 cp15详细介绍见于 << ARM体系架构参考手册(ARMv7-A/R).pdf >> 的 B3.17
cp15 一共有 1632位的寄存器,其编号为C0 ~ C15 ,用来控制cacheTCM和存储器管理。cp15 寄存器都是复合功能寄存器,不同功能对应不同的内存实体,全由访问指令的参数来决定,对于 armv7 架构而言,A 系列和 R 系列是统一设计的,A 系列带有 MMU 相关的控制,而 R 系列带有 MPU 相关控制,针对不同的功能需要做区分,同时又因为协处理器 cp15 只支持 16 个寄存器,而需要支持的功能较多,所以通过同一寄存器不同功能的方式来满足需求。

mcr | mrc 指令

armv7 中对于协处理器的访问,CP15的寄存器只能被MRCMCR(Move to Coprocessor from ARM Register )指令访问。MCR表示将 arm 核心寄存器中的值的写到 cp15 寄存器中,MRC 从 cp15 寄存器中读到 arm 核心寄存器中,大部分指令都需要在 PL1 以及更高的特权级下才能正常执行,这是因为 cp15 协处理器大多都涉及到系统和内存的设置,user 模式没有操作权限,user 模式仅能访问 cp15 中有限的几个寄存器比如:ISB、DSB、DMB、TPIDRURW、TPIDRURO 寄存器。

从 `cp**` 寄存器中读到 `arm` 核心寄存器中
MRC<cond> <coproc>, <opc1>, <Rt>, <CRn>, <CRm>{, <opc2>}
  • cond : 指令后缀,表示条件执行,关于条件执行可以参考 arm状态寄存器
  • coproc :协处理器的名称,cp0~cp15 分别对应名称 p0~p15
  • opc1 :对于 cp15 而言,这一个参数一般为0。
  • Rt :arm 的通用寄存器
  • CRn :与 arm 核心寄存器交换数据的核心寄存器名,c0~c15
  • CRm :需要额外操作的协处理器的寄存器名,c0~c15,针对多种功能的 cp15 寄存器,需要使用 CRm 和 opc2 来确定 CRn 对应哪个寄存器实体。
  • opc2 :可选,与 CRm搭配使用,同样是决定多功能寄存器中指定实体。

啥玩意,太抽象没看懂,后面直接上内核代码就懂了,先看16个寄存器的功能介绍表

c0 寄存器

c0 寄存器提供处理器和特征识别 ,内核宏定义为,可参考图理解

/*!* Identification registers (c0)	| c0 - 身份寄存器*/
#define MIDR                CP15_REG(c0, 0, c0, 0)    /*! Main ID Register | 主ID寄存器 */
#define MPIDR               CP15_REG(c0, 0, c0, 5)    /*! Multiprocessor Affinity Register | 多处理器关联寄存器给每个CPU制定一个逻辑地址*/
#define CCSIDR              CP15_REG(c0, 1, c0, 0)    /*! Cache Size ID Registers | 缓存大小ID寄存器*/	
#define CLIDR               CP15_REG(c0, 1, c0, 1)    /*! Cache Level ID Register | 缓存登记ID寄存器*/	
#define VPIDR               CP15_REG(c0, 4, c0, 0)    /*! Virtualization Processor ID Register | 虚拟化处理器ID寄存器*/	
#define VMPIDR              CP15_REG(c0, 4, c0, 5)    /*! Virtualization Multiprocessor ID Register | 虚拟化多处理器ID寄存器*/	

c1 寄存器

c1 为系统控制寄存器

/*!* System control registers (c1)	| c1 - 系统控制寄存器 各种控制位(可读写)*/
#define SCTLR               CP15_REG(c1, 0, c0, 0)    /*! System Control Register | 系统控制寄存器*/	
#define ACTLR               CP15_REG(c1, 0, c0, 1)    /*! Auxiliary Control Register | 辅助控制寄存器*/	
#define CPACR               CP15_REG(c1, 0, c0, 2)    /*! Coprocessor Access Control Register | 协处理器访问控制寄存器*/	

/// 读取CP15的系统控制寄存器到 R0寄存器
STATIC INLINE UINT32 OsArmReadSctlr(VOID)
{UINT32 val;__asm__ volatile("mrc p15, 0, %0, c1,c0,0" : "=r"(val));return val;
}
/// R0寄存器写入CP15的系统控制寄存器
STATIC INLINE VOID OsArmWriteSctlr(UINT32 val)
{__asm__ volatile("mcr p15, 0, %0, c1,c0,0" ::"r"(val));__asm__ volatile("isb" ::: "memory");
}

解读

  • 从图中找到 c1-0-c0-0行,后边的备注是 SCTLR, System Control Register 系统控制寄存器,其操作模式是支持 Read/Write
  • %0表示 r0 寄存器,注意这个寄存器是CPU的寄存器,: “=r”(val) 意思向编译器声明,会修改R0寄存器的值,改之前提前打好招呼,都是绅士文明人。其实编译器的功能是非常强大的,不仅仅是大家普遍认为的只是编译代码的工具而已。OsArmReadSctlr的含义就是读取CP15的系统控制寄存器到R0寄存器。
  • volatile的意思还告诉编译器,不要去优化这段代码,原封不动的生成目标指令。
  • “isb” ::: “memory” 还是告诉编译器内存的内容要被更改了,需要无效所有Cache,并访问实际的内容,而不是Cache!
  • CRn | CRm | opc2 是一套组合拳,c7-0-c10-4 c7-0-c10-5 都表示不同的功能含义

c2、c3 寄存器

/*!* Memory protection and control registers (c2 & c3) | c2 - 传说中的TTB寄存器,主要是给MMU使用 c3 - 域访问控制位*/
#define TTBR0               CP15_REG(c2, 0, c0, 0)    /*! Translation Table Base Register 0 | 转换表基地址寄存器0*/	
#define TTBR1               CP15_REG(c2, 0, c0, 1)    /*! Translation Table Base Register 1 | 转换表基地址寄存器1*/	
#define TTBCR               CP15_REG(c2, 0, c0, 2)    /*! Translation Table Base Control Register | 转换表基地址控制寄存器*/	
#define DACR                CP15_REG(c3, 0, c0, 0)    /*! Domain Access Control Register | 域访问控制寄存器*/	

看段代码

STATIC INLINE UINT32 OsArmReadTtbr0(VOID)
{UINT32 val;__asm__ volatile("mrc p15, 0, %0, c2,c0,0" : "=r"(val));return val;
}
STATIC INLINE VOID OsArmWriteTtbr0(UINT32 val)
{__asm__ volatile("mcr p15, 0, %0, c2,c0,0" ::"r"(val));__asm__ volatile("isb" ::: "memory");
}
STATIC INLINE UINT32 OsArmReadTtbr1(VOID)
{UINT32 val;__asm__ volatile("mrc p15, 0, %0, c2,c0,1" : "=r"(val));return val;
}
STATIC INLINE VOID OsArmWriteTtbr1(UINT32 val)
{__asm__ volatile("mcr p15, 0, %0, c2,c0,1" ::"r"(val));__asm__ volatile("isb" ::: "memory");
}

c2寄存器负责存页表的基地址,即一级映射描述符表的基地址。还记得吗?每个进程的页表都是独立的!c2值一变,当前使用的页表就发生了变化,页表变化意味着虚拟地址和物理地址的映射关系发生了变化。那么什么情况下会修改里面的值呢?很容易想到只有在进程切换时发生的mmu上下文切换,直接看代码吧!

/// mmu 上下文切换
VOID LOS_ArchMmuContextSwitch(LosArchMmu *archMmu)
{UINT32 ttbr;UINT32 ttbcr = OsArmReadTtbcr();//读取TTB寄存器的状态值if (archMmu) {ttbr = MMU_TTBRx_FLAGS | (archMmu->physTtb);//进程TTB物理地址值/* enable TTBR0 */ttbcr &= ~MMU_DESCRIPTOR_TTBCR_PD0;//使能TTBR0} else {ttbr = 0;/* disable TTBR0 */ttbcr |= MMU_DESCRIPTOR_TTBCR_PD0;}
#ifdef LOSCFG_KERNEL_VM/* from armv7a arm B3.10.4, we should do synchronization changes of ASID and TTBR. */OsArmWriteContextidr(LOS_GetKVmSpace()->archMmu.asid);//这里先把asid切到内核空间的IDISB; //指令必须同步 ,清楚流水线中未执行指令
#endifOsArmWriteTtbr0(ttbr);//通过r0寄存器将进程页面基址写入TTBISB; //指令必须同步OsArmWriteTtbcr(ttbcr);//写入TTB状态位ISB; //指令必须同步
#ifdef LOSCFG_KERNEL_VMif (archMmu) {OsArmWriteContextidr(archMmu->asid);//通过R0寄存器写入进程标识符至C13寄存器ISB;}
#endif
}

至于具体内核哪些地方会触发到 mmu的切换,可前往翻看 (进程切换篇)

c4 寄存器

c4 没有用于任何 ARMv7 实现,这么不待见4,难道原因跟中国人一样觉得数字不吉利 ,但老师教的老外是不喜欢 13 啊 , 但c13确很重要

c5 c6 寄存器

c5和c6寄存器提供内存系统故障报告。此外,c6还提供了MPU区域寄存器。这一类寄存器在软件排错时可以提供非常大的帮助,比如通过 DFSR(数据状态寄存器)、IFSR(指令状态寄存器) 的 status bits 可以查到系统 abort 类型,内核中的缺页异常就是通过该寄存器传递异常地址,从而分配页面的。

/*!* Memory system fault registers (c5 & c6)	| c5 - 内存失效状态 c6 - 内存失效地址*/
#define DFSR                CP15_REG(c5, 0, c0, 0)    /*! Data Fault Status Register | 数据故障状态寄存器 */			
#define IFSR                CP15_REG(c5, 0, c0, 1)    /*! Instruction Fault Status Register | 指令故障状态寄存器*/	
#define DFAR                CP15_REG(c6, 0, c0, 0)    /*! Data Fault Address Register | 数据故障地址寄存器*/			
#define IFAR                CP15_REG(c6, 0, c0, 2)    /*! Instruction Fault Address Register | 指令错误地址寄存器*/	

c7 寄存器

c7寄存器提供高速缓存维护操作和内存屏障操作。

c8 寄存器

c8 寄存器提供 TLB 维护功能

TLB是硬件上的一个cache,因为页表一般都很大,并且存放在内存中,所以处理器引入MMU后,读取指令、数据需要访问两次内存:首先通过查询页表得到物理地址,然后访问该物理地址读取指令、数据。为了减少因为MMU导致的处理器性能下降,引入了TLB,可翻译为“地址转换后援缓冲器”,也可简称为“快表”。简单地说,TLB就是页表的Cache,其中存储了当前最可能被访问到的页表项,其内容是部分页表项的一个副本。只有在TLB无法完成地址翻译任务时,才会到内存中查询页表,这样就减少了页表查询导致的处理器性能下降。详细看

照着图说吧,步骤是这样的。

  • 图中的page table的基地址就是上面TTB寄存器值,整个page table非常大,有多大接下来会讲,所以只能存在内存里,TTB中只是存一个开始位置而已。
  • 虚拟地址是程序的地址逻辑地址,也就是喂给CPU的地址,必须经过MMU的转换后变成物理内存才能取到真正的指令和数据。
  • TLBpage table的迷你版,MMU先从TLB里找物理页,找不到了再从page table中找,从page table中找到后会放入TLB中,注意这一步非常非常的关键。因为page table是属于进程的会有很多个,而TLB只有一个,不放入就会出现多个进程的page table都映射到了同一个物理页框而不自知。一个物理页同时只能被一个page table所映射。但除了TLB的唯一性外,要做到不错乱还需要了一个东西,就是进程在映射层面的唯一标识符 - asid,具体可前往翻看 (进程切换篇) 有详细说明。

c9 寄存器

c9 寄存器主要为 cache、分之预测 和 tcm 保留功能,这些保留功能由处理的实现决定

c10 寄存器

c10 寄存器主要提供内存重映射和 TLB 控制功能

c11 寄存器

c11 寄存器主要提供 TCM 和 DMA 的保留功能,这些保留功能由处理的实现决定

c12 寄存器

c12 安全扩展寄存器

c13 寄存器

c13 寄存器提供进程、上下文以及线程ID处理功能

/*!* Process, context and thread ID registers (c13) | c13 - 进程标识符*/
#define FCSEIDR             CP15_REG(c13, 0, c0, 0)    /*! FCSE Process ID Register | FCSE(Fast Context Switch Extension,快速上下文切换)进程ID寄存器 位于CPU和MMU之间*/
#define CONTEXTIDR          CP15_REG(c13, 0, c0, 1)    /*! Context ID Register | 上下文ID寄存器*/	
#define TPIDRURW            CP15_REG(c13, 0, c0, 2)    /*! User Read/Write Thread ID Register | 用户读/写线程ID寄存器*/	
#define TPIDRURO            CP15_REG(c13, 0, c0, 3)    /*! User Read-Only Thread ID Register | 用户只读写线程ID寄存器*/	
#define TPIDRPRW            CP15_REG(c13, 0, c0, 4)    /*! PL1 only Thread ID Register | 仅PL1线程ID寄存器*/

c14 寄存器

c14 寄存器提供通用定时器扩展的保留功能

c15 寄存器

ARMv7 保留 c15 用于实现定义的目的,并且不对 c15 编码的使用施加任何限制。
意思就是可以将他当通用寄存器来使用 语法: c15 0-7 c0-c15 0-7

鸿蒙全栈开发全新学习指南

也为了积极培养鸿蒙生态人才,让大家都能学习到鸿蒙开发最新的技术,针对一些在职人员、0基础小白、应届生/计算机专业、鸿蒙爱好者等人群,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线【包含了大厂APP实战项目开发】

本路线共分为四个阶段:

第一阶段:鸿蒙初中级开发必备技能

在这里插入图片描述

第二阶段:鸿蒙南北双向高工技能基础:gitee.com/MNxiaona/733GH

第三阶段:应用开发中高级就业技术

第四阶段:全网首发-工业级南向设备开发就业技术:gitee.com/MNxiaona/733GH

《鸿蒙 (Harmony OS)开发学习手册》(共计892页)

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:gitee.com/MNxiaona/733GH

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

基于ArkTS 开发

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

鸿蒙开发面试真题(含参考答案):gitee.com/MNxiaona/733GH

鸿蒙入门教学视频:

美团APP实战开发教学:gitee.com/MNxiaona/733GH

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:gitee.com/MNxiaona/733GH

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

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

相关文章

韵搜坊(全栈)-- 前后端初始化

文章目录 前端初始化后端初始化 前端初始化 使用ant design of vue 组件库 官网快速上手&#xff1a;https://www.antdv.com/docs/vue/getting-started-cn 安装脚手架工具 进入cmd $ npm install -g vue/cli # OR $ yarn global add vue/cli创建一个项目 $ vue create ant…

社交媒体数据恢复:默往

如果你在默往社交软件中丢失了重要的数据&#xff0c;不要着急&#xff0c;以下是一些步骤可以帮助你进行数据恢复&#xff1a; 登录账号&#xff1a;首先&#xff0c;你需要登录默往社交软件账号&#xff0c;确保你已经登录了正确的账号&#xff0c;因为如果你登录了错误的账号…

弘君资本策略:股指预计保持震荡上扬格局 关注公用事业、电网设备等板块

弘君资本指出&#xff0c;周一A股商场探底上升、小幅震动收拾&#xff0c;早盘股指低开后震动回落&#xff0c;沪指盘中在3126点附近取得支撑&#xff0c;午后股指企稳上升&#xff0c;盘中电网设备、公用事业、电力以及工程建造等职业体现较好&#xff1b;半导体、互联网以及软…

PXE+Kickstart无人值守安装安装Centos7.9

文章目录 一、什么是PXE1、简介2、工作模式3、工作流程 二、什么是Kickstart1、简介2、触发方式 三、无人值守安装系统工作流程四、实验部署1、环境准备2、服务端&#xff1a;关闭防火墙和selinux3、添加一张仅主机的网卡4、配置仅主机的网卡4.1、修改网络连接名4.2、配IP地址4…

差异基因散点图绘制教程

差异基因散点图绘制教程 本期教程 小杜的生信笔记&#xff0c;自2021年11月开始做的知识分享&#xff0c;主要内容是R语言绘图教程、转录组上游分析、转录组下游分析等内容。凡事在社群同学&#xff0c;可免费获得自2021年11月份至今全部教程&#xff0c;教程配备事例数据和相…

最新版Ceph( Reef版本)块存储简单对接k8s(上集)

当前ceph 你的ceph集群上执行 1.创建名为k8s-rbd 的存储池 ceph osd pool create k8s-rbd 64 642.初始化 rbd pool init k8s-rbd3 创建k8s访问块设备的认证用户 ceph auth get-or-create client.kubernetes mon profile rbd osd profile rbd poolk8s-rbd部署 ceph-rbd-csi c…

快速学习SpringAi

Spring AI是AI工程师的一个应用框架&#xff0c;它提供了一个友好的API和开发AI应用的抽象&#xff0c;旨在简化AI应用的开发工序&#xff0c;例如开发一款基于ChatGPT的对话应用程序。通过使用Spring Ai使我们更简单直接使用chatgpt 1.创建项目 jdk17 引入依赖 2.依赖配置 …

同城组局同城活动找搭子小程序JAVA源码面芽组局的实现方案

功能概述 基于微信小程序开发的一款软件&#xff0c;支持用户动态发布、私信聊天关注、礼物充值打赏、发起活动组局、用户报名参与、支持商家入驻&#xff0c;对接广告功能等。 活动发布&#xff1a;用户可以在平台上发布各种类型的活动&#xff0c;如户外徒步、音乐会观赏、…

AI应用案例:会议纪要自动生成

以腾讯会议转录生成的会议记录为研究对象&#xff0c;借助大模型强大的语义理解和文本生成等能力&#xff0c;利用指令和文本向量搜索实现摘要总结、要点提取、行动项目提取、会议纪要生成等过程&#xff0c;完成会议纪要的自动总结和生成&#xff0c;降低人工记录和整理时间成…

React 第三十章 React 和 Vue 描述页面的区别

面试题&#xff1a;React 和 Vue 是如何描述 UI 界面的&#xff1f;有一些什么样的区别&#xff1f; 标准且浅显的回答&#xff1a; React 中使用的是 JSX&#xff0c;Vue 中使用的是模板来描述界面 前端领域经过长期的发展&#xff0c;目前有两种主流的描述 UI 的方案&#xf…

Q1季度电饭煲家电行业线上市场(京东天猫淘宝)销售数据排行榜

鲸参谋监测的2024年Q1季度线上电商平台&#xff08;天猫淘宝京东&#xff09;电饭煲家电销售数据已出炉&#xff01; 今年Q1季度&#xff0c;电饭煲销售成绩不如预期。根据鲸参谋数据显示&#xff0c;今年Q1季度在线上电商平台&#xff08;淘宝天猫京东&#xff09;电饭煲销量…

三种有效方法:快速将视频格式转换mp4格式

在当今数字化时代&#xff0c;视频文件的格式多种多样&#xff0c;而将视频转换为MP4格式是一种常见的需求。MP4格式具有广泛的兼容性&#xff0c;适用于多种设备和平台&#xff0c;因此经常被选择作为视频文件的输出格式。 无论是为了在移动设备上观看视频&#xff0c;还是为…

照妖镜api接口,查询旺旺的降权、黑号举报数据(全网实时更新)

照妖镜api接口&#xff0c;查询旺旺的降权、黑号举报数据&#xff08;全网实时更新&#xff09; 照妖镜查号功能说明&#xff1a; 1.照妖镜查号功能的打标信息为商家主动共享&#xff0c;不对相关使用效果或纠纷承担责任&#xff1b; 2.本功能于查询互联网用户防止电信诈骗&…

NSS【web】刷题

[SWPUCTF 2021 新生赛]jicao 类型&#xff1a;PHP、代码审计、RCE 主要知识点&#xff1a;json_decode()函数 json_decode()&#xff1a;对JSON字符串解码&#xff0c;转换为php变量 用法&#xff1a; <?php $json {"ctf":"web","question"…

YOLOV8实战-和平精英敌我检测

YOLOV8实战&#xff0c;从环境配置、数据准备、数据标注、模型训练、模型导出到源码分享 前言&#xff1a;效果展示图片展示视频展示 简介&#xff1a;**【YOLOV8是啥&#xff1f;】****【YOLOV8能干啥&#xff1f;有啥应用场景&#xff1f;】** 一、环境准备1、新建一个虚拟环…

Linux中的网络隔离功能 netns

Network Namespace&#xff08;netns&#xff09; 是Linux内核提供的一项实现网络隔离的功能&#xff0c;它能隔离多个不同的网络空间&#xff0c;并且各自拥有独立的网络协议栈。通过 namespace 可以隔离容器的进程 PID、文件系统挂载点、主机名等多种资源&#xff0c;它可以为…

vscode调试Electron+ts

调试Electronjs 调试Electronjs: https://www.electronjs.org/zh/docs/latest/tutorial/debugging-vscode 调试Electronts 首先看一下&#xff0c;我的目录结构。目录结构决定了launch.json中的路径部分。我将在项目根目录下进行调试&#xff0c;项目根目录下包含electron代码…

数据可视化(十一):Pandas餐饮信息表分析——交叉表、离群点分析,多维分析等高级操作

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

golang创建式设计模式------单例模式

目录导航 1.单例模式1)什么是单例模式 2)使用场景3)实现方式1.懒汉式单例模式2.饿汉式3.双重检查式4.sysc.Once式 4)实践案例5)优缺点分析 1.单例模式 1)什么是单例模式 单例模式(Singleton Pattern)是一种常用的设计模式。单例模式的类提供了一种访问其唯一对象的方法&#…

【数据结构】线性表--顺序表(二)

文章目录 1、什么是线性表2、线性表的基本操作3、顺序表3.1、顺序表的定义3.2、顺序表的实现方式&#xff1a;静态分配3.3、顺序表的实现方式&#xff1a;动态分配3.4、顺序表的特点3.5、顺序表的初始化与插入操作3.6、顺序表的删除与查询 1、什么是线性表 ​ 线性表是具有相同…