linux-2.6.22.6 Kernel boot analysis Head.s boot segment Code

Source: Internet
Author: User

Learning Goals:

Learn about Arch/arm/kernel/head. s functions implemented as the first file launched by the kernel!

The previous analysis of the kernel makefile, you can know arch/arm/kernel/head. S is the first file that the kernel starts. In addition, when U-boot calls the kernel, the R1 Register Stores "machine type ID", which is used by the kernel.

Open Arch/arm/kernel/head. s file, you can see that the Stext function is the kernel entry function with the following function:

 the. Section". Text.head","Ax/ * defines a. Text.head segment, the segment's attribute A is the allowed segment, X is executable *  / the. Type Stext,%function/ * Defines the entry functions u-boot into the kernel * / + ENTRY (stext)/* Ingress address stext function */ -MSR Cpsr_c, #PSR_F_BIT | Psr_i_bit | Svc_mode/* off interrupt, set CPU to work in admin mode */
the
BayiMRC P15,0, R9, C0, C0/* Get the ID of the CPU */
theBL __lookup_processor_type/* Call function, input parameter r9=cpuid, return value R5=procinfo */
theMovs R10, R5/* Does not support the current CPU, the return value r5=0 */ -BEQ __error_p/* If r5=0, print error */ -BL __lookup_machine_type/* Call function, return value R5=machinfo */
theMovs R8, R5/* Does not support the current Development Board, return value R5=machinfo */ theBEQ __error_a/* If r5=0, print error */ theBL __create_page_tables/* Create page Table * /

Let's start by introducing the function that the entry function stext each statement to implement, and then analyze the __lookup_processor_type and __lookup_machine_type functions in detail:

Line 79th ensures that the processor enters management mode and disables interrupts by setting the CPSR register.

Line 81st reads the register C0 of the coprocessor CP15 to obtain the CPU ID.

Line 82nd calls the __lookup_processor_type function to detect if the kernel supports the current CPU. If supported, the R5 register returns an address to describe the processor structure, otherwise the value of R5 is 0.

Line 85th calls the __lookup_machine_type function to determine if the kernel supports the current Development Board. If supported, the R5 register returns an address to describe the structure of the Board, otherwise the value of R5 is 0.

If __lookup_processor_type, __lookup_machine_type have a return value of 0, the kernel cannot start, and if the kernel is configured to enable CONFIG_DEBUG_LL, error messages are also printed.

Before we introduce the two functions of __lookup_processor_type and __lookup_machine_type, we need to plug in some of the contents first. We briefly said earlier that __lookup_processor_type and __lookup_machine_type are used to detect whether the kernel supports the current architecture of the processor, whether the current Development Board is supported, and if the kernel wants to implement the detection function, Then the kernel will be sure to store its own supported processor architecture information and the supported Development Board information, the following first to find out how this information in the kernel is defined.

In the kernel, a number of pro_info_list structures are defined that represent the CPUs that it supports. For ARM architecture CPUs, the source code for these structures is in the arch/arm/mm/directory, such as proc-arm920. The following code in S, which represents the pro_info_list structure of the arm920 architecture CPU.

 448 . Section  " .proc.info.init  "  , #alloc, # Execinstr  449  450 . Type __arm920_ Proc_info,#object  451  __arm920_proc_info:  452 .    long  0x41009200/* CPU val */ 453 .    long  0xff00fff0/* CPU Mask */ 

Each processor architecture supported by the kernel has its own pro_info_list structure to hold its own CPU information, and the pro_info_list structures used by these different processors are defined in the ". Proc_info_init" segment. When the kernel is connected, these structures are organized together with a starting address of __proc_info_begin and an end address of __proc_info_end. You can see it from the connection script Arch/arm/kernel/vmlinux.lds.

 *    __proc_info_begin = .;          #.proc_info_init segment Start Address (connection program is dynamically determined)      *(. proc.info.init)notoginseng    __proc_info_ end =.;            #.proc_info_init End address (dynamically determined when the program is connected)

Then look at how the kernel supports the Development Board information content, how it is defined and stored. Each supported development Board in the kernel uses macro Machine_start, machine_end to define a MACHINE_DESC structure that defines some properties and functions related to the board, such as machine ID, start I/O Physical address, Bootloader the address of the incoming parameter, the interrupt initialization function, and so on. For example, the SMDK2410 Development Board, defined in the arch/arm/mach-sc32410/mach-smdk2410.c.

