设为首页 加入收藏

TOP

ARM64启动汇编和内存初始化(上) --- (一)(二)
2023-07-23 13:25:41 】 浏览:127
Tags:ARM64 ---
所有 CPU 都一致的值。如果在 EL1 模式下进入内核,则 CNTHCTL_EL2 中的 EL1PCTEN (bit 0) 必须置位。 - 一致性 通过内核启动的所有 CPU 在内核入口地址上必须处于相同的一致性域中。 这可能要根据具体实现来定义初始化过程,以使能每个CPU上对维护操作的 接收。 - 系统寄存器 在进入内核映像的异常级中,所有构架中可写的系统寄存器必须通过软件 在一个更高的异常级别下初始化,以防止在 未知 状态下运行。 对于拥有 GICv3 中断控制器并以 v3 模式运行的系统: - 如果 EL3 存在: ICC_SRE_EL3.Enable (位 3) 必须初始化为 0b1。 ICC_SRE_EL3.SRE (位 0) 必须初始化为 0b1。 - 若内核运行在 EL1: ICC_SRE_EL2.Enable (位 3) 必须初始化为 0b1。 ICC_SRE_EL2.SRE (位 0) 必须初始化为 0b1。 - 设备树(DT)或 ACPI 表必须描述一个 GICv3 中断控制器。 对于拥有 GICv3 中断控制器并以兼容(v2)模式运行的系统: - 如果 EL3 存在: ICC_SRE_EL3.SRE (位 0) 必须初始化为 0b0。 - 若内核运行在 EL1: ICC_SRE_EL2.SRE (位 0) 必须初始化为 0b0。 - 设备树(DT)或 ACPI 表必须描述一个 GICv2 中断控制器。

这里有个很关键的问题:为什么跳转到内核时指令高速缓存可以打开,数据高速缓存必须关闭?
(1)CPU启动取数据的时候首先去访问数据高速缓存,这个数据高速缓存有可能缓存了bootloader的数据,这个数据对于内核可能是错误的。因此数据高速缓存必须关闭。
(2)bootloader和内核的指令无冲突。因为bootloader指令运行完成后不会再次运行,直接运行内核的指令。因此指令高速缓存可以不关闭。

2. 启动汇编接口primary_entry分析

	/*
	 * The following callee saved general purpose registers are used on the
	 * primary lowlevel boot path:
	 *
	 *  Register   Scope                      Purpose
	 *  x21        primary_entry() .. start_kernel()        FDT pointer passed at boot in x0
	 *  x23        primary_entry() .. start_kernel()        physical misalignment/KASLR offset
	 *  x28        __create_page_tables()                   callee preserved temp register
	 *  x19/x20    __primary_switch()                       callee preserved temp registers
	 *  x24        __primary_switch() .. relocate_kernel()  current RELR displacement
	 */
SYM_CODE_START(primary_entry)
	bl	preserve_boot_args
	bl	init_kernel_el			// w0=cpu_boot_mode
	adrp	x23, __PHYS_OFFSET              --- '__PHYS_OFFSET加载到x23寄存器'
	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
SYM_CODE_END(primary_entry)

2.1 preserve_boot_args

??功能:把bootloader传进来的x0 .. x3保存到boot_args数组中。

/*
 * Preserve the arguments passed by the bootloader in x0 .. x3
 */
SYM_CODE_START_LOCAL(preserve_boot_args)
	mov	x21, x0				// x21=FDT(x0寄存器保存devicetree的地址),devicetree保存到x21寄存器
	adr_l	x0, boot_args			// record the contents of. boot_args数组地址保存到x0
	stp	x21, x1, [x0]			// x0 .. x3 at kernel entry
	stp	x2, x3, [x0, #16]                  '参数x0 .. x3保存到boot_args数组中'

	dmb	sy				// needed before dc ivac with.内存屏障指令(+sy表示全系统高速缓存范围内做一次内存屏障)
						// MMU off

	add	x1, x0, #0x20			// 4 x 8 bytes
	b	dcache_inval_poc		// tail call 清除boot_args数组对应的高速缓存
SYM_CODE_END(preserve_boot_args)

2.2 init_kernel_el

??判断启动的模式是EL2还是非安全模式的EL1,并进行相关级别的系统配置(ARMv8中EL2是hypervisor模式,EL1是标准的内核模式),然后使用w0返回启动模式(BOOT_CPU_MODE_EL1或BOOT_CPU_MODE_EL2)。通常来讲系统启动时运行在EL3,uboot会把处理器置于EL2,内核运行到init_kernel_el会设为EL1。

/*
 * Starting from EL2 or EL1, configure the CPU to execute at the highest
 * reachable EL supported by the kernel in a chosen default state. If dropping
 * from EL2 to EL1, configure EL2 before configuring EL1.
 *
 * Since we cannot always rely on ERET synchronizing writes to sysregs (e.g. if
 * SCTLR_ELx.EOS is clear), we place an ISB prior to ERET.
 *
 * Returns either BOOT_CPU_MODE_EL1 or BOOT_CPU_MODE_EL2 in w0 if
 * booted in EL1 or EL2 respectively.
 */
SYM_FUNC_START(init_kernel_el)
	mrs	x0, CurrentEL            '获取当前PSTATE异常等级'
	cmp	x0, #CurrentEL_EL2       
	b.eq	init_el2                 '如果PSTATE异常等级为EL2,则跳转到init_el2'

首页 上一页 1 2 3 4 5 6 7 下一页 尾页 2/8/8
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇沁恒 CH32V208(一): CH32V208WBU6.. 下一篇微控制器实时操作系统实践5选择IDE

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目