This article analyzes the CPU usage based on linux2.4.19 source and PXA 270.
When the ARM Linux kernel is started, the kernel interruption exception vector table is initialized through the call relationship between start_kernel ()-> trap_init.
/* ARCH/ARM/kernel/traps. C */
Void _ init trap_init (void)
{
Extern void _ trap_init (unsigned long );
Unsigned long base = vectors_base ();
_ Trap_init (base );
If (base! = 0)
Oopsprintk (kern_debug "relocating machine vectors to 0x % 08lx/N", base );
# Ifdef config_cpu_32
Modify_domain (domain_user, domain_client );
# Endif
}
Vectors_base is a macro used to obtain the address of the arm exception vector. This macro is defined in include/ARCH/ASM-arm/proc-armv/system. h:
Extern unsigned long cr_no_alignment;/* defined in entry-armv.S */
Extern unsigned long cr_alignment;/* defined in entry-armv.S */
# If _ linux_arm_arch _> = 4
# Define vectors_base () (cr_alignment & cr_v )? 0xffff0000: 0)
# Else
# Define vectors_base () (0)
# Endif
For versions earlier than armv4, the address is fixed to 0; For armv4 and later versions, the address of the arm abnormal vector table is subject to the C1 register of the coprocessor CP15.
(Control
In register), the V bit (bit [13]) is controlled. If v = 1, the address of the abnormal vector table is 0x00000000 ~ 0x0000001c; If V = 0
0xffff0000 ~ 0xffff001c. (For details, see ARM architecture reference manual)
The following analyzes the cr_alginment value which is determined, we find the definition of cr_alignment in arch/ARM/kernel/entry-armv.S:
. Globl symbol_name (cr_alignment)
. Globl symbol_name (cr_no_alignment)
Symbol_name (cr_alignment ):
. Space 4
Symbol_name (cr_no_alignment ):
. Space 4
Friends who have analyzed the head-armv.S file will know that the head-armv.S is not the entrance to the compressed kernel:
1. Section ". Text. init", # alloc, # execinstr
2. Type stext, # Function
3 entry (stext)
4 mov R12, R0
5
6 mov r0, # f_bit | I _bit | mode_svc @ Make sure SVC Mode
7 MSR cpsr_c, R0 @ and all irqs disabled
8 BL _ lookup_processor_type
9 TEQ R10, #0 @ invalid processor?
10 moveq r0, # 'P' @ Yes, error 'P'
11 beq _ Error
12 BL _ lookup_ubunture_type
13 TEQ R7, #0 @ invalid architecture?
14 moveq r0, # 'A' @ Yes, error 'A'
15 beq _ Error
16 BL _ create_page_tables
17 adr lr, _ RET @ return address
18 Add PC, R10, #12 @ initialise Processor
19 @ (return control REG)
20
21. Type _ switch_data, % object
22 _ switch_data:. Long _ mmap_switched
23. Long symbol_name (_ bss_start)
24. Long symbol_name (_ end)
25. Long symbol_name (processor_id)
26. Long symbol_name (_ machine_arch_type)
27. Long symbol_name (cr_alignment)
28. Long symbol_name (init_task_union) plus 8192
29
30. Type _ ret, % Function
31 _ RET: ldr lr, _ switch_data
32 MCR P15, 0, R0, C1, C0
33 MRC P15, 0, R0, C1, C0, 0 @ read it back.
34 mov r0, R0
35 mov r0, R0
36 mov PC, LR
Here, we are concerned about placing LR at the beginning of line 17 and line 17 code as the relative address at the _ RET label, so that we can jump to line 31 to continue running when returning somewhere in the future;
Line 18, for the PXA270 platform I analyzed, it will be jump to arch/ARM/MM/proc-xscale.S to execute the _ xscale_setup function,
In _ xscale_setup, the control of CP15 is read.
The value of register (C1) is sent to the R1 register, and the corresponding flag bit (including setting V bit = 1) is set in the R1 register, but in _ xscale_setup, R1 stores
Is not immediately written back to the control of CP15
In register, but somewhere after the return, it will be analyzed slowly. _ Xscale_setup calls move PC, and the LR command returns 31 lines to jump.
Line 31: Place _ mmap_switched in _ switch_data In the LR register. In line 36, the program jumps to _ mmap_switched.
Rows 32 and 33 write the values in the R0 register back to control register (C1) of CP15, and then read the values in the R0.
Next, let's take a look at the code jump to _ mmap_switched:
40_mmap_switched:
41 ADR R3, _ switch_data + 4
42 ldmia R3, {R4, R5, R6, R7, R8, SP} @ r2 = compat
43 @ sp = Stack pointer
44
45 mov FP, #0 @ clear BSS (and zero FP)
46 1: CMP R4, R5
47 strcc FP, [R4], #4
48 BCC 1b
49
50 STR R9, [R6] @ save processor ID
51 STR R1, [R7] @ save Machine Type
52 Bic R2, R0, #2 @ clear 'A' bit
53 stmia R8, {r0, R2} @ save control register values
54 B symbol_name (start_kernel)
41 ~ The result of row 42 is: R4 =__ bss_start, R5 =__ end,..., R8 = cr_alignment,.... Here R8 stores the address of the cr_alignment variable.
In row 53, since R0 saved the value of control register (C1) of CP15, the R0 value is written to the address pointed to by R8, that is, cr_alignment = r0, we can see the cr_alignment value assignment process clearly.
Let's return to the trap_init () function. After the above analysis, we know that vectors_base returns 0xffff0000. Function _ trap_init is compiled by assembly code in arch/ARM/kernel/entry-arm.S:
. Align 5
_ Stubs_start:
Vector_irq:
...
Vector_data:
....
Vector_prefetch:
...
Vector_undefinstr:
...
Vector_fiq: disable_fiq
Subs PC, LR, #4
Vector_addrexcptn:
B vector_addrexcptn
...
_ Stubs_end:
. Equ _ real_stubs_start,. lcvectors + 0x200
. Lcvectors: SWI sys_error0
B _ real_stubs_start + (vector_undefinstr-_ stubs_start)
Ldr pc, _ real_stubs_start + (. lcvswi-_ stubs_start)
B _ real_stubs_start + (vector_prefetch-_ stubs_start)
B _ real_stubs_start + (vector_data-_ stubs_start)
B _ real_stubs_start + (vector_addrexcptn-_ stubs_start)
B _ real_stubs_start + (vector_irq-_ stubs_start)
B _ real_stubs_start + (vector_fiq-_ stubs_start)
Entry (_ trap_init)
Stmfd SP !, {R4-R6, LR}/* Pressure stack, save data */
/* Copy the abnormal vector table (. lcvectors start with 8 addresses) to the address pointed to by R0 (abnormal vector address). R0 is the parameter passed during the _ trap_init (base) function call, for more information, see atpcs */
ADR R1,. lcvectors @ set up the vectors
Ldmia R1, {R1, R2, R3, R4, R5, R6, IP, LR}
Stmia r0, {R1, R2, R3, R4, R5, R6, IP, LR}
/* Place the hash code at the 0x200 offset after the exception vector address, that is, _ stubs_start ~ Each Exception Handling Code between _ stubs_end */
Add R2, R0, #0x200
R0, _ stubs_start @ copy stubs to 0x200
ADR R1, _ stubs_end
1: LDR R3, [R0], #4
STR R3, [R2], #4
CMP r0, r1
BLT 1b
Loadregs (FD, SP !, {R4-R6, PC})/* outputs the stack and restores data. function _ trap_init returns */
The filled vector table of the _ trap_init function is as follows:
Code for handling Virtual Address exceptions
0xffff0000 reset SWI sys_error0
0xffff0004 undefined B _ real_stubs_start + (vector_undefinstr-_ stubs_start)
0xffff0008 software interrupt ldr pc, _ real_stubs_start + (. lcvswi-_ stubs_start)
0xffff000c command exception B _ real_stubs_start + (vector_prefetch-_ stubs_start)
0xffff0010 Data Exception B _ real_stubs_start + (vector_data-_ stubs_start)
0xffff0014 reserved B _ real_stubs_start + (vector_addrexcptn-_ stubs_start)
0xffff0018 irq B _ real_stubs_start + (vector_irq-_ stubs_start)
0xffff001c fiq B _ real_stubs_start + (vector_fiq-_ stubs_start)
When an exception occurs, the processor jumps to the starting vector of the corresponding 0xffff0000 to take the command, and then hashes the Exception Processing code through the B command. because the B command in arm is relatively redirected
Only the addressing range of +/-32 MB is available, SO _ stubs_start ~ The exception handling code between _ stubs_end is copied to the starting point of 0xffff0200.
You can directly use the B command to jump to the past, which is more efficient than using the absolute jump (LDR.
------------------------- References --------------------
1. Liu Yu, embedded system interface design and Linux driver development, Beijing University of Aeronautics and Astronautics Press, 2006.
2, ARM architecture reference manual, arm Limited, 2000.
Original article address
Http://hi.baidu.com/_%C5%CE%C8%FD%C4%EA_/blog/item/cceac934d9dd95b1d1a2d370.html