Overview of the linux kernel startup process details on an ARM processor
For ARM processors, the first file that the kernel launches is the head.S file under arc/arm/kernel. Of course, there is also this file under arc/arm/boot/compress. This file is slightly different from the above file. When zImage is to be generated when the compressed kernel is created, the latter is started. When the latter is different from the former, it is in front of it. The code is self-extracting, and the code behind is the same. Here we analyze the head.S file under arc/arm/kernel. When the work done by head.S is completed, it will jump to the start_kernel function in the init/ directory where main.c starts to fall.
The first stage
First intercept part of the head.S file and highlight the highlighted code.
ENTRY(stext)
Msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
@ and irqs disabled
Mrc p15, 0, r9, c0, c0 @ get processor id
Bl __lookup_processor_type @ r5=procinfo r9=cpuid
Movs r10, r5 @ invalid processor (r5=0)?
Beq __error_p @ yes, error 'p'
Bl __lookup_machine_type @ r5=machinfo
Movs r8, r5 @ invalid machine (r5=0)?
Beq __error_a @ yes, error 'a'
Bl __create_page_tables
/*
* The following calls CPU specific code in a position independent
* manner. See arch/arm/mm/proc-*.S for details. r10 = base of
* xxx_proc_info structure selected by __lookup_machine_type
* above. On return, the CPU will be ready for the MMU to be
* turned on, and r0 will hold the CPU control register value.
*/
Ldr r13, __switch_data @ address to jump to after
@ mmu has been enabled
Adr lr, __enable_mmu @ return (PIC) address
The first step is to execute __lookup_processor_type. This function checks the processor model. It reads the CPU model of your board and compares it with the processor supported by the kernel to see if it can handle it. This we do not care about its specific implementation process, because now the mainstream processor cores provide support.
The second step is to execute __lookup_machine_type. This function checks the model of the machine. It reads the machine ID passed in by your bootloader and compares it with the machine ID it can handle to see if it can be processed. The ID number of the kernel is defined in the MACH_TYPE_xxxx macro definition in the arc/arm/tool/mach_types file. How exactly does the kernel check if it is a machine it supports? Virtually every machine will have a data structure describing a particular machine in /arc/arm/mach-xxxx/smdk-xxxx.c file, as follows
MACHINE_START(S3C2440, "SMDK2440")
/* Maintainer: Ben Dooks <> */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.init_irq = s3c24xx_init_irq,
.map_io = smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.timer = &s3c24xx_timer,
MACHINE_END
MACHINE_START and MACHINE_END are actually expanded into a structure
#define MACHINE_START(_type,_name) \
Static const struct machine_desc __mach_desc_##_type \
__used \
__attribute__((__section__(".arch.info.init"))) = { \
.nr = MACH_TYPE_##_type, \
.name = _name,
#define MACHINE_END \
};
So the above data structure is expanded to
Static const struct machine_desc __mach_desc_S3C2440 \
__used \
__attribute__((__section__(".arch.info.init"))) = { \
.nr = MACH_TYPE_S3C2440, \
.name =†SMDK2440â€,};
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.init_irq = s3c24xx_init_irq,
.map_io = smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.timer = &s3c24xx_timer,
}
Each machine will have a machine_desc __mach_desc structure. The kernel compares the nr number of each machine_desc__mach_desc with the ID passed from the bootloader. If it is the same, the kernel thinks that the machine is supported, and the kernel will call the machine in a later job. The method in the machine_desc __mach_desc_ structure does some initialization work.
The third step is to create a level one page table.
The fourth step is to save the address of the function __switch_data in R13. After enabling mmu in the fourth step, it jumps to the function execution.
The fifth step is to execute __enable_mmu, which is to enable MMU. This function calls __turn_mmu_on function, and then let _turn_mmu_on pass the value assigned to R13 in the third step to the PC pointer (mov pc, r13). ), so the kernel starts jumping to the __switch_data function to start execution.
Let's look at the __switch_data function in arch/arm/kenel/head-common.S
__switch_data:
.long __mmap_switched
.long __data_loc @ r4
.long __data_start @ r5
.long __bss_start @ r6
.long _end @ r7
.long processor_id @ r4
.long __machine_arch_type @ r5
.long cr_alignment @ r6
.long init_thread_union + THREAD_START_SP @ sp
/*
* The following fragment of code is executed with the MMU on in MMU mode,
* and uses absolute addresses; this is not position independent.
*
* r0 = cp#15 control register
* r1 = machine ID
* r9 = processor ID
*/
.type __mmap_switched, %function
__mmap_switched:
Adr r3, __switch_data + 4
Ldmia r3!, {r4, r5, r6, r7}
Cmp r4, r5 @ Copy data segment if needed
1: cmpne r5, r6
Ldrne fp, [r4], #4
Strne fp, [r5], #4
Bne 1b
Mov fp, #0 @ Clear BSS (and zero fp)
1: cmp r6, r7
Strcc fp, [r6],#4
Bcc 1b
Ldmia r3, {r4, r5, r6, sp}
Str r9, [r4] @ Save processor ID
Str r1, [r5] @ Save machine type
Bic r4, r0, #CR_A @ Clear 'A' bit
Stmia r6, {r0, r4} @ Save control register values
b start_kernel
The job of this function is to copy the data segment to the BBS segment, set the heap pointer, then save the processor core and machine kernel, and finally jump to the start_kernel function. Then the kernel started executing the second phase.
second stage
Let's take a look at the start_kernel function of main.c in the init/ directory. Here I've only taken a screenshot.
Asmlinkage void __init start_kernel(void)
{
.........................
..........................
Printk(KERN_NOTICE);
Printk(linux_banner);
Setup_arch(&command_line);
Setup_command_line(command_line);
Parse_early_param();
Parse_args("Booting kernel", static_command_line, __start___param,
__stop___param - __start___param,
&unknown_bootoption);
........................
..............................
init_IRQ();
Pidhash_init();
Init_timers();
Hrtimers_init();
Softirq_init();
Timekeeping_init();
Time_init();
Profile_init();
..............................
.................................
Console_init();
....................................
....................................
Ssssss;
}
From the above it can be seen that the start_kernel first prints the kernel information, then processes some parameters passed in by the bootloader, and then performs various initializations, in which the console is initialized. Eventually rest_init() is called; this function starts the mounted root file system and starts the init process.
In summary, the kernel startup process is roughly the following steps:
1. Check CPU and machine type
2. Initiate initialization of stack, MMU, and other programs that are critical to the operation
3. Print kernel information
4. Perform initialization of various modules
5. Mount the root file system
6. Start the first init process
Gaming All In One Pc,All In One Gaming Pc,All In One Pc I5 16Gb Ram,I7 All In One
Guangdong Elieken Electronic Technology Co.,Ltd. , https://www.elieken.com