注解用户空间,内核空间的汇编拷贝代码

    百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
    https://weharmony.gitee.io
上级 5d3039f7
......@@ -30,42 +30,59 @@
*/
#include "asm.h"
/*********************************************
BEQ    相等
BNE    不等
BPL    非负
BMI    负
BCC    无进位
BCS    有进位
BLO    小于(无符号数)
BHS    大于等于(无符号数)
BHI    大于(无符号数)
BLS    小于等于(无符号数)
BVC    无溢出(有符号数)
BVS    有溢出(有符号数)
BGT    大于(有符号数)
BGE    大于等于(有符号数)
BLT    小于(有符号数)
BLE    小于等于(有符号数)
*********************************************/
.syntax unified
.arm
// 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}
cmp r2, #0
beq .Lget_user_return
cmp r2, r3
bne .Lget_user_err
cmp r2, #1
bhi .Lget_user_half
.Lget_user_byte:
0: ldrbt r3, [r1], #0
1: strb r3, [r0], #0
b .Lget_user_return
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
bhi .Lget_user_word
2: ldrht r3, [r1], #0
3: strh r3, [r0], #0
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
bhi .Lget_user_err
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
bx lr
.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
bx lr
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
......
......@@ -97,6 +97,10 @@ ARM的指令系统中关于栈指令的内容比较容易引起迷惑,这是
| 变量2 |
|---------------|
|---------------| 低地址
LDMFD SP!, {PC}^
LDM/STR架构中{∧}为可选后缀,当指令为LDM且寄存器列表中包含R15PC),
选用该后缀时表示:除了正常的数据传送之外,还将SPSR复制到CPSR(将备份的程序状态寄存器SPCR恢复到当前程序状态寄存器CPSR)。
******************************************************************************/
#ifdef LOSCFG_KERNEL_SMP_LOCKDEP
.extern OsLockDepCheckOut/*使用外部定义的函数*/
......@@ -196,7 +200,7 @@ OsTaskSchedule: /*新老任务切换上下文*/
PUSH_FPU_REGS R2 /*保存fpu寄存器*/
/* store sp on running task */
STR SP, [R1] @存储任务到栈
STR SP, [R1] @在运行的任务栈中保存SP
OsTaskContextLoad:
/* clear the flag of ldrex */ @LDREX 可从内存加载数据,如果物理地址有共享TLB属性,则LDREX会将该物理地址标记为由当前处理器独占访问,并且会清除该处理器对其他任何物理地址的任何独占访问标记。
......@@ -237,9 +241,9 @@ OsTaskContextLoad:
STR R2, [R3, #OS_PERCPU_TASK_LOCK_OFFSET]
#endif
MVN R3, #CPSR_INT_DISABLE
MVN R3, #CPSR_INT_DISABLE @按位取反 R3 = 0x3F
AND R4, R4, R3
MSR SPSR_cxsf, R4
MSR SPSR_cxsf, R4 @修改spsr
/* restore r0-r12, lr */
LDMFD SP!, {R0-R12}
......@@ -282,30 +286,30 @@ OsIrqFromKernel: @从内核发起中断
SUB SP, SP, #(2 * 4) @申请8个栈空间
/* pop r0-r3 from irq stack*/
LDMFD R0, {R0-R3} @出栈
LDMFD R0, {R0-R3} @R0位置依次出栈
/* push caller saved regs as trashed regs in svc stack */
STMFD SP!, {R0-R3, R12}
STMFD SP!, {R0-R3, R12} @R0~R3入栈,R12入栈
/* 8 bytes stack align */
SUB SP, SP, #4
SUB SP, SP, #4 @栈对齐
/*
* save fpu regs in case in case those been
* altered in interrupt handlers.
*/
PUSH_FPU_REGS R0
#ifdef LOSCFG_IRQ_USE_STANDALONE_STACK @IRQ使用独立
PUSH {R4}
MOV R4, SP
EXC_SP_SET __svc_stack_top, OS_EXC_SVC_STACK_SIZE, R1, R2
PUSH_FPU_REGS R0 @保存fpu regs,以防中断处理程序中的fpu regs被修改。
#ifdef LOSCFG_IRQ_USE_STANDALONE_STACK @是否使用了独立的IRQ
PUSH {R4} @R4先入栈保存,接下来要切换栈,需保存现场
MOV R4, SP @R4=SP
EXC_SP_SET __svc_stack_top, OS_EXC_SVC_STACK_SIZE, R1, R2 @切换到svc
#endif
/*BLX 带链接和状态切换的跳转*/
BLX HalIrqHandler /* 调用硬中断处理程序,无参 */
BLX HalIrqHandler /* 调用硬中断处理程序,无参 ,说明HalIrqHandlersvc栈中执行 */
#ifdef LOSCFG_IRQ_USE_STANDALONE_STACK @是否使用了独立的IRQ栈
MOV SP, R4
POP {R4}
MOV SP, R4 @恢复现场,sp = R4
POP {R4} @弹出R4
#endif
/* process pending signals */ @处理挂起信号
......@@ -327,10 +331,10 @@ OsIrqFromKernel: @从内核发起中断
OsIrqContextRestore: @恢复硬中断环境
LDR R0, [SP, #(4 * 7)] @读取 SP+28 位置数据给R0
MSR SPSR_cxsf, R0 @恢复spsr
AND R0, R0, #CPSR_MASK_MODE
CMP R0, #CPSR_USER_MODE @
AND R0, R0, #CPSR_MASK_MODE @掩码找出当前工作模式
CMP R0, #CPSR_USER_MODE @是否为用户模式?
LDMFD SP!, {R0-R3, R12} @
LDMFD SP!, {R0-R3, R12} @SP位置依次出栈
BNE OsIrqContextRestoreToKernel @CPU工作在非用户模式
......@@ -339,7 +343,7 @@ OsIrqContextRestore: @恢复硬中断环境
ADD SP, SP, #(3 * 4)
/* return to user mode */
LDMFD SP!, {PC}^
LDMFD SP!, {PC}^ @回到用户模式
OsIrqContextRestoreToKernel:
/* svc mode not load sp */
......
......@@ -200,31 +200,31 @@ reloc_img_to_bottom_done:
warm_reset: @初始化CPU各异常工作模式环境
/* initialize interrupt/exception environments */
mov r0, #(CPSR_IRQ_DISABLE |CPSR_FIQ_DISABLE|CPSR_IRQ_MODE)
msr cpsr, r0 @先切到IRQ模式
msr cpsr, r0 @设置为普通中断模式和栈
EXC_SP_SET __irq_stack_top, #OS_EXC_IRQ_STACK_SIZE
mov r0, #(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_UNDEF_MODE)
msr cpsr, r0
msr cpsr, r0 @设置为未定义模式和栈
EXC_SP_SET __undef_stack_top, #OS_EXC_UNDEF_STACK_SIZE
mov r0, #(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_ABT_MODE)
msr cpsr, r0
msr cpsr, r0 @设置为终止模式和栈
EXC_SP_SET __abt_stack_top, #OS_EXC_ABT_STACK_SIZE
mov r0, #(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_FIQ_MODE)
msr cpsr, r0
msr cpsr, r0 @设置为快中断模式和栈
EXC_SP_SET __fiq_stack_top, #OS_EXC_FIQ_STACK_SIZE
/* initialize CPSR (machine state register) */
mov r0, #(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SVC_MODE)
msr cpsr, r0
msr cpsr, r0 @设置为管理模式和栈
/* Note: some functions in LIBGCC1 will cause a "restore from SPSR"!! */
msr spsr, r0
msr spsr, r0 @同步设置spsr
/* get cpuid and keep it in r12 */
mrc p15, 0, r12, c0, c0, 5 @C0获取CPUIDR12
and r12, r12, #MPIDR_CPUID_MASK @掩码操作
mrc p15, 0, r12, c0, c0, 5 @R12保存CPUID
and r12, r12, #MPIDR_CPUID_MASK @掩码操作获取当前cpu id
/* set svc stack, every cpu has OS_EXC_SVC_STACK_SIZE stack *//*设置每一个SVC,每个CPU都有独立的 SVC*/
ldr r0, =__svc_stack_top @栈底位置,注意这里虽然使用了top,但实际是栈底
......@@ -340,7 +340,7 @@ cpu_start: /* 启动次级CPU */
ldr r4, [r4]
add r4, r4, r11 /* r4 = tt_trampoline paddr */
bl mmu_setup
bl mmu_setup /* 安装MMU */
bl secondary_cpu_start /* 启动次级CPU */
b .
......@@ -357,19 +357,19 @@ secondary_cpu_init: /* 次级CPU初始化 */
mcr p15, 0, r1, c1, c1, 0
cps #0x13
#endif
bl warm_reset
bl warm_reset @重置次级CPU
/*
* set sp for current cpu
* r1 is stack bottom, r0 is stack size, r12 hold cpu id
*/
sp_set:
mrc p15, 0, r12, c0, c0, 5
and r12, r12, #MPIDR_CPUID_MASK
mul r3, r0, r12
sub r2, r1, r3
mov sp, r2
bx lr /* set sp */
sp_set: /* 设置当前cpu 栈顶指针 ,r1是栈底 ,r0是栈大小,r12cpuid*/
mrc p15, 0, r12, c0, c0, 5 @从协处理器取出cpuid
and r12, r12, #MPIDR_CPUID_MASK @掩码获取当前运行cpu id
mul r3, r0, r12 @ r3 = r0 * r12 计算出偏移量
sub r2, r1, r3 @ r2 = r1 - r3 算出cpuid 对应的栈顶位置
mov sp, r2 @ 将栈顶指针sp移到栈顶位置.
bx lr /* set sp */ @跳回到LR执行
/*
* r4: page table base address
......
......@@ -71,11 +71,12 @@ LITE_OS_SEC_TEXT_INIT VOID OsSystemInfo(VOID)
HalIrqVersion(), __DATE__, __TIME__,\
KERNEL_NAME, KERNEL_MAJOR, KERNEL_MINOR, KERNEL_PATCH, KERNEL_ITRE, buildType);
}
//次级CPU初始化,本函数执行的次数由次级CPU的个数决定. 例如:在四核情况下,会被执行3次, 0号通常被定义为主CPU 执行main
//次级CPU初始化,本函数执行的次数由次级CPU的个数决定.
//例如:在四核情况下,会被执行3次, 0号通常被定义为主CPU 执行main
LITE_OS_SEC_TEXT_INIT VOID secondary_cpu_start(VOID)
{
#if (LOSCFG_KERNEL_SMP == YES)
UINT32 cpuid = ArchCurrCpuid();
#if (LOSCFG_KERNEL_SMP == YES)//支持多cpu核开关
UINT32 cpuid = ArchCurrCpuid();//获取当前cpu id
OsArchMmuInitPerCPU();//每个CPU都需要初始化MMU
......@@ -91,10 +92,10 @@ LITE_OS_SEC_TEXT_INIT VOID secondary_cpu_start(VOID)
OsCurrProcessSet(OS_PCB_FROM_PID(OsGetKernelInitProcessID())); //设置内核进程为CPU进程
OsSwtmrInit(); //定时任务初始化,每个CPU维护自己的定时器队列
OsIdleTaskCreate(); //创建空闲任务,每个CPU维护自己的任务队列
OsStart(); //本CPU正式启动在内核层的工作
OsStart(); //正式启动在内核层的工作
while (1) {
__asm volatile("wfi");//wait for Interrupt 等待中断,即下一次中断发生前都在此hold住不干活
}//类似的还有 WFE: wait for Events 等待事件,即下一次事件发生前都在此hold住不干活
__asm volatile("wfi");//wait for Interrupt 等待中断,即下一次中断发生前都在此呆着不干活
}//类似的还有 WFE: wait for Events 等待事件,即下一次事件发生前都在此呆着不干活
#endif
}
......@@ -150,7 +151,7 @@ LITE_OS_SEC_TEXT_INIT VOID release_secondary_cores(VOID)//调动次级CPU干活
内核入口函数,由汇编调用,见于reset_vector_up.S 和 reset_vector_mp.S
up指单核CPU, mp指多核CPU
******************************************************************************/
LITE_OS_SEC_TEXT_INIT INT32 main(VOID)//由主CPU执行,默认 0号为主CPU
LITE_OS_SEC_TEXT_INIT INT32 main(VOID)//由主CPU执行,默认0号CPU 为主CPU
{
UINT32 uwRet = LOS_OK;
......@@ -167,7 +168,7 @@ LITE_OS_SEC_TEXT_INIT INT32 main(VOID)//由主CPU执行,默认 0号为主CPU
/* system and chip info */
OsSystemInfo();//输出系统和芯片的信息
PRINT_RELEASE("\nmain core booting up...\n"); //主内核启动中...
PRINT_RELEASE("\nmain core booting up...\n"); //控制台输出 主内核启动中...
uwRet = OsMain();// 内核各模块初始化
if (uwRet != LOS_OK) {
......
git add -A
git commit -m '注解异常分发汇编代码
git commit -m '注解用户空间,内核空间的汇编拷贝代码
百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
https://weharmony.gitee.io
'
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册