WindowsCE exceptions and service interruptionsProgramPreliminary Study (=)
--------- By nasiry
Continue with the previous content. In the previous analysis, we had a rough idea about the SWI, Fiq, and IRQ processes, next we will continue to understand dataabort, prefetchabort, and the public distribution program commonhandler to complete the exception handling process.
2-4 dataabort Service Program
It is triggered by data exceptions. Generally, three commands trigger data exceptions. These commands are all memory access operations, it can only happen after MMU is introduced. 1. LDR/STR command. 2. Swap command. 3. LDM/STM commands. MMU has four types of failures: Storage Access failure, address alignment failure, address transformation failure, Domain Controller failure, and access control permission failure. therefore, when an exception occurs, you need to access CP15 to learn the specific cause and situation of the exception. MFC is a macro command dedicated to Microsoft's asmarm Macro Assembler, which is equivalent to MCR commands. Data exceptions and interruption modes may occur during mutual locks, so you also need to handle the situation of mutual locks. Normally, after saving the relevant registers, the system reads the C6, C5, and C13 registers of CP15. The three registers are the Invalid Address Register (FAR), the invalid status register (FSR), and the process number register (which is not well translated by pcp15), which are then processed based on the specific failure type. In the ARM processor, CP15 has three address types: VA, Pa, and MVA. Va (Virtual Address) is the virtual address or logical address, which is the address converted by PT through CP15, and PA (physical address) it corresponds to the address on AMBA, corresponding to the electrical medium, that is, the physical address. The modified virtual address (MVA) corresponds to the translation address in the cache and TLB.
Nested_entry dataaborthandler
Sub LR, LR, #8; repair continuation address
Stmfd SP !, {R0-r3, R12, LR}
Prolog_end
Sub r0, LR, # interlocked_start
CMP r0, # INTERLOCKED_END-INTERLOCKED_START
Bllo checkinterlockedrestart
Mfc15 r0, C6; (R0) = far
Mfc15 R1, C5; (R1) = FSR
Mfc15 R2, C13; (R2) = process base address
; Far = fault Address Register
; CP = 15: CRN = 6, CRM = 0, op_1 = 0, op_2 = 0
; FSR = fault Status Register
; CP = 15: CRN = 5, CRM = 0, op_1 = 0, op_2 = 0
; Pcp15: PID process ID register
; CP = 15: CRN = 13, CRM = 0, op_1 = 0, op_2 = 0
Tst r0, #0xfe000000; slot 0 reference?
Orreq r0, R0, R2; (R0) = process slot based address
And R1, R1, # 0x0d; type of data abort
CMP R1, #0x05; translation error?
Movne r0, #0
Calleq loadpagetable; (R0) =! 0 if entry loaded
Tst r0, R0
Ldmnefd SP !, {R0-r3, R12, PC} ^; restore regs & continue
; **************************************** *****************************
Ldr lr, = KData-4
Ldmfd SP !, R0-r3, R12}
Analytic dB LR, {r0-r3}
Ldmfd SP !, {R0}
STR r0, [LR]; save resume address
MoV R1, # id_data_abort; (R1) = Exception ID
B commonhandler
Entry_end dataaborthandler
After the occurrence of dataabort, the data stored in C6 is the MVA address that causes an exception. We can see from WindowsCE memory layout that the running space of the current process is in slot0, that is, 0x0-0x1fffffff, in fact, the data on this slot is only a copy of the actual process. If the data exception occurs in slot0, you need to find the actual slot storage address where the process is located, then, try to copy the kernel page table to the actual page table used by the hardware for restoration. If the copy operation is successful, return; otherwise, enter the exception distribution program commonhandler.
2-5 prefetchabort Service Program
For arm processors, because they use the Harvard structure-independent Data command bus, the exceptions generated during data/command reading can be naturally distinguished, essentially, these exceptions are the same as those caused by storage access failure. Therefore, these exceptions are related to MMU. In the arm manual, both dataabort and prefetchabort are called memory abort. Prefetch is generated after the action of the prefetch command. When the processor runs the invalid command (this is invalid and cannot be identified in the undefined exception, that is, it does not exist or cannot be obtained) this exception is triggered. Therefore, not all commands are invalid. For example, when a branch program points to an inaccessible area and the previous branch points to another accessible area. Although the prefetch In the last region is invalid, this branch is not executed, so no exception is generated. Therefore, the exact definition of prefetch should be prefetch and executes abort :). bkpt in the armv5 command set can also produce invalid prefetch, but because the arm here is usually arm9, that is, the armv4 command is used, we do not discuss bkpt. Because data exceptions and command exceptions belong to the same storage exception and the two exceptions cannot interrupt each other, the two exceptions in arm design use the same group register abort group.
Alternate_entry prefetchabort
Sub LR, LR, #0xf0000004; check whether the abnormal address is 0xf0000000-0xf0010400
Cmp lr, #0x00010400 ;.
BHS processprefabort;-> normal prefetch exception execution processprefabort
...
Processprefabort
Add LR, LR, #0xf0000000; repair continuation address
Stmfd SP !, {R0-r3, R12, LR}
MoV r0, LR; (R0) = faulting address
Mfc15 R2, C13; (R2) = process base address
Tst r0, #0xfe000000; slot 0 reference?
Orreq r0, R0, R2; (R0) = process slot based address
Call loadpagetable; (R0) =! 0 if entry loaded
Tst r0, R0
Ldmnefd SP !, {R0-r3, R12, PC} ^; restore regs & continue
Ldmfd SP !, R0-r3, R12}
Ldr lr, = KData-4
Analytic dB LR, {r0-r3}
Ldmfd SP !, {R0}
STR r0, [LR]; save resume address
MoV R1, # id_prefetch_abort; (R1) = Exception ID
B commonhandler
The following describes the situation of WindowsCE. Prefetchabort is the entry of the service program. At the beginning of the program, the LR, that is, the address that generates the exception + 4 (caused by the assembly line), the address is reduced by 0xf000 0004, and whether the value is between 0-0x10400, why? Originally, in addition to using the prefetchabort service program as normal Exception Handling, WindowsCE used this exception as a means of system calling. The system calls the address 0xf0000000-0xf0010400 through a prefetch exception. The following describes how to handle prefetch failures. That is, the branch of processprefabort. The content of this branch is the same as that of dataabort, so I will not repeat it.
2-6 exception distribution commonhandler
so far, we have understood WindowsCE's basic understanding of the handling situation in various exception/interrupt modes, but some situations are still sent to commonhandler for processing, next we will analyze this distribution program and complete WindowsCE's handling of the entire abnormal process.
alternate_entry commonhandler
Mrs R2, spsr
MSR cpsr_c, # svc_mode: or: 0x80; Switch to supervisor Mode w/irqs disabled
LDR R3, = kdata; (r3) = PTR to kdata page
when the commonhandler starts, the system is transferred to the supervisor state for execution.
; Save the processor state into a thread structure. If the previous state was
; User or system and the kernel isn' t busy, then save the state into the current
; Thread. Otherwise, create a temporary thread structure on the kernel stack.
;
; (R1) = Exception ID
; (R2) = spsr
; (R3) = PTR to kdata page
; Interrupted r0-r3, and PC saved at (r3-0x14)
; In supervisor mode.
Alternate_entry saveandreschedule
And r0, R2, # 0x1f; (R0) = previous Mode
CMP r0, # user_mode; 'Z' set if from user mode
Cmpne r0, # system_mode; 'Z' set if from System Mode
BNE % F50; reentering kernel, save state on Stack
Field Protection Branch
; Whether the mode is user and system state before an exception occurs. FIQ/IRQ/svc/abort/UNDEF
LDR r0, [R3, # pcurthd]; (R0) = PTR to current thread
; R0 = kdata + pcurthd
Add r0, R0, # tcxr4; (R0) = PTR to R4 save
; R0 = kdata + pcurthd + tcxr4
; 0x44bytes after thread_context_offset is used to back up the register content
Stmia r0, {r4-r14} ^; Save User bank registers
**************************************** ************
; Save registers for fault from a non-preemptible state.
50 sub sp, SP, # tcxsizeof; Allocate space for temp. Thread Structure
CMP r0, # svc_mode
BNE % f55; must mode switch to save state
Add r0, SP, # tcxr4; (R0) = PTR to R4 save Area
Stmia r0, {r4-r14}; save SVC State registers
Add R4, SP, # tcxsizeof; (R4) = old SVC Stack pointer
STR R4, [r0, # TcxSp-TcxR4]; update Stack pointer Value
B % B10
55
msr cpsr, R2; Switch to mode exception came from
Add r0, SP, # tcxr4; (R0) = PTR to R4 save area
stmia r0, {r4-r14 }; save mode's register state
MSR cpsr_c, # svc_mode: Or: 0x80; Back to supervisor mode
B % B10; go save remaining State
Before unified processing, you need to save the status of the former State Register group for subsequent recovery. In the case of user State and system state, you can directly Save the user State Register. At the same time, we can see that the condition for reaching 50 is that the previous status is FIQ/IRQ/svc/abort/UNDEF, that is, the exception is nested, system nesting has been handled before. The first thing to handle is the case where the SVC is nested. The above shows that the SVC mode is used for handling specific events after exceptions/interruptions (eg: handleexception ), therefore, this process does not exist independently. Therefore, the current Register is the former State Register. Therefore, you need to recalculate the stack pointer position here. In other FIQ/IRQ/abort/UNDEF mode, you need to switch the current status to save the registers, therefore, before entering the real processing program, different branches are required to save the status of the former State Register. But why can't we see the registers saved in system mode before and after? This is because the system state and user State use the same set of registers, so saving the user State Register group achieves on-site protection. This design is entirely determined by the arm grouping register architecture, so different processing is required. Through the above processing, all the situations have completed the on-site protection operations in a unified manner. Next we need to further handle these exceptions.
10 ldmdb R3, {r3-r7}; load saved r0-r3 & PC
; 16 bytes before kdata is used for passing Parameters
So each exception handle is finally sent to this location by the r0-r3 and PC.
Analytic dB R0 !, {R2-r6}; save PSR, r0-r3
Sub r0, R0, # thread_context_offset; (R0) = PTR to thread struct
STR R7, [r0, # tcxpc]; save PC
Mfc15 R2, C6; (R2) = fault address
Mfc15 R3, C5; (r3) = fault status
; R0 = & kdata
; R1 = Exception ID
; R2 = far
; R3 = FSR
; Process an exception or reschedule request.
Firstschedule
20 MSR cpsr_c, # svc_mode; Enable interrupts
Call handleexception
LDR R2, [r0, # tcxpsr]; (R2) = Target status
And R1, R2, # 0x1f; (R1) = Target mode
CMP R1, # user_mode
Cmpne R1, # system_mode
BNE % f30; not going back to user or System Mode
; System mode and user mode Branch
Add r0, R0, # tcxr3
Ldmia r0, {r3-r14} ^; reload user/system mode registers
LDR R1, = kdata
MSR cpsr_c, # svc_mode: Or: 0x80; disable all interrupts
Ldrb R1, [R1, # bresched]; (R1) = nest LEVEL + reschedule flag
CMP R1, #1
MoV R1, # id_reschedule
Beq % B20; interrupted, reschedule again
MSR spsr, r2
Ldr lr, [r0, # TcxPc-TcxR3]
Ldmdb r0, {r0-r2}
Movs PC, LR; return to user or System Mode
Handleexception is a function for exception handling. It further analyzes and processes the exceptions that have not been processed. This function is not publicCodeSo there is no way to go further. Due to the large number of exception handling types, the code of this exception handling function is quite large, so it will consume a relatively large number of clock cycles, in the previous code, we performed exception handling when the interrupt is disabled. If the interrupt is not enabled here, the entire exception handling process will be quite long, this will greatly affect the system's real-time performance. Therefore, before handleexception is called, the interrupt is re-opened, and the interrupt is closed after processing is complete. If these exceptions cannot be handled, there are only two situations: 1. End the process/thread. 2. Suspend the system. In the second case, the handleexception of the system will not be returned. Therefore, only the normal process of exception handling and the possibility of terminating the thread. In this case, if the address that triggers the exception is returned to continue running, it will still cause an exception. Therefore, the End Process/thread must be rescheduled to complete the process. If the Exception Processing is successful, you do not have to schedule it. You can directly return the exception and continue the execution. Here, we also need to consider the case of nesting (here only refers to the exception nesting in both the system mode and the concurrency mode), that is, the interruption/exception has already entered the scheduling status and again causes the interruption/exception, at this time, the last scheduling is forcibly canceled and then rescheduled. this is used for exception recovery and deprivation during scheduling. If this is not the case, the register status will be restored directly and the breakpoint will be returned for further execution.
; Return to a non-preemptible privileged mode.
;
; (R0) = PTR to thread structure
; (R2) = Target mode
30 msr cpsr, R2; Switch to target mode
Add r0, R0, # tcxr0
Ldmia r0, {r0-r15}; Reload all registers & Return
After handleexception processing, all exceptions have been processed, so here we only consider the case of reverse return. Because this does not include processing in the user mode, all exceptions are processed in the privileged mode, you can access the kdata region. Here, you can use the thread backup in the kdata region to recover registers and return data.