本文以OpenSBI 0.9版本为参考进行讲解
现在分析sbi_init源码,进入sbi_init时,scratch是唯一的参数。在进入sbi_init前,每个cpu会把_trap_handler的地址设置到mtvec里面。
-
sbi_init函数
void __noreturn sbi_init(struct sbi_scratch *scratch)
{
bool next_mode_supported = FALSE;
bool coldboot = FALSE;
u32 hartid = current_hartid();
const struct sbi_platform *plat = sbi_platform_ptr(scratch);if ((SBI_HARTMASK_MAX_BITS <= hartid) || //hartid错误,超过了最大值,当前core 进入了wfi状态 sbi_platform_hart_invalid(plat, hartid)) sbi_hart_hang(); switch (scratch->next_mode) { case PRV_M: next_mode_supported = TRUE; break; case PRV_S: /* 对于jump模式,会走这里 */ if (misa_extension('S')) /* 查看当前模式是否支持 */ next_mode_supported = TRUE; break; case PRV_U: if (misa_extension('U')) next_mode_supported = TRUE; break; default: sbi_hart_hang(); } /* * Only the HART supporting privilege mode specified in the * scratch->next_mode should be allowed to become the coldboot * HART because the coldboot HART will be directly jumping to * the next booting stage. * * We use a lottery mechanism to select coldboot HART among * HARTs which satisfy above condition. */ /* * atomic_xchg作用就是原子操作,设置coldboot_lottery新值返回旧值,第一次设置,设置的是1,返回的是0, * 所以说第一个设置的core就是负责boot的core,那么执行的就是coldboot,其他的core执行是warmboot * 下面约定主core就是负责coldboot的core,其他的是从core,主core不一定是core 0 */ if (next_mode_supported && atomic_xchg(&coldboot_lottery, 1) == 0) coldboot = TRUE; if (coldboot) /* 全局数据的初始化由主core完成,coldboot初始化的会比warmboot多,sbi的打印默认是由主core输出的,从core没有log */ init_coldboot(scratch, hartid); else /* 从core会在sbi_hsm_init->sbi_hsm_hart_wait里面wfi,直到被下一级boot唤醒,从core只初始化自己独有的数据或者寄存器 */ init_warmboot(scratch, hartid);}
-
init_coldboot(scratch, hartid);
static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
{
int rc;
unsigned long *init_count;
const struct sbi_platform *plat = sbi_platform_ptr(scratch);/* Note: This has to be first thing in coldboot init sequence */ /* 创建hartid_to_scratch_table映射表,也就是hart id和scrash内存绑定的表;记录last_hartid_having_scratch值,也就是core的最大值index(core count -1) */ rc = sbi_scratch_init(scratch); ------ 详见2.1 if (rc) sbi_hart_hang(); /* Note: This has to be second thing in coldboot init sequence */ /* * 初始化动态加载的镜像的模块,并把mem region注册到hartid_to_domain_table数组里面。 * 这里的mem region会在sbi_hart_pmp_configure中进行配置保护 * 这里注册了两个mem regions,一个是fw自己所占的内存,一个是任意的地址 */ rc = sbi_domain_init(scratch, hartid); if (rc) sbi_hart_hang(); /* * 每一个hart id的scrash内存里面,从SBI_SCRATCH_EXTRA_SPACE_OFFSET这个地方偏移开始申请__SIZEOF_POINTER__大小的内存,并memset为0 * 从core也会判断init_count_offset是否正确,内存是否分配成功 */ init_count_offset = sbi_scratch_alloc_offset(__SIZEOF_POINTER__, ---------------- 详见2.2 "INIT_COUNT"); if (!init_count_offset) sbi_hart_hang(); /* *每一个core申请hart data内存,并把每一个core的state设置为SBI_HART_STARTING,这个函数主从core都会调用, * 主core申请内存设置状态,从core在wfi,直到自己的state设置为SBI_HART_STARTING * hsm应该是hart state mechine的简写。 */ rc = sbi_hsm_init(scratch, hartid, TRUE); -------------------详见2.3 if (rc) sbi_hart_hang(); /* * 平台相关的早期的初始化,调用platform.c里面设置的回调函数:early_init,用户可以把需要初始化的

最低0.47元/天 解锁文章
575





