Millions of Chinese character annotations >> Intensive reading of the kernel source code, Chinese annotation analysis, deep excavation of foundation engineering, permanent brain memory, four major code warehouses are updated daily <gitee | github | csdn | coding>
Hundreds of blog analysis >> Storytelling core, Q&A guide, life-style metaphor, tabular description, graphical display, multi-site daily synchronization update <oschina | csdn | weharmony>
The description of the ARM part of the series is based on the ARM720T.pdf document.
Why is there an abnormal takeover?
Take the growth of a child as an analogy. Adults always hope that children can grow up healthily, but they will always encounter various problems in the process of growth. The tree desires to be quiet and windy, and there is danger on the growth path. Sometimes it is their own problems and sometimes they are foreign. Regarding environmental issues. Just like Douyin’s recent popular saliva songs, the society is very simple, and the complicated ones are people. Every time I hear it, I want to stand up and twist a few times. Hey! What did Lao Na do wrong?
For example: What do you do when you are bullied by children? What do you do when you find that you spend money? How do you deal with puberty? What should you do if you lose love and jump off the building? It means more than his cognition, but it can’t solve it by himself, so he needs a higher authority , A more intelligent person stepped in to help solve the problem of wiping the ass.
Then the application is the kid, and the kernel is the guardian, with higher authority and higher wisdom. And there are more than one guardian, but six. Each guardian solves a situation, and it takes over when a situation occurs. For the handling of this matter, don't worry about it, kids, shut you off at home first, and handle the outside safety before releasing the app to play.
These six people have their own tools to deal with problems, have standard solutions, have their own independent office space, the office space is the stack space (independent), and the standard solution is the private code segment, placed in a fixed location. the tool is SPSR_***
, SP_***
, LR_***
the register set. see the series of articles published work mode , then briefly reviewed here what work mode there, including children themselves (user mode) a total of seven modes.
Seven working modes
The picture is from page 43 of ARM720T.pdf . In the ARM system, the CPU works in the following seven modes:
- User mode (usr): It is a normal user mode and cannot be directly switched to other modes. The ARM processor is in the normal program execution state.
- Fast interrupt mode (fiq): support high-speed data transmission and channel processing, enter this mode when FIQ responds abnormally
- External interrupt mode (irq): used for general interrupt processing, enter this mode when IRQ responds abnormally
- Management mode (svc): operating system protection mode, enter this mode when the system is reset and software interrupt response (triggered by the system call to execute the soft interrupt SWI command)
- Data access termination mode (abt): Enter this mode when data or instruction prefetching is terminated, which can be used to handle memory failures and implement virtual memory and memory protection.
- System mode (sys): Run privileged operating system tasks, similar to user mode, but with privileges such as being able to switch directly to other modes
- Undefined instruction abort mode (und): handles undefined instruction traps, enters this mode when undefined instructions are executed, and can be used to support software emulation of hardware coprocessors.
Except for user mode, the other 6 working modes belong to privileged mode
- The other five modes in the privileged mode except the system mode are called exception modes
- Most programs run in user mode
- Entering privileged mode is to handle interrupts, exceptions, or access protected system resources
- Hardware permission level: System mode> Abnormal mode> User mode
- The difference between fast interrupt (fiq) and slow interrupt (irq): interrupt is prohibited during fast interrupt processing
Each mode has its own independent entry point and independent running stack space. The CPU part of the series has already introduced that as long as the entry function and running space are provided, the CPU can work. The entry function solves the problem of the source of instructions and the running space. It solves the problem of the running site of instructions.
And in the case of multi-core, each privileged mode of each CPU core has its own independent stack space. Note that the stack space in the privileged mode, the stack space in the user mode is determined by the user (application ) Provided by the program.
Official concept
Exception takeover is a series of actions taken by the operating system to handle exceptions (chip hardware exceptions) that occur during operation, such as printing the call stack information of the current function when the exception occurs, CPU site information, and the stack of tasks.
Exception takeover, as a debugging method, can provide users with useful exception information when an exception occurs in the system, such as exception type, system status when the exception occurs, etc., so that users can locate and analyze the problem.
Hongmeng's exception takeover, the processing action when an exception occurs in the system is: display the task information (including task name, task number, stack size, etc.) that is running when the exception occurs, and information such as the CPU site.
Entry and Exit Abnormal Way
Two things need to be handled for abnormal takeover switching:
- One is where the code should be cut, that is, to reset the PC register. The switching method under each abnormal mode is as shown in the figure:
- Another is to restore the state of each mode, i.e.,
CPSR(1个)
andSPSR(共5个)
the relationship ofM[4:0]
the modification, as shown:
The following is M[4:0]
the specific operation method in each mode:
Stack frame
Each function has its own stack space, called a stack frame. When a function is called, a stack frame of the sub-function is created, and the function is put into the stack at the same time as parameters, local variables, and registers. Stack frame to address the low growth from the high address, that address bottom of the stack is high, top of the stack is the end of the address. See series with a stack of papers published way
To ARM32 CPU
architecture, for example, each stack frame are saved PC
, LR
, SP
and FP
the historical value of the register.
The principle of stack analysis is shown in the figure below. The actual stack information differs according to different CPU architectures. This is only for illustration.
The registers of different colors in the figure represent different functions. You can see the preservation of registers during the function call. Through the FP register, the stack traces back to the parent function of the abnormal function, continues to analyze the stack according to the law, and introduces the function call relationship, which is convenient for users to locate the problem.
Interpretation
-
LR register (Link Register), link register, points to the return address of the function.
-
R11: It can be used as a general-purpose register. It can be used as a frame pointer register FP when certain coding options are turned on to realize the stack traceback function.
The GNU compiler (gcc) defaults to R11 as a general-purpose register for storing variables, so the stack traceback function of FP cannot be used by default. To support the call stack parsing function, you need to add the -fno-omit-frame-pointer option to the compilation parameters to prompt the compiler to use R11 as FP. -
FP register (Frame Point), frame pointer register, points to the start address of the stack frame of the parent function of the current function. The stack frame of the parent function can be obtained by using this register, and the FP of the parent function can be obtained from the stack frame, and the stack frame of the grandfather function can be obtained. By analogy, the program call stack can be traced to obtain the calling relationship between functions.
When an exception occurs in the system, the system prints the contents of the registers saved in the stack frame of the exception function, as well as the contents of the LR and FP registers in the stack frame of the parent function and grandfather function, and the user can trace the calling relationship between the functions based on this, and locate the exception the reason.
Six kinds of exception mode implementation code
/* Define exception type ID */ //ARM处理器一共有7种工作模式,除了用户和系统模式其余都叫异常工作模式
#define OS_EXCEPT_RESET 0x00 //重置功能,例如:开机就进入CPSR_SVC_MODE模式
#define OS_EXCEPT_UNDEF_INSTR 0x01 //未定义的异常,就是others
#define OS_EXCEPT_SWI 0x02 //软中断
#define OS_EXCEPT_PREFETCH_ABORT 0x03 //预取异常(取指异常), 指令三步骤: 取指,译码,执行,
#define OS_EXCEPT_DATA_ABORT 0x04 //数据异常
#define OS_EXCEPT_FIQ 0x05 //快中断异常
#define OS_EXCEPT_ADDR_ABORT 0x06 //地址异常
#define OS_EXCEPT_IRQ 0x07 //普通中断异常
Address abort
@ Description: Address abort exception handler
_osExceptAddrAbortHdl: @地址异常处理
SUB LR, LR, #8 @ LR offset to return from this exception: -8.
STMFD SP, {
R0-R7} @ Push working registers, but don`t change SP.
MOV R0, #OS_EXCEPT_ADDR_ABORT @ Set exception ID to OS_EXCEPT_ADDR_ABORT.
B _osExceptDispatch @跳到异常分发统一处理
Fast interrupt processing (fiq)
@ Description: Fast interrupt request exception handler
_osExceptFiqHdl: @快中断异常处理
SUB LR, LR, #4 @ LR offset to return from this exception: -4.
STMFD SP, {
R0-R7} @ Push working registers.
MOV R0, #OS_EXCEPT_FIQ @ Set exception ID to OS_EXCEPT_FIQ.
B _osExceptDispatch @ Branch to global exception handler.
Interpretation
- Normal interrupts need to be disabled for fast interrupt processing
Prefectch abort
@ Description: Prefectch abort exception handler
_osExceptPrefetchAbortHdl:
#ifdef LOSCFG_GDB
#if __LINUX_ARM_ARCH__ >= 7
GDB_HANDLE OsPrefetchAbortExcHandleEntry
#endif
#else
SUB LR, LR, #4 @ LR offset to return from this exception: -4.
STMFD SP, {
R0-R7} @ Push working registers, but don`t change SP.
MOV R5, LR
MRS R1, SPSR
MOV R0, #OS_EXCEPT_PREFETCH_ABORT @ Set exception ID to OS_EXCEPT_PREFETCH_ABORT.
AND R4, R1, #CPSR_MASK_MODE @ Interrupted mode
CMP R4, #CPSR_USER_MODE @ User mode
BEQ _osExcPageFault @ Branch if user mode
_osKernelExceptPrefetchAbortHdl:
MOV LR, R5
B _osExceptDispatch @ Branch to global exception handler.
#endif
Data access exception (Data abort)
@ Description: Data abort exception handler
_osExceptDataAbortHdl: @数据异常处理,缺页就属于数据异常
#ifdef LOSCFG_GDB
#if __LINUX_ARM_ARCH__ >= 7
GDB_HANDLE OsDataAbortExcHandleEntry
#endif
#else
SUB LR, LR, #8 @ LR offset to return from this exception: -8.
STMFD SP, {
R0-R7} @ Push working registers, but don`t change SP.
MOV R5, LR
MRS R1, SPSR
MOV R0, #OS_EXCEPT_DATA_ABORT @ Set exception ID to OS_EXCEPT_DATA_ABORT.
B _osExcPageFault @跳到缺页异常处理
#endif
Soft interrupt processing (swi)
@ Description: Software interrupt exception handler
_osExceptSwiHdl: @软中断异常处理
SUB SP, SP, #(4 * 16) @先申请16个栈空间用于处理本次软中断
STMIA SP, {
R0-R12} @保存R0-R12寄存器值
MRS R3, SPSR @读取本模式下的SPSR值
MOV R4, LR @保存回跳寄存器LR
AND R1, R3, #CPSR_MASK_MODE @ Interrupted mode 获取中断模式
CMP R1, #CPSR_USER_MODE @ User mode 是否为用户模式
BNE OsKernelSVCHandler @ Branch if not user mode 非用户模式下跳转
@ 当为用户模式时,获取SP和LR寄出去值
@ we enter from user mode, we need get the values of USER mode r13(sp) and r14(lr).
@ stmia with ^ will return the user mode registers (provided that r15 is not in the register list).
MOV R0, SP @获取SP值,R0将作为OsArmA32SyscallHandle的参数
STMFD SP!, {
R3} @ Save the CPSR 入栈保存CPSR值
ADD R3, SP, #(4 * 17) @ Offset to pc/cpsr storage 跳到PC/CPSR存储位置
STMFD R3!, {
R4} @ Save the CPSR and r15(pc) 保存LR寄存器
STMFD R3, {
R13, R14}^ @ Save user mode r13(sp) and r14(lr) 保存用户模式下的SP和LR寄存器
SUB SP, SP, #4
PUSH_FPU_REGS R1 @保存中断模式(用户模式模式)
MOV FP, #0 @ Init frame pointer
CPSIE I @开中断,表明在系统调用期间可响应中断
BLX OsArmA32SyscallHandle /*交给C语言处理系统调用*/
CPSID I @执行后续指令前必须先关中断
POP_FPU_REGS R1 @弹出FP值给R1
ADD SP, SP,#4 @ 定位到保存旧SPSR值的位置
LDMFD SP!, {
R3} @ Fetch the return SPSR 弹出旧SPSR值
MSR SPSR_cxsf, R3 @ Set the return mode SPSR 恢复该模式下的SPSR值
@ we are leaving to user mode, we need to restore the values of USER mode r13(sp) and r14(lr).
@ ldmia with ^ will return the user mode registers (provided that r15 is not in the register list)
LDMFD SP!, {
R0-R12} @恢复R0-R12寄存器
LDMFD SP, {
R13, R14}^ @ Restore user mode R13/R14 恢复用户模式的R13/R14寄存器
ADD SP, SP, #(2 * 4) @定位到保存旧PC值的位置
LDMFD SP!, {
PC}^ @ Return to user 切回用户模式运行
Ordinary interrupt processing (irq)
OsIrqHandler: @硬中断处理,此时已切换到硬中断栈
SUB LR, LR, #4
/* push r0-r3 to irq stack */
STMFD SP, {
R0-R3} @r0-r3寄存器入 irq 栈
SUB R0, SP, #(4 * 4)@r0 = sp - 16
MRS R1, SPSR @获取程序状态控制寄存器
MOV R2, LR @r2=lr
/* disable irq, switch to svc mode */@超级用户模式(SVC 模式),主要用于 SWI(软件中断)和 OS(操作系统)。
CPSID i, #0x13 @切换到SVC模式,此处一切换,后续指令将入SVC的栈
@CPSID i为关中断指令,对应的是CPSIE
/* push spsr and pc in svc stack */
STMFD SP!, {
R1, R2} @实际是将 SPSR,和LR入栈,入栈顺序为 R1,R2,SP自增
STMFD SP, {
LR} @LR再入栈,SP不自增
AND R3, R1, #CPSR_MASK_MODE @获取CPU的运行模式
CMP R3, #CPSR_USER_MODE @中断是否发生在用户模式
BNE OsIrqFromKernel @中断不发生在用户模式下则跳转到OsIrqFromKernel
/* push user sp, lr in svc stack */
STMFD SP, {
R13, R14}^ @sp和LR入svc栈
Interpretation
- Can respond to fast interrupts during normal interrupt processing
Undefined exception handling (undef)
@ Description: Undefined instruction exception handler
_osExceptUndefInstrHdl:@出现未定义的指令处理
#ifdef LOSCFG_GDB
GDB_HANDLE OsUndefIncExcHandleEntry
#else
@ LR offset to return from this exception: 0.
STMFD SP, {
R0-R7} @ Push working registers, but don`t change SP.
MOV R0, #OS_EXCEPT_UNDEF_INSTR @ Set exception ID to OS_EXCEPT_UNDEF_INSTR.
B _osExceptDispatch @ Branch to global exception handler.
#endif
Unified handling of abnormal distribution
_osExceptDispatch: @异常模式统一分发处理
MRS R2, SPSR @ Save CPSR before exception.
MOV R1, LR @ Save PC before exception.
SUB R3, SP, #(8 * 4) @ Save the start address of working registers.
MSR CPSR_c, #(CPSR_INT_DISABLE | CPSR_SVC_MODE) @ Switch to SVC mode, and disable all interrupts
MOV R5, SP
EXC_SP_SET __exc_stack_top, OS_EXC_STACK_SIZE, R6, R7
STMFD SP!, {
R1} @ Push Exception PC
STMFD SP!, {
LR} @ Push SVC LR
STMFD SP!, {
R5} @ Push SVC SP
STMFD SP!, {
R8-R12} @ Push original R12-R8,
LDMFD R3!, {
R4-R11} @ Move original R7-R0 from exception stack to original stack.
STMFD SP!, {
R4-R11}
STMFD SP!, {
R2} @ Push task`s CPSR (i.e. exception SPSR).
CMP R0, #OS_EXCEPT_DATA_ABORT @是数据异常吗?
BNE 1f @不是跳到 锚点1处
MRC P15, 0, R8, C6, C0, 0 @R8=C6(内存失效的地址) 0(访问数据失效)
MRC P15, 0, R9, C5, C0, 0 @R9=C5(内存失效的状态) 0(无效整个指令cache)
B 3f @跳到锚点3处执行
1: CMP R0, #OS_EXCEPT_PREFETCH_ABORT @是预取异常吗?
BNE 2f @不是跳到 锚点2处
MRC P15, 0, R8, C6, C0, 2 @R8=C6(内存失效的地址) 2(访问指令失效)
MRC P15, 0, R9, C5, C0, 1 @R9=C5(内存失效的状态) 1(虚拟地址)
B 3f @跳到锚点3处执行
2: MOV R8, #0
MOV R9, #0
3: AND R2, R2, #CPSR_MASK_MODE
CMP R2, #CPSR_USER_MODE @ User mode
BNE 4f @不是用户模式
STMFD SP, {
R13, R14}^ @ save user mode sp and lr
4:
SUB SP, SP, #(4 * 2) @sp=sp-(4*2)
Very important ARM37 registers
See the series of articles published register
end
The above is the code processing corresponding to the exception takeover. The specific scenarios where each exception occurs and the code details are handled. Because the content is too much and too complicated, the series will be analyzed one by one in the follow-up. Stay tuned!
Participate in contribution
-
Fork this warehouse >> New Feat_xxx branch >> Submit code comment >> New Pull Request
Like, please generously like + follow + favorite
Search "Hongmeng Kernel Source Code Analysis" on major sites to quickly find the organization.
Welcome to reprint, please indicate the source, the official account reprint application method: just reply to your official account name after paying attention.
Millions of Chinese character annotations >> Intensive reading of the kernel source code, Chinese annotation analysis, deep excavation of foundation engineering, permanent brain memory, four major code warehouses are updated daily <gitee | github | csdn | coding>
Hundreds of blog analysis >> Storytelling core, Q&A guide, life-style metaphor, tabular description, graphical display, multi-site daily synchronization update <oschina | csdn | weharmony>