arm64_linux启动流程分析01_内核的入口

本次分析使用的linux内核的版本时 4.14.2, 读者可以自己下载了对照分析

首先看链接文件如下:

1
2
3
4
5
6
7
8
9
10
11
ENTRY(_text)
SECTIONS
{
.....省略部分无关内容....

. = KIMAGE_VADDR + TEXT_OFFSET;

.head.text : {
_text = .;
HEAD_TEXT
}

可以看到入口点在_text. 而_text是指向.head.text段的起始位置. 所以内核是从.head.text开始运行的. 那么这个段是写什么内容呢?

HEAD_TEXT是一个宏#define HEAD_TEXT *(.head.text)

arch/arm64/kernel/head.S中有

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
	__HEAD
_head:
/*
* DO NOT MODIFY. Image header expected by Linux boot-loaders.
*/
#ifdef CONFIG_EFI
/*
* This add instruction has no meaningful effect except that
* its opcode forms the magic "MZ" signature required by UEFI.
*/
add x13, x18, #0x16
b stext
#else
b stext // branch to kernel start, magic
.long 0 // reserved
#endif
...省略后面的内容...

所以对应到code, 内核是从_head开始运行的. 这个开始点放置了一个arm64 linux的header:

1
2
3
4
5
6
7
8
9
10
u32 code0;			/* Executable code */
u32 code1; /* Executable code */
u64 text_offset; /* Image load offset, little endian */
u64 image_size; /* Effective Image size, little endian */
u64 flags; /* kernel flags, little endian */
u64 res2 = 0; /* reserved */
u64 res3 = 0; /* reserved */
u64 res4 = 0; /* reserved */
u32 magic = 0x644d5241; /* Magic number, little endian, "ARM\x64" */
u32 res5; /* reserved (used for PE COFF offset) */

这个头的前两个位置放置的是可执行code

在开启UEFI支持时, add x13, x18, #0x16这个code实际上是为了满足EFI格式的”MZ”头. 如果使用UEFI来启动kernel, 会识别出来并走UEFI启动的流程, 如果是普通的启动过程如使用uboot的booti进行引导, 那么第一条指令就是一条dummy指令. 第二条就跳转到stext运行了.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ENTRY(stext)
bl preserve_boot_args
bl el2_setup // Drop to EL1, w0=cpu_boot_mode
adrp x23, __PHYS_OFFSET
and x23, x23, MIN_KIMG_ALIGN - 1 // KASLR offset, defaults to 0
bl set_cpu_boot_mode_flag
bl __create_page_tables
/*
* The following calls CPU setup code, see arch/arm64/mm/proc.S for
* details.
* On return, the CPU will be ready for the MMU to be turned on and
* the TCR will have been set.
*/
bl __cpu_setup // initialise processor
b __primary_switch
ENDPROC(stext)

这段代码就是内核启动是运行的初始化代码. 后面会分章节来详细描述.