世界快资讯:RISC-VLinux汇编启动过程分析
/* 关闭所有中断 */ csrw CSR_IE, zero csrw CSR_IP, zero
/* 加载全局指针gp */.option push.option norelax la gp, __global_pointer$.option pop
/* 禁用 FPU 以检测内核空间中浮点的非法使用*/ li t0, SR_FS csrc CSR_STATUS, t0
/* 选择一个核启动 */ la a3, hart_lottery li a2, 1 amoadd.w a3, a2, (a3) bnez a3, .Lsecondary_start
/* 清除bss */ la a3, __bss_start la a4, __bss_stop ble a4, a3, clear_bss_done
/* 保存hatr id和dtb地址,hart id保存到a0,dtb地址保存到a1 */ mv s0, a0 mv s1, a1 la a2, boot_cpu_hartid
la sp, init_thread_union + THREAD_SIZE
mv a0, s1 call setup_vm // 跳转到C函数setup_vm,setup_vm会创建临时页表
#ifdef CONFIG_MMU la a0, early_pg_dir call relocate//重定向,实际就是开启MMU#endif
call setup_trap_vector/* 重载C环境 */ la tp, init_task sw zero, TASK_TI_CPU(tp) la sp, init_thread_union + THREAD_SIZE
tail start_kernel
完整_start_kernel汇编代码:
ENTRY(_start_kernel)/* 关闭所有中断 */csrw CSR_IE, zerocsrw CSR_IP, zero/* 在源码中,这里有一个M模式处理的宏,这里没有用到,直接跳过*//* 加载全局指针gp */.option push.option norelaxla gp, __global_pointer$.option pop/* 禁用 FPU 以检测内核空间中浮点的非法使用*/li t0, SR_FScsrc CSR_STATUS, t0#ifdef CONFIG_SMPli t0, CONFIG_NR_CPUSblt a0, t0, .Lgood_corestail .Lsecondary_park.Lgood_cores:#endif/* 选择一个核启动 */la a3, hart_lotteryli a2, 1amoadd.w a3, a2, (a3)bnez a3, .Lsecondary_start/* 清除bss */la a3, __bss_startla a4, __bss_stopble a4, a3, clear_bss_doneclear_bss:REG_S zero, (a3)add a3, a3, RISCV_SZPTRblt a3, a4, clear_bssclear_bss_done:/* 保存hatr id和dtb地址,hart id保存到a0,dtb地址保存到a1 */mv s0, a0mv s1, a1la a2, boot_cpu_hartidREG_S a0, (a2)/* 初始化页表,然后重定向到虚拟地址 */la sp, init_thread_union + THREAD_SIZEmv a0, s1call setup_vm // 跳转到C函数setup_vm,setup_vm会创建临时页表#ifdef CONFIG_MMUla a0, early_pg_dircall relocate//重定向,实际就是开启MMU#endif /* CONFIG_MMU */call setup_trap_vector/* 重载C环境 */la tp, init_tasksw zero, TASK_TI_CPU(tp)la sp, init_thread_union + THREAD_SIZE#ifdef CONFIG_KASANcall kasan_early_init#endif/* Start the kernel */call soc_early_inittail start_kernel//跳转到C函数start_kernel,开始C语言部分初始化
汇编中非常重要的一个部分就是页表的创建,关乎着后面的程序能不能继续往下跑。setup_vm创建页表后就会开始执行relocate重定向,这个重定向主要开启mmu,下面分析relocate的汇编。
relocate
relocate重定向,就是在开启mmu。开启mmu的操作就是将一级页表的地址以及权限写到satp
寄存器中,这就算开启mmu了。
(资料图片)
#ifdef CONFIG_MMU la a0, early_pg_dir //跳转到relocate前,先把第一级页表early_pg_dir的地址存入a0 call relocate//跳转到relocate,开启MMU#endif
relocate有两次开启mmu的操作,第一次开启mmu使用的是setup_vm()
建立的trampoline_gd_dir
页表,这页表保存的是kernel
的前2M
内存。第二次开启MMU使用的是early_pg_dir
页表,这个页表映射了整个kernel内存以及dtb
的4M空间。
如果trampoline_pg_dir
或者early_pg_dir
这两个页表的映射没弄好的话,开启MMU的时候就会失败,所以页表的建立十分关键。页表创建后续再深究,下面分析relocate汇编代码。
/* Relocate return address */li a1, PAGE_OFFSETla a2, _startsub a1, a1, a2add ra, ra, a1
/* Point stvec to virtual address of intruction after satp write */la a2, 1fadd a2, a2, a1csrw CSR_TVEC, a2
再进入relocate之前,就已经把early_pg_dir赋值给a0了,所以a0是early_pg_dir。srl是逻辑右移,mmu使用的是sv39,虚拟地址39位,物理地址56位:
低12位是偏移量,所以PAGE_SHIFT
等于12,将early_pg_dir
地址右移12位存到a2
。根据satp寄存器定义:
MODE
等于0x8
代表使用sv39 mmu
,0x0
代表不进行地址翻译,即不开启MMU
。这里STAP_MODE
为sv39
,即0x8
。将early_pg_dir
地址和SATP_MODE
进行或运算后,即可得到写入satp
寄存器的值,最后保存到a2
。
/* Compute satp for kernel page tables, but don"t load it yet */srl a2, a0, PAGE_SHIFTli a1, SATP_MODE//sv39 mmuor a2, a2, a1
satp
值的计算和上述是一样的。开启MMU
之前,通过sfence.vma
命令先刷新TLB
。此时开启MMU
,就会进入下面的标号为1
的汇编段
la a0, trampoline_pg_dirsrl a0, a0, PAGE_SHIFTor a0, a0, a1sfence.vmacsrw CSR_SATP, a0
进入异常1f
段,重新设置异常入口为.Lsecondary_park
,然后切换到early_pg_dir
页表,相当于第二次开启MMU。此时,如果之前建立的early_pg_dir
页表不对,则会就进入.Lsecondary_park
。.Lsecondary_park
里面是个wfi
指令,是个死循环。
完整relocate汇编代码:
relocate:/* Relocate return address */li a1, PAGE_OFFSETla a2, _startsub a1, a1, a2add ra, ra, a1/* Point stvec to virtual address of intruction after satp write */la a2, 1fadd a2, a2, a1csrw CSR_TVEC, a2/* Compute satp for kernel page tables, but don"t load it yet */srl a2, a0, PAGE_SHIFTli a1, SATP_MODEor a2, a2, a1/* * Load trampoline page directory, which will cause us to trap to * stvec if VA != PA, or simply fall through if VA == PA. We need a * full fence here because setup_vm() just wrote these PTEs and we need * to ensure the new translations are in use. */la a0, trampoline_pg_dirsrl a0, a0, PAGE_SHIFTor a0, a0, a1sfence.vmacsrw CSR_SATP, a0.align 21:/* Set trap vector to spin forever to help debug */la a0, .Lsecondary_parkcsrw CSR_TVEC, a0/* Reload the global pointer */.option push.option norelaxla gp, __global_pointer$.option pop/* * Switch to kernel page tables. A full fence is necessary in order to * avoid using the trampoline translations, which are only correct for * the first superpage. Fetching the fence is guarnteed to work * because that first superpage is translated the same way. */csrw CSR_SATP, a2sfence.vmaret
总结
以上就是RISC-V Linux的汇编启动流程,虽说RISC-V的指令不复杂,但要理解这个汇编启动的部分,还是需要一点基础和时间。另外,大多数人工作中基本用不上汇编,只有真正用上了理解才会比较深。
标签:
- 世界快资讯:RISC-VLinux汇编启动过程分析
- 舞狮运动分为哪几种 舞狮运动分为哪几种类型
- 48伏20安的电瓶车能跑多远(电瓶车48伏20安能跑多远)
- 银行最近四大反常行为,透露一个重要信号,存钱的要知道|全球百事通
- 记者:青岛海牛对阵国安一票难求,青春足球场上座人数有望超3万 焦点观察
- 环球关注:观想科技2022年净利降7成 2021年上市一创投行保荐
- 在车里体验Hi-end的声音——丹拿车载音响体验
- 李陵投降匈奴后结婚生子,后代发展成一个国家,主动与唐朝认亲
- 新增备案专业1641个,今年高校本科专业调整有哪些亮点? 当前速读
- 江苏一季度实现生产总值29401.7亿元,同比增长4.7%
- 台湾食药署发布边境查验不合格进口食品名单(4月25日) 环球热点评
- 去年中国境内举办经贸类展览1807个
- 环球快看点丨过过过!四六级加考,25日查分
- 去年青海完成国土绿化525.5万亩 完成防沙治沙127.46万亩|环球热消息
- 热资讯!多数券商完成深蹲起跳 “券茅”逆势下滑
- 锂电池板块多股一季报业绩暴雷 长远锂科开盘大跌13%
- 焦点热门:非遗的无为与有为
- Ruinarch撒旦驾到成就怎么解锁
- 今日最新!福建省第十届少数民族传统体育运动会在南平启幕
- 已婚已育双休未婚单休 合理吗?
- 广西师范大学来山东师范大学考察交流 焦点观察
- 环球关注:完美世界4月25日快速回调
- 【环球聚看点】“MBTI式社交”引爆年轻人朋友圈
- 全球快消息!微软敲定Win10一年两更策略春季上新功能秋季主优化
- 环球快资讯丨欧阳狂生(关于欧阳狂生介绍)
- 天天报道:着力培养高素质乡土人才
- 消费呈现恢复向好态势(经济新方位·首季数据观察)|世界时讯
- 青少年心理健康评估系统升级 区块链算法加密个人隐私 观点
- 焦点关注:如何悬挂立方体货架
- 使用数字人民币发的工资,是种什么体验?