198Machine_start (SMDK2410,"SMDK2410")/*@TODO: Request a new identifier and switch199 * to SMDK2410*/ $     /*Maintainer:jonas Dietsche*/201. Phys_io =S3c2410_pa_uart,202. Io_pg_offst = (((u32) s3c24xx_va_uart) >> -) &0XFFFC,203. Boot_params = S3c2410_sdram_pa +0x100,204. Map_io =Smdk2410_map_io,205. INIT_IRQ =S3c24xx_init_irq,206. Init_machine =Smdk2410_init,207. Timer = &S3c24xx_timer,208Machine_end

In the kernel's include/asm/-arm/mach/arch.h file, find the 198th, 202 lines of the macro Machine_start, machine_end definition, the two macros are defined as follows:

 - #defineMachine_start (_type,_name)Wuyi Static Const structMachine_desc __mach_desc_# #_type the __used -__ATTRIBUTE__ ((__section__ (". Arch.info.init"))) = {     Wu. NR =mach_type_# #_type, -. Name =_name, About  $ #defineMachine_end -};

Following the macro definition above, the 198-row ~208 line code is expanded as follows:

Static Const structmachine_desc __mach_desc_smdk2410 __used __attribute__ (__section__ (". Arch.info.init"))) ={. nr=mach_type_smdk2410,. Name="SMDK2410",. Phys_io=S3c2410_pa_uart,. Io_pg_offst= (((u32) s3c24xx_va_uart) >> -) &0XFFFC,. Boot_params= S3c2410_sdram_pa +0x100,. Map_io=smdk2410_map_io,. Init_irq=S3c24xx_init_irq,. Init_machine=smdk2410_init,. Timer= &S3c24xx_timer,};

