For head. s call, where __mmap_switched B start_kernel jumps to C to execute and never returns.
Register value when jumping to Start_kernel:
R0 = cp#15 Control Register
R1 = Machine ID
R2 = ATAGS/DTB pointer
R9 = Processor ID
Http://blog.chinaunix.net/uid-20451980-id-1945242.html
Linux kernel Analysis (ii)
Note: This article is for Stephen du original, reproduced please specify
Here we begin to explain Head-common. S of content. In addition, my order of instruction is done in the order of the source code rather than in the order of the function call, so the reader should pay attention to the function's entry and return address.
This defines the storage address of the ATAG data.
#define Atag_core 0x54410001
#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
This part head. s inside open MMU after execution. Here we begin preparing for C code preparation: Mainly the text section, the initialization of the data segment positioning! The structure of the initial kernel itself is roughly the same as the normal process, which is why it was written by the macro kernel!
__data_loc is the beginning of the text section of kernel.
__bss_start is the end of __data_loc and the beginning of the BSS section.
As you can see, kernel must prepare the text segment with the initialized data segment, which is not required for uninitialized data segments and stack segments! Just set the stack pointer and the heap start address just fine! So there's no definition of stack and heap after 22 lines!
. Type __switch_data,%object
__switch_data:
. Long __mmap_switched
A. Long __data_loc @ R4
. long __data_start @ R5
A. Long __bss_start @ r6
. Long _end @ R7
The memory location stores the processor ID, which is the contents of the R4 register, in case the subsequent code discards the contents of R4
Long processor_id @ R4
The memory location stores the machine type information and the contents of the R5 are dropped.
Long __machine_arch_type @ R5
This memory stores the Atag address pointer, which prevents R6 from being discarded.
Long __atags_pointer @ r6
. Long Cr_alignment @ R7
This memory location has the kernel stack & heap memory location information, as long as the PC pointer point here can execute C code!
Init_thread_union long + thread_start_sp @ SP
29
The previous code may be in nor flash to run in XIP mode (in fact, NAND flash can also XIP, but a bit technical barriers), but kernel code can not always run in Flash, the function will be kernel section of the Move and processing!
Type __mmap_switched,%function
__mmap_switched:
R3 ADR, __switch_data + 4//R3 point to __mmap_switched comment Error! R3 point to __data_loc!
Loading code snippets, initialization data segments, and uninitialized data segment addresses into R4~R7
Ldmia R3!,{r4, R5, R6, R7}//Load the function ' s addr into R4~r7;r3 point toprocessor_id
It is difficult to understand here that R4=__data_loc is the storage location of the physical upper segment (possibly in Flash rather than in RAM); R5=_data_start is the address of the data in memory, and if they are equal, it is not necessary to do copy in RAM. If it is not in RAM, do copy to make it run in memory!
R4 CMP, R5//CopyData segment if needed __data_start is the destination and __data_loc are thesrc!
Copy related actions
1:cmpne R5, R6//If__data_start and __data_loc are not the same start the transfer session
Ldrne FP,[R4], #4
Strne FP,[R5], #4
1b BNE
Clears uninitialized data segments, clears the block for C code execution
-mov fp, #0 @ Clear BSS (and Zero FP)
Wuyi 1:cmp R6, R7
STRCC FP, [R6], #4
1b Bcc
Performs a save operation. The most important thing here is the SP pointer loading! After the statement the SP has pointed to the kernel stack, the conditions for executing C code are ready (code snippet OK, initialization data segment OK, uninitialized data segment Ok,stackok)
Ldmia R3,{r4, R5, R6, R7, SP}
R9 str, [R4] @ Save Processor ID
R1 STR, [R5] @ Save Machine type
R2 str, [R6] @ Save atags pointer
R4 Bic, R0, #CR_A @Clear ' A ' bit
Stmia r7,{r0, R4} @Save control Register values
@Now We'll enter the world of Ccode and the MMU are on now!
Entry_for_c_call b
//b Start_kernel @For ARM start_kernel is defined in the init/main.c we'll never RETURNF Rom Start_kernel at all
144
145/*
146 * Read Processor ID Register (cp#15, CR0), Andlook up in the Linker-built
147 * Supported processor list. Note that Wecan ' t use the absolute addresses
148 * For the __proc_info lists since we aren ' trunning with the MMU on
149 * (and therefore, we is not in the correctaddress space). We have to
* Calculate the offset.
151 *
* R9 = CPUID
153 * Returns:
154 * R3, R4, R6 corrupted
155 * R5 = proc_info pointer inphysical address space
156 * R9 = CPUID (preserved)
157 */
158. Type __lookup_processor_type,%function
159 __lookup_processor_type:
R3 ADR, 3f
161 Ldmda R3, {R5-R7}
162 Sub R3, R3,R7 @ get offset between Virt&phys
163 add R5, R5,R3 @ convert virt addresses to
164 add R6, R6,R3 @ Physical address space
165 1:ldmia R5, {r3, r4} @ Value,mask
166 and R4, R4,R9 @ mask wanted bits
167 TEQ R3, R4
168 BEQ 2f
169 add R5, R5, #PROC_INFO_SZ @ sizeof (proc_info_list)
R5 CMP, R6
171 Blo 1b
172 mov R5, #0 @ Unknown processor
173 2:mov pc, LR
174
175/*
176 * This provides a C-API version of the abovefunction.
177 */
178 ENTRY (Lookup_processor_type)
179 Stmfd sp!, {r4-r7, R9, LR}
R9 mov, R0
181 BL __lookup_processor_type
182 mov r0, R5
183 Ldmfd sp!, {r4-r7, R9, PC}
184
185/*
186 * Look in and arch/arm/kernel/arch. [Ch]for
187 * More information about the __PROC_INFO and__arch_info structures.
188 */
189. Long __proc_info_begin
__proc_info_end long.
191 3:. Long.
192. Long __arch_info_begin
193. Long __arch_info_end
194
195/*
196 * Lookup Machine Architecture in thelinker-build List of architectures.
197 * Note that we can ' t use the absolute addressesfor the __arch_info
198 * Lists since we aren ' t running with the MMU in (and therefore, we are
199 * Not in the correct address space). Wehave to calculate the offset.
200 *
201 * R1 = machine architecture number
202 * Returns:
203 * R3, R4, R6 corrupted
204 * R5 = mach_info pointer in physicaladdress space
205 */
206. Type __lookup_machine_type,%function
207 __lookup_machine_type:
208 ADR R3, 3b
209 Ldmia R3, {r4, R5,R6}
R3 Sub, R3,R4 @ Get offset between Virt&phys
211 Add R5, R5,R3 @ convert virt addresses to
212 Add R6, R6,R3 @ Physical address space
213 1:LDR R3, [R5, #MACHINFO_TYPE] @ Get machine TYPE
214 TEQ R3, r1 @ matches loader number?
215 beq 2f @ found
216 Add R5, R5, #SIZEOF_MACHINE_DESC @ Next Machine_desc
217 CMP R5, R6
218 Blo 1b
219 mov R5, #0 @ Unknown machine
2:mov PC, LR
221
222/*
223 * This provides a C-API version of the abovefunction.
224 */
225 ENTRY (Lookup_machine_type)
226 Stmfd sp!, {R4-R6, LR}
227 mov r1, r0
228 BL __lookup_machine_type
229 mov r0, R5
Ldmfd sp!, {R4-R6, PC}
231
232/* Determine validity of the R2 atags pointer. The heuristic requires
233 * That the pointer is aligned, in the first 16kof physical RAM and
234 * The Atag_core marker is first andpresent. Future revisions
235 * of this function is more lenient with thephysical address and
236 * May also is able to move the atags block ifnecessary.
237 *
238 * r8 = Machinfo
239 *
* Returns:
241 * R2 Either valid atags pointer, or zero
242 * R5, R6 corrupted
243 */
244
245. Type __vet_atags,%function
246 __vet_atags:
247 TST R2, #0x3 @ aligned?
248 BNE 1f
249
R5,[r2 Ldr, #0] @is first tag atag_core?
251 Subs R5, R5, #ATAG_CORE_SIZE
252 BNE 1f
253 Ldr R5,[r2, #4]
254 Ldr R6,=atag_core
255 CMP R5, R6
1f BNE
257
258 mov pc, LR @ atag pointer is ok
259
260 1:mov R2, #0
261 mov pc, LR
Linux head-common.s analysis (RPM)