直播网站,建设部网站被黑,移动宽带续费多少钱,网站建设外包合同模板TinyEMU源码分析之启动流程 1 始于0x10002 确定BBL入口点3 mentry.S执行过程4 启动流程小结 本文属于《
TinyEMU模拟器基础系列教程》之一#xff0c;欢迎查看其它文章。 本文中使用的代码#xff0c;均为伪代码#xff0c;删除了部分源码。 1 始于0x1000
我们沿着TinyEMU… TinyEMU源码分析之启动流程 1 始于0x10002 确定BBL入口点3 mentry.S执行过程4 启动流程小结 本文属于《
TinyEMU模拟器基础系列教程》之一欢迎查看其它文章。 本文中使用的代码均为伪代码删除了部分源码。 1 始于0x1000
我们沿着TinyEMU的启动流程依次讲解以便理解其启动原理。
整个虚拟机到底从哪里开始执行第一条指令呢
我们可以在glue函数的s-pc GET_PC()位置处打上断点查看第一条指令的PC。
static void no_inline glue(riscv_cpu_interp_x, XLEN)(RISCVCPUState *s, int n_cycles1)
{for(;;) {// 获取PCs-pc GET_PC(); addr s-pc;ptr (uint8_t *)(s-tlb_code[tlb_idx].mem_addend (uintptr_t)addr);code_ptr ptr;//根据PC获取一条指令机器码insn get_insn32(code_ptr); }
}可以发现第一条指令的PC为0x1000。 我们回顾一下《TinyEMU源码分析之虚拟机初始化》中介绍的5条指令。
auipc t0, jump_addr // t0 0x80000000
auipc a1, dtb // a1 PC
addi a1, a1, dtb // a1 a1 0x3c
csrr a0, mhartid // a0 mhartid
jalr zero, t0, jump_addr // PC t0这5条指令就是从0x1000内存地址开始存放的。 因此虚拟机可以确定
第1条指令从auipc t0, jump_addr开始执行第5条指令jalr zero, t0, jump_addr将PC设置为0x80000000因此第6条指令必然跳转到0x80000000处执行。
而0x80000000处我们存放的是BIOS/Bootloader这里是bbl64.bin因此0x80000000处为bbl64.bin的第一条指令入口点我们需要分析bbl64.bin的源码找到其入口点。
2 确定BBL入口点
bbl64.bin的源码包括2部分汇编文件与C文件。 汇编文件为riscv-pk\machine\mentry.S一般叫启动文件。 Bootloader的.s启动文件是汇编语言源代码文件通常用于嵌入式系统的启动过程。 这个文件包含了系统启动时的底层硬件初始化代码是用汇编语言编写的以便直接操作硬件寄存器完成必要的初始化工作。 在链接器的链接脚本.lds文件内会定义程序的入口点即程序的第一条可执行指令。 关于链接器脚本可参考《【裸机开发】链接脚本.lds文件的基本语法》。 因此编译器对.s和.c文件执行编译与链接后程序就可以从该入口点开始执行。 通常入口点就在汇编文件中这里就是mentry.S。
我们看链接脚本riscv-pk\bbl\bbl.lds如下 ENTRY(symbol)这里的symbol指的是符号表中的符号。汇编阶段会生成符号表符号表中的符号包括静态变量、全局变量、函数名等。这是将某一个符号symbol的值设为入口地址。
我们再看riscv-pk\machine\mentry.S如下 因此bbl.lds指定的入口点就是mentry.S中的reset_vector处。 即0x80000000处指令为j do_reset。
3 mentry.S执行过程
执行指令j do_reset跳转到do_reset地址后后续执行过程如下所示 汇编代码添加了注释比较简单主要有以下操作
主要是初始化x系列寄存器以及根据misa寄存器判断此外前面讲过的a0与a1寄存器值作为init_first_hart函数的入参保存异常向量表基址到mtvec寄存器准备栈指针sp最后跳转到riscv-pk\machine\minit.c中的init_first_hart函数进入到C代码阶段。
4 启动流程小结
在bbl64.bin执行完毕后进入运行OSkernel-riscv64.bin阶段。 上述启动流程可用下图来简要描述