HarmonyOS鸿蒙Next内核源码分析(工作模式篇) | 鸿蒙开机代码长什么样 ? | 中文注解HarmonyOS源码 | v36.01

HarmonyOS鸿蒙Next内核源码分析(工作模式篇) | 鸿蒙开机代码长什么样 ? | 中文注解HarmonyOS源码 | v36.01 百万汉字注解 >> 精读内核源码,中文注解分析, 深挖地基工程,大脑永久记忆,四大码仓每日同步更新< Gitee | Github | CSDN | Coding >

百篇博客分析 >> 故事说内核,问答式导读,生活式比喻,表格化说明,图形化展示,多站点每日同步更新< OSCHINA | CSDN | WeHarmony >

系列篇硬件部分说明基于ARM720T.pdf文档.

本篇说清楚CPU的工作模式

读本篇之前建议先读鸿蒙内核源码分析(总目录)其他篇.

正如一个互联网项目的后台管理系统有权限管理一样,CPU工作是否也有权限(模式)? 一个成熟的软硬件架构,肯定会有这些设计,只是大部分人不知道,也不需要知道,老百姓就干好老百姓的活就行了,有工作能吃饱饭就知足了,宫的事你管那么多干嘛,你也管不了.

应用程序就只关注应用功能,业务逻辑相关的部分就行了,底层实现对应用层屏蔽的越干净系统设计的就越优良.

但鸿蒙内核源码分析系列篇的定位就是要把整个底层解剖,全部掰开,看看宫里究竟发生了么事.从本篇开始要接触大量的汇编的代码,将鸿蒙内核的每段汇编代码一一说明白.如此才能知道最开始的开始发生了什么,最后的最后又发生了什么.

七种模式

先看一张图,图来源于 ARM720T.pdf 第43页,在ARM体系中,CPU工作在以下七种模式中:

  • 用户模式(usr):属于正常的用户模式,ARM处理器正常的程序执行状态。
  • 快速中断模式(fiq):用于处理快速中断,对高速数据传输或通道处理
  • 外部中断模式(irq):对一般情况下的中断进行处理。
  • 管理模式(svc):属于操作系统使用的保护模式,处理软件中断swi reset。
  • 数据访问终止模式(abt):当数据或指令预取终止时进入该模式,可用于处理存储器故障、实现虚拟存储器和存储器保护。
  • 系统模式(sys):运行具有特权的操作系统任务。
  • 未定义指令中止模式(und):处理未定义的指令陷阱,当未定义的指令执行时进入该模式,可用于支持硬件协处理器的软件仿真。

除了用户模式外,其它六种均为特权模式或者叫异常模式。每种模式都有自己独立的入口和独立的运行栈空间。系列篇之CPU篇已介绍过只要提供了入口函数和运行空间,CPU就可以干活了。入口函数解决了指令来源问题,运行空间解决了指令的运行问题。

在多核情况下,每个CPU核的每种异常模式都有自己独立的栈空间。注意是异常模式下的栈空间,用户模式的栈空间是由用户(应用)程序提供的。

如何让这七种模式能流畅的跑起来呢? 至少需要以下解决三个基本问题.

  • 栈空间是怎么申请的?申请了多大?
  • 被切换中的模式代码放在哪里?谁来安排它们放在哪里?
  • 模式之间是怎么切换的?状态怎么保存?

本篇代码来源于鸿蒙内核源码之reset_vector_mp.S,点击查看

这个汇编文件大概 500多行,非常重要,本篇受限于篇幅只列出一小部分,说清楚以上三个问题.系列其余篇中将详细说明每段汇编代码的作用和实现,可前往查阅.

1.异常模式栈空间怎么申请?

鸿蒙是如何给异常模式申请栈空间的

代码解读
  • 六种异常模式都有自己独立的栈空间
  • 每种模式的OS_EXC_***_STACK_SIZE栈大小都不一样,最大是管理模式(svc)8K,最小的只有40个字节. svc模式为什么要这么大呢? 因为开机代码和系统调用代码的运行都在管理模式,系统调用的函数实现往往较复杂,最大不能超过8K. 例如:某个系统调用中定义一个8K的局部变量,内核肯定立马闪蹦.因为栈将溢出,处理异常的程序出现了异常,后面就再也没人兜底了,只能是死局.
  • 鸿蒙是支持多核处理的,CORE_NUM表明,每个CPU核的每种异常模式都有自己的独立栈空间.注意理解这个是理解内核代码的基础.否则会一头雾水

2.异常模式入口地址在哪?

再看一张图,图来源于 ARM720T.pdf 第56页

这就是一切一切的开始,指定所有异常模式的入口地址表,这就是规定,没得商量的.在低地址情况下.开机代码就是放在 0x00000000的位置, 触发开机键后,硬件将PC寄存器置为0x00000000,开始了万里长征的第一步.在系统运行过程中就这么来回跳.

b reset_vector                    @开机代码
b _osExceptUndefInstrHdl          @异常处理之CPU碰到不认识的指令
b _osExceptSwiHdl                 @异常处理之软中断
b _osExceptPrefetchAbortHdl       @异常处理之取指异常
b _osExceptDataAbortHdl           @异常处理之数据异常
b _osExceptAddrAbortHdl           @异常处理之地址异常
b OsIrqHandler                    @异常处理之硬中断
b _osExceptFiqHdl                 @异常处理之快中断

以上是各个异常情况下的入口地址,在reset_vector_mp.S中都能找到,经过编译链接后就会变成

