百万汉字注解 >> 精读内核源码,中文注解分析, 深挖地基工程,大脑永久记忆,四大码仓每日同步更新< gitee | github | csdn | coding >
百篇博客分析 >> 故事说内核,问答式导读,生活式比喻,表格化说明,图形化展示,主流站点定期更新中< oschina | csdn | 掘金 | weharmony >
鸿蒙内核源码分析系列篇至少已经有五篇涉及到了汇编,请自行翻看,但还是远远不够,要写十五篇,彻底摸透,现在才刚刚开始,本篇先整理鸿蒙内核所有汇编文件和大概说明文件的作用,后续一块一块来剥,不把这些汇编剥个精光不罢休.
鸿蒙所有汇编文件如下:
直接点击可以查看注解源码,有些站点会把链接去除,没办法,可直接去各大站点搜"鸿蒙内核源码分析",找到源码注解.
OsSRSaveRegister
和 OsSRRestoreRegister
汇编实现将用户空间数据src 拷贝到内核空间 dst
// errno_t _arm_get_user(void *dst, const void *src, size_t dstTypeLen, size_t srcTypeLen)
FUNCTION(_arm_get_user)
stmdb sp!, {
r0, r1, r2, r3, lr} @四个参数入栈,保存LR
cmp r2, #0 @r2 和 0比较
beq .Lget_user_return @相等 跳到Lget_user_return 直接返回
cmp r2, r3 @r2 和 r3比较
bne .Lget_user_err @不等,说明函数要返回错误
cmp r2, #1 @r2 和 1比较
bhi .Lget_user_half @if(dstTypeLen>1) 跳转到Lget_user_half
.Lget_user_byte: @按字节拷贝数据
0: ldrbt r3, [r1], #0 @r3=*r1
1: strb r3, [r0], #0 @*r0=r3
b .Lget_user_return
.Lget_user_half:
cmp r2, #2 @r2 和 2比较
bhi .Lget_user_word @if(dstTypeLen>2) Lget_user_word
2: ldrht r3, [r1], #0 @完成最后一个字节的拷贝
3: strh r3, [r0], #0 @完成最后一个字节的拷贝
b .Lget_user_return
.Lget_user_word:
cmp r2, #4 @r2 和 4比较
bhi .Lget_user_err @if(dstTypeLen>4) 跳转到Lget_user_err
4: ldrt r3, [r1], #0
5: str r3, [r0], #0
.Lget_user_return: @返回锚点
ldmia sp!, {
r0, r1, r2, r3, lr} @保存的内容出栈,恢复各寄存器值
mov r0, 0 @r0保存返回值为0
bx lr @跳回调用函数继续执行,_arm_get_user到此结束!
.Lget_user_err:
ldmia sp!, {
r0, r1, r2, r3, lr} @保存的内容出栈,恢复各寄存器值
mov r0, #-14 @r0保存返回值为-14
bx lr @跳回调用函数继续执行,_arm_get_user到此结束!
.pushsection __exc_table, "a"
.long 0b, .Lget_user_err
.long 1b, .Lget_user_err
.long 2b, .Lget_user_err
.long 3b, .Lget_user_err
.long 4b, .Lget_user_err
.long 5b, .Lget_user_err
.popsection
解读
用户空间和内核空间的数据为什么需要拷贝?
这是个经典问题,看了网上的一些回答,没毛病:
内核不能信任任何用户空间的指针。必须对用户空间的指针指向的数据进行验证。如果只做验证不做拷贝的话,那么在随后的运行中要随时受到其它进/线程可能修改用户空间数据的威胁。所以必须做拷贝。
在内存系列篇中已经反复的说过,每个用户进程都有自己独立的用户空间,但这个用户空间是通过MMU映射出来的,是表面上繁花似锦,背后都共用着真正的物理内存,所以在高频率的任务切换过程中,原有的用户空间地址内容很容易被覆盖掉.举个例子说明下:
鸿蒙开机代码根据 CPU多核还是单核分成了两个独立文件处理.
mp
就是多处理器(multiprocessing)的意思:
多CPU核的操作系统3种处理模式(SMP+AMP+BMP) 鸿蒙实现的是 SMP
的方式
非对称多处理(Asymmetric multiprocessing,AMP)每个CPU内核
运行一个独立的操作系统或同一操作系统的独立实例(instantiation)。
对称多处理(Symmetric multiprocessing,SMP)一个操作系统的实例
可以同时管理所有CPU内核,且应用并不绑定某一个内核。
混合多处理(Bound multiprocessing,BMP)一个操作系统的实例可以
同时管理所有CPU内核,但每个应用被锁定于某个指定的核心。
up
(unit processing )的意思,单个CPU,虽然没mp的复杂,但文件也很大 500行汇编,一小节讲不完,需要单独的一篇专讲 reset_vector
这里只列出up情况下的开机代码
reset_vector: @鸿蒙单核cpu 开机代码
/* do some early cpu setup: i/d cache disable, mmu disabled */
mrc p15, 0, r0, c1, c0, 0
bic r0, #(1<<12)
bic r0, #(1<<2 | 1<<0)
mcr p15, 0, r0, c1, c0, 0
/* r11: delta of physical address and virtual address */
adr r11, pa_va_offset
ldr r0, [r11]
sub r11, r11, r0
/* if we need to relocate to proper location or not */
adr r4, __exception_handlers /* r4: base of load address */
ldr r5, =SYS_MEM_BASE /* r5: base of physical address */
subs r12, r4, r5 /* r12: delta of load address and physical address */
beq reloc_img_to_bottom_done /* if we load image at the bottom of physical address */
/* we need to relocate image at the bottom of physical address */
ldr r7, =__exception_handlers /* r7: base of linked address (or vm address) */
ldr r6, =__bss_start /* r6: end of linked address (or vm address) */
sub r6, r7 /* r6: delta of linked address (or vm address) */
add r6, r4 /* r6: end of load address */
异常模式处理入口和统一分发现实,之前也有提到过,很复杂,1000多行,后续单独细说实现过程.
两个简单的函数longjmp
setjmp
的实现,加注解部分请前往
鸿蒙内核源码注解分析 查看
FUNCTION(longjmp)
ldmfd r0,{
r4-r12}
add r0,#(4 * 9)
ldr r13,[r0]
add r0,#4
ldr r14,[r0]
cmp r1,#0
moveq r1,#1
mov r0,r1
mov pc,lr
FUNCTION(setjmp)
stmea r0,{
r4-r12}
add r0,#(4 * 9)
str r13,[r0]
add r0,#4
str r14,[r0]
mov r0,#0
mov pc,lr
.global OsSRSaveRegister
.global OsSRRestoreRegister
两个函数的汇编现实,有点复杂,后续单独说明.
这是缓存部分的两个函数实现,此处没有加注解,试着看明白这两个函数的实现.加注解部分请前往
鸿蒙内核源码注解分析 查看
.macro DCACHE_LINE_SIZE, reg, tmp
mrc p15, 0, \tmp, c0, c0, 1
lsr \tmp, \tmp, #16
and \tmp, \tmp, #0xf
mov \reg, #4
mov \reg, \reg, lsl \tmp
.endm
FUNCTION(arm_inv_cache_range)
push {
r2, r3}
DCACHE_LINE_SIZE r2, r3
sub r3, r2, #1
tst r0, r3
bic r0, r0, r3
mcrne p15, 0, r0, c7, c14, 1
tst r1, r3
bic r1, r1, r3
mcrne p15, 0, r1, c7, c14, 1
1:
mcr p15, 0, r0, c7, c6, 1
add r0, r0, r2
cmp r0, r1
blo 1b
dsb
pop {
r2, r3}
mov pc, lr
FUNCTION(arm_clean_cache_range)
push {
r2, r3}
DCACHE_LINE_SIZE r2, r3
sub r3, r2, #1
bic r0, r0, r3
1:
mcr p15, 0, r0, c7, c10, 1
add r0, r0, r2
cmp r0, r1
blo 1b
dsb
pop {
r2, r3}
mov pc, lr
v44.03 (中断管理篇) | 硬中断的实现<>观察者模式 < csdn | harmony | 掘金 >
v43.03 (中断概念篇) | 外人眼中权势滔天的当红海公公 < csdn | harmony | 掘金 >
v42.03 (中断切换篇) | 中断切换到底在切换什么? < csdn | harmony | 掘金 >
v41.03 (任务切换篇) | 汇编逐行注解分析任务上下文 < csdn | harmony | 掘金 >
v40.03 (汇编汇总篇) | 所有的汇编代码都在这里 < csdn | harmony | 掘金 >
v39.03 (异常接管篇) | 社会很单纯,复杂的是人 < csdn | harmony | 掘金 >
v38.03 (寄存器篇) | ARM所有寄存器一网打尽,不再神秘 < csdn | harmony | 掘金 >
v37.03 (系统调用篇) | 全盘解剖系统调用实现过程 < csdn | harmony | 掘金 >
v36.03 (工作模式篇) | CPU是韦小宝,有哪七个老婆? < csdn | harmony | 掘金 >
v35.03 (时间管理篇) | Tick是操作系统的基本时间单位 < csdn | harmony | 掘金 >
v34.03 (原子操作篇) | 是谁在为原子操作保驾护航? < csdn | harmony | 掘金 >
v33.03 (消息队列篇) | 进程间如何异步解耦传递大数据 ? < csdn | harmony | 掘金 >
v32.03 (CPU篇) | 内核是如何描述CPU的? < csdn | harmony | 掘金 >
v31.03 (定时器篇) | 内核最高优先级任务是谁? < csdn | harmony | 掘金 >
v30.03 (事件控制篇) | 任务间多对多的同步方案 < csdn | harmony | 掘金 >
v29.03 (信号量篇) | 信号量解决任务同步问题 < csdn | harmony | 掘金 >
v28.03 (进程通讯篇) | 进程间通讯有哪九大方式? < csdn | harmony | 掘金 >
v27.03 (互斥锁篇) | 互斥锁比自旋锁可丰满许多 < csdn | harmony | 掘金 >
v26.03 (自旋锁篇) | 想为自旋锁立贞节牌坊! < csdn | harmony | 掘金 >
v25.03 (并发并行篇) | 怎么记住并发并行的区别? < csdn | harmony | 掘金 >
v24.03 (进程概念篇) | 进程在管理哪些资源? < csdn | harmony | 掘金 >
v23.02 (汇编传参篇) | 汇编如何传递复杂的参数? < csdn | harmony | 掘金 >
v22.02 (汇编基础篇) | CPU在哪里打卡上班? < csdn | harmony | 掘金 >
v21.02 (线程概念篇) | 是谁在不断的折腾CPU? < csdn | harmony | 掘金 >
v20.02 (用栈方式篇) | 栈是构建底层运行的基础 < csdn | harmony | 掘金 >
v19.02 (位图管理篇) | 为何进程和线程优先级都是32个? < csdn | harmony | 掘金 >
v18.02 (源码结构篇) | 内核500问你能答对多少? < csdn | harmony | 掘金 >
v17.02 (物理内存篇) | 这样记伙伴算法永远不会忘 < csdn | harmony | 掘金 >
v16.02 (内存规则篇) | 内存管理到底在管什么? < csdn | harmony | 掘金 >
v15.02 (内存映射篇) | 什么是内存最重要的实现基础 ? < csdn | harmony | 掘金 >
v14.02 (内存汇编篇) | 什么是虚拟内存的实现基础? < csdn | harmony | 掘金 >
v13.02 (源码注释篇) | 热爱是所有的理由和答案 < csdn | harmony | 掘金 >
v12.02 (内存管理篇) | 虚拟内存全景图是怎样的? < csdn | harmony | 掘金 >
v11.02 (内存分配篇) | 内存有哪些分配方式? < csdn | harmony | 掘金 >
v10.02 (内存主奴篇) | 紫禁城的主子和奴才如何相处? < csdn | harmony | 掘金 >
v09.02 (调度故事篇) | 用故事说内核调度 < csdn | harmony | 掘金 >
v08.02 (总目录) | 百万汉字注解 百篇博客分析 < csdn | harmony | 掘金 >
v07.02 (调度机制篇) | 任务是如何被调度执行的? < csdn | harmony | 掘金 >
v06.02 (调度队列篇) | 就绪队列对调度的作用 < csdn | harmony | 掘金 >
v05.02 (任务管理篇) | 谁在让CPU忙忙碌碌? < csdn | harmony | 掘金 >
v04.02 (任务调度篇) | 任务是内核调度的单元 < csdn | harmony | 掘金 >
v03.02 (时钟任务篇) | 触发调度最大的动力来自哪里? < csdn | harmony | 掘金 >
v02.02 (进程管理篇) | 进程是内核资源管理单元 < csdn | harmony | 掘金 >
v01.09 (双向链表篇) | 谁是内核最重要结构体? < csdn | harmony | 掘金 >
访问注解仓库地址
Fork 本仓库 >> 新建 Feat_xxx 分支 >> 提交代码注解 >> 新建 Pull Request
新建 Issue
各大站点搜 “鸿蒙内核源码分析” .欢迎转载,请注明出处.