By expanding the code of the 198~208 line, you can see that the content defines a static constant of the Machine_desc type struct __mach_desc_smdk2410. The mach_type_smdk2410 is defined in Arch/arm/tools/mach-types, and finally the file is converted to a header file include/asm/arm/mach-type.h be contained by other files. The machine_des structure is defined in the Include/asm-arm/mach/arch.h file. The __attribute__ ((__section__ (". Arch.info.init")) statement means that all MACHINE_DESC structures are stored in the ". Arch.info.init" segment, and they are organized together when the kernel is connected. The start address is __arch_info_begin and the end address is __arch_info_end. You can see it from the connection script Arch/arm/kernel/vmlinux.lds.

 -   __arch_info_begin = .;                #.arch.info.init segment Start address (dynamically determined at connection time)     *(. arch.info.init)-   __arch_info_end = .;                  #.arch.info.init segment End address (dynamically determined when connected)

With the above-mentioned content as a cushion, the following __lookup_processor_type and __lookup_machine_type these two functions how to achieve their respective functional understanding will be more convenient. First look at the __lookup_processor_type function, in Arch/arm/kernel/head-common. The S file is defined as follows:

145 . Type __lookup_processor_type,%function146 __lookup_processor_type:147 ADR R3, 3f148 Ldmda R3, {R5-R7}149     SubR3, R3, R7 @ get offset between Virt&phys Max     AddR5, R5, R3 @ Convert virt addresses to151     AddR6, R6, R3 @ Physical Address space the 1: Ldmia R5, {r3, R4} @ value, Mask153      andR4, R4, R9 @ mask wanted bits154 TEQ R3, R4155 beq 2f156     AddR5, R5, #PROC_INFO_SZ @ sizeof (proc_info_list)157     CMPR5, R6158 Blo 1b159     movR5, #0@ Unknown Processor the 2:movPC, LR
176     . Long    __proc_info_begin177    . Long    __proc_info_end1783  :  . Long    . 179     . Long    __arch_info_begin     . Long    __arch_info_end

A physical address is used before the __enable_mmu function is called, but the kernel is linked with a virtual address. Therefore, before accessing the pro_info_list structure, the virtual address is converted to a physical address, and the above 147 lines of ~151 line is to achieve the above conversion.

Line 147th obtains 178 lines of physical address first. The ADR instruction is based on the PC register to calculate the address, at this time the MMU function is closed, the PC register is used in the physical address, so after "ADR r3,3f", the R3 is stored in 178 lines of code Physical address, the instruction 3f F is forward meaning, It means jumping to the back of the program (down).

Line 148th is used to get the data defined by row 176th ~178: __proc_info_begin, __pro_info_end, and ".". The first two variables are determined when the kernel is connected, they are virtual addresses, in front of the __proc_info_begin, we have made a detailed introduction to this, __pro_info_end, "." Represents the virtual address of the current code after the link is compiled. Ldmda R3, {r5-r7} instruction, reads 4 bytes of data from the source address [R3] into the register, every time the r3-4 is read, and after the instruction executes the R3 content is unchanged, the data stored to the register rule is low for the low register number, and the high address for the high register number.

The 149th line calculates the difference between the physical address and the virtual address, and the 150th to 151th calculates the physical address of the __pro_info_begin and __pro_info_end based on the difference.

The following code reads the first two members of the pro_info_list structure stored in the ". Proc_info_init" segment for each CPU architecture, judging whether Cpu_val equals R9&cpu_mask,r9 is the read head. Gets the CPU ID in S. If the comparison is equal, the kernel supports the current CPU and returns the structure address directly. Returns 0 if all pro_info_list structures in the ". Proc_info_init" segment do not support this CPU.

The 160th line is the child function call return statement.

Then we analyze the __lookup_machine_type function, and the same function is in Arch/arm/kernel/head-common. s file, whose code is as follows:

193 . Type __lookup_machine_type,%function194 __lookup_machine_type:195 ADR R3, 3b @address of 3b, Physical address196Ldmia R3, {r4, R5, r6} @r4 ="."virtual Address of 3b,r5=__arch_info_begin, R6=__arch_info_end197     SubR3, R3, r4 @ Get offset between Virt&phys198     AddR5, R5, R3 @ Convert virt addresses to199     AddR6, R6, R3 @ Physical Address space $ 1: LDR R3, [R5, #MACHINFO_TYPE] @ Get machine TYPE201 TEQ R3, r1 @ matches loader number?202 beq 2f @ found203     AddR5, R5, #SIZEOF_MACHINE_DESC @ Next Machine_desc204     CMPR5, R6205Blo 1b206     movR5, #0@ Unknown machine207 2:movPC, LR

Line 195th obtains 178 lines of physical address first. The ADR instruction is based on the PC register to calculate the address, at this time the MMU function is closed, the PC register is used in the physical address, so after "ADR r3,3f", the R3 is stored in the 178 lines of code Physical address, instruction 3b B is backward meaning, It means jumping to the front of the program (UP).

Line 196th is used to get the data defined by row 178th ~180: __arch_info_begin, __arch_info_end, and ".". The first two variables are determined when the kernel is connected, they are virtual addresses, in front of the __arch_info_begin, we have made a detailed introduction to this, __arch_info_end, "." Represents the virtual address of the current code after the link is compiled. Ldmia R3, {r5-r7} instruction, reads 4 bytes of data from the source address [R3] into the register, every time the r3+4 is read, and after the instruction executes the R3 content is unchanged, the data stored to the register rule is low for the low register number, and the high address for the high register number.

Line 197th calculates the difference between the physical address and the virtual address, and the 198th to 199th Line calculates the physical address of the __arch_info_begin, __arch_info_end, based on the difference.

The following code reads the machine type ID of each machine_des structure stored in the ". Arch_info_init" segment, judging whether the Uboot incoming machine ID (passed in through the R1 register) equals the machine type ID of the different machine_des structures stored in the kernel. If the comparison is equal, the kernel supports the current Development Board and returns the structure address directly. If the ". Arch_info_init" segment does not support the Development Board for all machine_des structures, it returns 0.

The No. 207 line is the child function call return statement.

If both the __lookup_processor_type and __lookup_machine_type functions return success, head. The s subsequent boot code will continue to execute. The __create_page_table function is used to create and page tables to establish a mapping of virtual addresses to physical addresses, which uses the proc_info_list structure returned by the __lookup_processer_type function. At the same time in the boot phase will enable the MMU, and finally call the Start_kernel function into the kernel to start the second phase.

Summary: The  Boot stage code does the following :
1, first check whether the kernel supports the current architecture processor, and then detect whether to support the current Development Board, if support to perform subsequent operations.
2. Set page table, enable MMU
3. Perform routine tasks prior to calling C function Start_kernel, including copying data segments, clearing BSS segments, etc.

linux-2.6.22.6 Kernel boot analysis Head.s boot segment Code

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.