内核启动阶段获得dtb位置指针过程

发布时间 2023-06-19 18:35:59作者: caseyzz

一.内核启动阶段获得dtb位置指针

arm64为例,内核启动如下:/arch/arm64/kernel/head.S

	__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
...

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

x0寄存器保存的是dtb里blob块的物理地址,x0寄存器内容由uboot设置,uboot将dtb地址传递给内核,跳转到stext,如下:

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
  bl	__cpu_setup			// initialise processor
  b	__primary_switch
ENDPROC(stext)
...
preserve_boot_args:
  mov	x21, x0				// x21=FDT

  adr_l	x0, boot_args		// record the contents of
  stp	x21, x1, [x0]			// x0 .. x3 at kernel entry
  stp	x2, x3, [x0, #16]

  dmb	sy				// needed before dc ivac with
            // MMU off

  add	x1, x0, #0x20		// 4 x 8 bytes
  b	__inval_cache_range	// tail call
ENDPROC(preserve_boot_args)

arm64 linux寄存器规定如下: