OpenSBI初始化分析

OpenSBI初始化

启动流程:主要涉及三个阶段

  • .S汇编阶段,主要是Opensbi的底层初始化阶段,为C准备执行环境;
  • 设备初始化阶段,此阶段正式进入C环境;
  • 会跳转到二级 Bootloader,正式进入S模式;

OpenSBI底层初始化

确定启动的hart id

非启动hart转入_wait_relocate_copy_done等待启动hart初始化完成。
在fw_boot_hart中:fw_jump和fw_payload模式将a0返回为-1;fw_dynamic将根据a2中的dynamic_info去决定a0的值(-1或者为一个固定值,应该是设置的),a1值为2

 _start:
	/* Find preferred boot HART id */
	MOV_3R	s0, a0, s1, a1, s2, a2
	call	fw_boot_hart
	add	a6, a0, zero
	MOV_3R	a0, s0, a1, s1, a2, s2
	li	a7, -1
	beq	a6, a7, _try_lottery
	/* Jump to relocation wait loop if we are not boot hart */
	bne	a0, a6, _wait_relocate_copy_done
根据hart id执行重定位(lottery算法确定主hart)
_try_lottery:
	/* Jump to relocation wait loop if we don't get relocation lottery */
	la	a6, _relocate_lottery
	li	a7, 1
	amoadd.w a6, a7, (a6)
    /*_relocate_lottery不等于0,即跳到boot hart做重定位的地方。若多核一起启动执行,只有最先执行源自指令的a6是0,后续执行到这里的从核直接跳到重定位完成地址*/
	bnez	a6, _wait_relocate_copy_done  /*这里没抢到锁的核将到_wait_relocate_copy_done处循环*/

	/* Save load address */
	la	t0, _load_start
	la	t1, _start
	REG_S	t1, 0(t0)  //将_start指向_load_start
当加载地址和链接地址不相同时,需要进行重定位
	/* Relocate if load address != link address
    *   
    * 地址分布:
    * _link_start <-----t0
    *
    * _link_end <-----t1    
    *
    * _load_start <-----t2
    *
    * _load_end <-----t3
    *
    */
_relocate:
	la	t0, _link_start
	REG_L	t0, 0(t0)
	la	t1, _link_end
	REG_L	t1, 0(t1)
	la	t2, _load_start
	REG_L	t2, 0(t2)
	sub	t3, t1, t0
	add	t3, t3, t2
	beq	t0, t2, _relocate_done
	la	t4, _relocate_done
	sub	t4, t4, t2
	add	t4, t4, t0
	blt	t2, t0, _relocate_copy_to_upper

地址拷贝:首先要避免地址重叠,实际copy时需要区分copy到高地址或低地址,因此,copy始于地址开头或结尾的效果不同。若_load_start < _link_start,则需要往高地址拷贝数据。

_relocate_copy_to_upper:
    // load_end > link_start将存在地址重叠,将进入异常
	ble	t3, t0, _relocate_copy_to_upper_loop
	la	t2, _relocate_lottery
	BRANGE	t0, t3, t2, _start_hang
	la	t2, _boot_status
	BRANGE	t0, t3, t2, _start_hang
	la	t2, _relocate
	la	t5, _relocate_done
	BRANGE	t0, t3, t2, _start_hang
	BRANGE	t0, t3, t5, _start_hang
	BRANGE	t2, t5, t0, _start_hang

重定位的地址拷贝发生在_relocate_copy_to_upper_loop中,保证不发生重叠,所以从

_relocate_copy_to_upper_loop:
	add	t3, t3, -__SIZEOF_POINTER__
	add	t1, t1, -__SIZEOF_POINTER__
	REG_L	t2, 0(t3)
	REG_S	t2, 0(t1)
	blt	t0, t1, _relocate_copy_to_upper_loop
	jr	t4

低地址拷贝同理,方向与高地址相反

_relocate_copy_to_lower:
	ble	t1, t2, _relocate_copy_to_lower_loop
	la	t3, _relocate_lottery
	BRANGE	t2, t1, t3, _start_hang
	la	t3, _boot_status
	BRANGE	t2, t1, t3, _start_hang
	la	t3, _relocate
	la	t5, _relocate_done
	BRANGE	t2, t1, t3, _start_hang
	BRANGE	t2, t1, t5, _start_hang
	BRANGE  t3, t5, t2, _start_hang

_relocate_copy_to_lower_loop:
	REG_L	t3, 0(t2)
	REG_S	t3, 0(t0)
	add	t0, t0, __SIZEOF_POINTER__
	add	t2, t2, __SIZEOF_POINTER__
	blt	t0, t1, _relocate_copy_to_lower_loop
	jr	t4

再来看下非启动hart的动作:一直在等待启动hart的link_start和load_start相同,也就是_boot_status变为BOOT_STATUS_RELOCATE_DONE。接下来可以看到在几个nop指令后,非启动hart会跳转到_wait_for_boot_hart的链接地址,将继续等待启动hart完成其他的初始化工作。

_wait_relocate_copy_done:
	la	t0, _start
	la	t1, _link_start
	REG_L	t1, 0(t1)
    //若load adress与link address不同,表示重定位未完成
	beq	t0, t1, _wait_for_boot_hart
	la	t2, _boot_status
    //记录_wait_for_boot_hart的链接地址
	la	t3, _wait_for_boot_hart
	sub	t3, t3, t0
	add	t3, t3, t1
1:
	/* waitting for relocate copy done (_boot_status == 1) */
	li	t4, BOOT_STATUS_RELOCATE_DONE
	REG_L	t5, 0(t2)
	/* Reduce the bus traffic so that boot hart may proceed faster */
	nop
	nop
	nop
	bgt     t4, t5, 1b
	jr	t3
重定位结束:设置_boot_status为BOOT_STATUS_RELOCATE_DONE
_relocate_done:

	/*
	 * Mark relocate copy done
	 * Use _boot_status copy relative to the load address
	 */
	la	t0, _boot_status
	la	t1, _link_start
	REG_L	t1, 0(t1)
	la	t2, _load_start
	REG_L	t2, 0(t2)
	sub	t0, t0, t1
	add	t0, t0, t2

    /* 重定位完成,设置标志*/
	li	t1, BOOT_STATUS_RELOCATE_DONE
	REG_S	t1, 0(t0)
	fence	rw, rw

	/* At this point we are running from link address */

	/* Reset all registers for boot HART */
	li	ra, 0
	call	_reset_regs

	/* Zero-out BSS */
	la	s4, _bss_start
	la	s5, _bss_end
清除bss段,设置sp指针,8k的临时栈空间,以及scratch空间的构造
写状态寄存器CSR_MTVEC,保存发生异常时处理器需要跳转到的地址
设置sp寄存器,栈指针:栈空间为8k,向下生长
保存:a0~a4寄存器的值,用于fw_save_info,只有fw_dynamic的模式才会用到这些寄存器(因为暂时只有dynamic模式才会将这个结构体传向内核)
_bss_zero:
	REG_S	zero, (s4)
	add	s4, s4, __SIZEOF_POINTER__
	blt	s4, s5, _bss_zero

	/* Setup temporary trap handler */
	la	s4, _start_hang
	csrw	CSR_MTVEC, s4

	/* Setup temporary stack */
	la	s4, _fw_end
	li	s5, (SBI_SCRATCH_SIZE * 2)
	add	sp, s4, s5

	/* Allow main firmware 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值