b 0x00000000                     @开机代码
b 0x00000004                      @异常处理之CPU碰到不认识的指令
b 0x00000008                      @异常处理之:软中断
b 0x0000000C                      @异常处理之:取指异常
b 0x00000010                      @异常处理之:数据异常
b 0x00000014                      @异常处理之:地址异常
b 0x00000018                      @异常处理之:硬中断
b 0x0000001C                      @异常处理之:快中断

不管是主动切换的异常,还是被动切换的异常,都会先跳到对应的入口去处理.每个异常的代码都起始于汇编,处理完了再切回去.举个例子:

某个应用程序调用了系统调用(比如创建定时器),会经过以下大致过程:

  • swi指令将用户模式切换到管理模式(svc)
  • 在管理模式中先保存用户模式的现场信息(R0-R15寄存器值入栈)
  • 获取系统调用号,知道是调用了哪个系统调用
  • 查询系统调用对应的注册函数
  • 执行真正的创建定时器函数
  • 执行完成后,恢复用户模式的现场信息(R0-R15寄存器值出栈)
  • 跳回用户模式继续执行

各异常处理代码很多,不一一列出,本篇只列出开机代码,请尝试读懂鸿蒙内核开机代码,后续讲详细说明每行代码的用处.

开机代码
reset_vector

mov r0, #                    @r0
mcr p15, , r0, c13, c0,     @c0,c13 ,C13为进程标识符 含义见 ARM720T.PDF 第页
@禁用MMU, id缓存
mrc p15, , r0, c1, c0,      @r0 c1 ,c1寄存器详细解释见第页
bic r0, #()            @位清除指令,清除r0的第位
bic r0, #( )          @清除第和位 ,禁止 MMU和缓存 位MMU enabledisable 位Cache enabledisable
mcr p15, , r0, c1, c0,      @c1r0

@物理地址和虚拟地址的增量
adr r11, pa_va_offset    @将基于PC相对偏移的地址pa_va_offset值读取到寄存器R11
ldr r0, [r11]              @将R11的值给r0
sub r11, r11, r0            @r11 r11 r0

mrc p15, , r12, c0, c0,        @获取CPUID
r12, r12, #MPIDR_CPUID_MASK  @r12经过掩码过滤
cmp r12, #               @当前是否为号CPU
bne secondary_cpu_init      @不是号主CPU则调用secondary_cpu_init

adr r4, __exception_handlers     @r4获得加载基地址
ldr r5, SYS_MEM_BASE             @r5获得物理基地址
subs r12, r4, r5                 @r12r4r5 加载地址和物理地址的增量
beq reloc_img_to_bottom_done

异常的优先级

当同时出现多个异常时,该响应哪一个呢?就涉及到了异常的优先级,如下

  • Reset (最高优先级).
  • Data Abort.
  • FIQ.
  • IRQ.
  • Prefetch Abort.
  • Undefined Instruction, SWI (最低优先级).

可以看出swi的优先级最低,swi就是软件中断,系统调用就是通过它来实现的.

3.异常模式怎么切换?

写应用程序经常会用到状态,来记录各种分支逻辑,传递参数.这么多异常模式,相互切换,中间肯定会有很多的状态需要保存.比如:如何能知道当前运行在哪种模式下?怎么查?去哪里查呢?

答案是: CPSR 和 SPSR

CPSR:程序状态寄存器(current program status register) (当前程序状态寄存器),在任何处理器模式下被访问。

SPSR:程序状态保存寄存器(saved program status register),每一种处理器模式下都有一个状态寄存器SPSR,SPSR用于保存CPSR的状态,以便异常返回后恢复异常发生时的工作状态。当特定 的异常中断发生时,这个寄存器用于存放当前程序状态寄存器的内容。在异常中断退出时,可以用SPSR来恢复CPSR。

这些寄存器:

  • 保存有关最近执行的ALU操作的信息
  • 控制中断的启用和禁用
  • 设置处理器操作模式
7 回复

值得收藏慢慢看

更多关于HarmonyOS鸿蒙Next内核源码分析(工作模式篇) | 鸿蒙开机代码长什么样 ? | 中文注解HarmonyOS源码 | v36.01的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


我们要学习的地方很多呢,嘻嘻

似乎挺难的,无奈了

一直觉得这内容有内涵

百万汉字注解 百篇博客分析 精读鸿蒙源码 深挖地基工程

https://gitee.com/weharmony/kernel_liteos_a_note

HarmonyOS鸿蒙Next内核的工作模式主要分为用户模式和内核模式。用户模式下运行应用程序,内核模式下运行操作系统核心功能。鸿蒙开机代码主要包括启动引导程序(Bootloader)、内核初始化、系统服务启动等部分。Bootloader负责硬件初始化和加载内核,内核初始化包括内存管理、进程调度、设备驱动等。系统服务启动后,鸿蒙进入用户模式,运行应用程序。源码中的中文注解有助于理解代码逻辑和功能实现。v36.01版本可能包含性能优化、新功能添加或bug修复。具体源码分析需结合代码文件和版本更新日志。

HarmonyOS鸿蒙Next内核的开机代码主要涉及系统初始化、硬件检测和系统服务启动等关键步骤。具体流程包括:

  1. CPU初始化:设置处理器状态,启动核心调度;
  2. 内存管理:初始化内存映射,分配内核堆栈;
  3. 设备驱动加载:检测并初始化硬件设备;
  4. 系统服务启动:启动任务调度、文件系统等核心服务;
  5. 用户界面启动:加载图形界面和服务框架。

源码中通过宏定义和函数调用实现模块化设计,关键部分有中文注解,便于开发者理解。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!